blob: 44029cdd9bb73725d60d607efb8636099ea4d564 [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
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003783 public final void activityPaused(IBinder token) {
3784 final long origId = Binder.clearCallingIdentity();
3785 mMainStack.activityPaused(token, false);
3786 Binder.restoreCallingIdentity(origId);
3787 }
3788
3789 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3790 CharSequence description) {
3791 if (localLOGV) Slog.v(
3792 TAG, "Activity stopped: token=" + token);
3793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 // Refuse possible leaked file descriptors
3795 if (icicle != null && icicle.hasFileDescriptors()) {
3796 throw new IllegalArgumentException("File descriptors passed in Bundle");
3797 }
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);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003807 r.icicle = icicle;
3808 r.haveState = true;
3809 if (thumbnail != null) {
3810 r.thumbnail = thumbnail;
3811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003812 r.description = description;
3813 r.stopped = true;
3814 r.state = ActivityState.STOPPED;
3815 if (!r.finishing) {
3816 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003817 r.stack.destroyActivityLocked(r, true);
3818 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 }
3820 }
3821 }
3822 }
3823
3824 if (r != null) {
3825 sendPendingThumbnail(r, null, null, null, false);
3826 }
3827
3828 trimApplications();
3829
3830 Binder.restoreCallingIdentity(origId);
3831 }
3832
3833 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003834 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003835 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 }
3837
3838 public String getCallingPackage(IBinder token) {
3839 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003840 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003841 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003842 }
3843 }
3844
3845 public ComponentName getCallingActivity(IBinder token) {
3846 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003847 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003848 return r != null ? r.intent.getComponent() : null;
3849 }
3850 }
3851
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003852 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003853 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003855 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 if (r != null) {
3857 return r.resultTo;
3858 }
3859 }
3860 return null;
3861 }
3862
3863 public ComponentName getActivityClassForToken(IBinder token) {
3864 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003865 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003867 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003868 return r.intent.getComponent();
3869 }
3870 return null;
3871 }
3872 }
3873
3874 public String getPackageForToken(IBinder token) {
3875 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003876 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003878 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 return r.packageName;
3880 }
3881 return null;
3882 }
3883 }
3884
3885 public IIntentSender getIntentSender(int type,
3886 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003887 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003889 if (intents != null) {
3890 if (intents.length < 1) {
3891 throw new IllegalArgumentException("Intents array length must be >= 1");
3892 }
3893 for (int i=0; i<intents.length; i++) {
3894 Intent intent = intents[i];
3895 if (intent == null) {
3896 throw new IllegalArgumentException("Null intent at index " + i);
3897 }
3898 if (intent.hasFileDescriptors()) {
3899 throw new IllegalArgumentException("File descriptors passed in Intent");
3900 }
3901 if (type == INTENT_SENDER_BROADCAST &&
3902 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3903 throw new IllegalArgumentException(
3904 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3905 }
3906 intents[i] = new Intent(intent);
3907 }
3908 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003909 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003910 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003911 }
3912 }
3913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003914 synchronized(this) {
3915 int callingUid = Binder.getCallingUid();
3916 try {
3917 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3918 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003919 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 .getPackageUid(packageName);
3921 if (uid != Binder.getCallingUid()) {
3922 String msg = "Permission Denial: getIntentSender() from pid="
3923 + Binder.getCallingPid()
3924 + ", uid=" + Binder.getCallingUid()
3925 + ", (need uid=" + uid + ")"
3926 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003927 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 throw new SecurityException(msg);
3929 }
3930 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003931
3932 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003933 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 } catch (RemoteException e) {
3936 throw new SecurityException(e);
3937 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003938 }
3939 }
3940
3941 IIntentSender getIntentSenderLocked(int type,
3942 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003943 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003944 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003945 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003946 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003947 if (index < 0) {
3948 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003949 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003950 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003951 if (activity.finishing) {
3952 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003954 }
3955
3956 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3957 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3958 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3959 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3960 |PendingIntent.FLAG_UPDATE_CURRENT);
3961
3962 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3963 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003964 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003965 WeakReference<PendingIntentRecord> ref;
3966 ref = mIntentSenderRecords.get(key);
3967 PendingIntentRecord rec = ref != null ? ref.get() : null;
3968 if (rec != null) {
3969 if (!cancelCurrent) {
3970 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003971 if (rec.key.requestIntent != null) {
3972 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3973 }
3974 if (intents != null) {
3975 intents[intents.length-1] = rec.key.requestIntent;
3976 rec.key.allIntents = intents;
3977 rec.key.allResolvedTypes = resolvedTypes;
3978 } else {
3979 rec.key.allIntents = null;
3980 rec.key.allResolvedTypes = null;
3981 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 return rec;
3984 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003985 rec.canceled = true;
3986 mIntentSenderRecords.remove(key);
3987 }
3988 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003989 return rec;
3990 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003991 rec = new PendingIntentRecord(this, key, callingUid);
3992 mIntentSenderRecords.put(key, rec.ref);
3993 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3994 if (activity.pendingResults == null) {
3995 activity.pendingResults
3996 = new HashSet<WeakReference<PendingIntentRecord>>();
3997 }
3998 activity.pendingResults.add(rec.ref);
3999 }
4000 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004001 }
4002
4003 public void cancelIntentSender(IIntentSender sender) {
4004 if (!(sender instanceof PendingIntentRecord)) {
4005 return;
4006 }
4007 synchronized(this) {
4008 PendingIntentRecord rec = (PendingIntentRecord)sender;
4009 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004010 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 .getPackageUid(rec.key.packageName);
4012 if (uid != Binder.getCallingUid()) {
4013 String msg = "Permission Denial: cancelIntentSender() from pid="
4014 + Binder.getCallingPid()
4015 + ", uid=" + Binder.getCallingUid()
4016 + " is not allowed to cancel packges "
4017 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004018 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 throw new SecurityException(msg);
4020 }
4021 } catch (RemoteException e) {
4022 throw new SecurityException(e);
4023 }
4024 cancelIntentSenderLocked(rec, true);
4025 }
4026 }
4027
4028 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4029 rec.canceled = true;
4030 mIntentSenderRecords.remove(rec.key);
4031 if (cleanActivity && rec.key.activity != null) {
4032 rec.key.activity.pendingResults.remove(rec.ref);
4033 }
4034 }
4035
4036 public String getPackageForIntentSender(IIntentSender pendingResult) {
4037 if (!(pendingResult instanceof PendingIntentRecord)) {
4038 return null;
4039 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004040 try {
4041 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4042 return res.key.packageName;
4043 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004044 }
4045 return null;
4046 }
4047
4048 public void setProcessLimit(int max) {
4049 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4050 "setProcessLimit()");
4051 mProcessLimit = max;
4052 }
4053
4054 public int getProcessLimit() {
4055 return mProcessLimit;
4056 }
4057
4058 void foregroundTokenDied(ForegroundToken token) {
4059 synchronized (ActivityManagerService.this) {
4060 synchronized (mPidsSelfLocked) {
4061 ForegroundToken cur
4062 = mForegroundProcesses.get(token.pid);
4063 if (cur != token) {
4064 return;
4065 }
4066 mForegroundProcesses.remove(token.pid);
4067 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4068 if (pr == null) {
4069 return;
4070 }
4071 pr.forcingToForeground = null;
4072 pr.foregroundServices = false;
4073 }
4074 updateOomAdjLocked();
4075 }
4076 }
4077
4078 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4079 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4080 "setProcessForeground()");
4081 synchronized(this) {
4082 boolean changed = false;
4083
4084 synchronized (mPidsSelfLocked) {
4085 ProcessRecord pr = mPidsSelfLocked.get(pid);
4086 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004087 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 return;
4089 }
4090 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4091 if (oldToken != null) {
4092 oldToken.token.unlinkToDeath(oldToken, 0);
4093 mForegroundProcesses.remove(pid);
4094 pr.forcingToForeground = null;
4095 changed = true;
4096 }
4097 if (isForeground && token != null) {
4098 ForegroundToken newToken = new ForegroundToken() {
4099 public void binderDied() {
4100 foregroundTokenDied(this);
4101 }
4102 };
4103 newToken.pid = pid;
4104 newToken.token = token;
4105 try {
4106 token.linkToDeath(newToken, 0);
4107 mForegroundProcesses.put(pid, newToken);
4108 pr.forcingToForeground = token;
4109 changed = true;
4110 } catch (RemoteException e) {
4111 // If the process died while doing this, we will later
4112 // do the cleanup with the process death link.
4113 }
4114 }
4115 }
4116
4117 if (changed) {
4118 updateOomAdjLocked();
4119 }
4120 }
4121 }
4122
4123 // =========================================================
4124 // PERMISSIONS
4125 // =========================================================
4126
4127 static class PermissionController extends IPermissionController.Stub {
4128 ActivityManagerService mActivityManagerService;
4129 PermissionController(ActivityManagerService activityManagerService) {
4130 mActivityManagerService = activityManagerService;
4131 }
4132
4133 public boolean checkPermission(String permission, int pid, int uid) {
4134 return mActivityManagerService.checkPermission(permission, pid,
4135 uid) == PackageManager.PERMISSION_GRANTED;
4136 }
4137 }
4138
4139 /**
4140 * This can be called with or without the global lock held.
4141 */
4142 int checkComponentPermission(String permission, int pid, int uid,
4143 int reqUid) {
4144 // We might be performing an operation on behalf of an indirect binder
4145 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4146 // client identity accordingly before proceeding.
4147 Identity tlsIdentity = sCallerIdentity.get();
4148 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004149 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4151 uid = tlsIdentity.uid;
4152 pid = tlsIdentity.pid;
4153 }
4154
4155 // Root, system server and our own process get to do everything.
4156 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4157 !Process.supportsProcesses()) {
4158 return PackageManager.PERMISSION_GRANTED;
4159 }
4160 // If the target requires a specific UID, always fail for others.
4161 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004162 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163 return PackageManager.PERMISSION_DENIED;
4164 }
4165 if (permission == null) {
4166 return PackageManager.PERMISSION_GRANTED;
4167 }
4168 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004169 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 .checkUidPermission(permission, uid);
4171 } catch (RemoteException e) {
4172 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004173 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 }
4175 return PackageManager.PERMISSION_DENIED;
4176 }
4177
4178 /**
4179 * As the only public entry point for permissions checking, this method
4180 * can enforce the semantic that requesting a check on a null global
4181 * permission is automatically denied. (Internally a null permission
4182 * string is used when calling {@link #checkComponentPermission} in cases
4183 * when only uid-based security is needed.)
4184 *
4185 * This can be called with or without the global lock held.
4186 */
4187 public int checkPermission(String permission, int pid, int uid) {
4188 if (permission == null) {
4189 return PackageManager.PERMISSION_DENIED;
4190 }
4191 return checkComponentPermission(permission, pid, uid, -1);
4192 }
4193
4194 /**
4195 * Binder IPC calls go through the public entry point.
4196 * This can be called with or without the global lock held.
4197 */
4198 int checkCallingPermission(String permission) {
4199 return checkPermission(permission,
4200 Binder.getCallingPid(),
4201 Binder.getCallingUid());
4202 }
4203
4204 /**
4205 * This can be called with or without the global lock held.
4206 */
4207 void enforceCallingPermission(String permission, String func) {
4208 if (checkCallingPermission(permission)
4209 == PackageManager.PERMISSION_GRANTED) {
4210 return;
4211 }
4212
4213 String msg = "Permission Denial: " + func + " from pid="
4214 + Binder.getCallingPid()
4215 + ", uid=" + Binder.getCallingUid()
4216 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004217 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 throw new SecurityException(msg);
4219 }
4220
4221 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004222 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4223 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4224 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4225 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4226 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004228 // Is the component private from the target uid?
4229 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4230
4231 // Acceptable if the there is no read permission needed from the
4232 // target or the target is holding the read permission.
4233 if (!readPerm) {
4234 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004235 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004236 == PackageManager.PERMISSION_GRANTED)) {
4237 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 }
4239 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004240
4241 // Acceptable if the there is no write permission needed from the
4242 // target or the target is holding the read permission.
4243 if (!writePerm) {
4244 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004246 == PackageManager.PERMISSION_GRANTED)) {
4247 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004248 }
4249 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004250
4251 // Acceptable if there is a path permission matching the URI that
4252 // the target holds the permission on.
4253 PathPermission[] pps = pi.pathPermissions;
4254 if (pps != null && (!readPerm || !writePerm)) {
4255 final String path = uri.getPath();
4256 int i = pps.length;
4257 while (i > 0 && (!readPerm || !writePerm)) {
4258 i--;
4259 PathPermission pp = pps[i];
4260 if (!readPerm) {
4261 final String pprperm = pp.getReadPermission();
4262 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4263 + pprperm + " for " + pp.getPath()
4264 + ": match=" + pp.match(path)
4265 + " check=" + pm.checkUidPermission(pprperm, uid));
4266 if (pprperm != null && pp.match(path) &&
4267 (pm.checkUidPermission(pprperm, uid)
4268 == PackageManager.PERMISSION_GRANTED)) {
4269 readPerm = true;
4270 }
4271 }
4272 if (!writePerm) {
4273 final String ppwperm = pp.getWritePermission();
4274 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4275 + ppwperm + " for " + pp.getPath()
4276 + ": match=" + pp.match(path)
4277 + " check=" + pm.checkUidPermission(ppwperm, uid));
4278 if (ppwperm != null && pp.match(path) &&
4279 (pm.checkUidPermission(ppwperm, uid)
4280 == PackageManager.PERMISSION_GRANTED)) {
4281 writePerm = true;
4282 }
4283 }
4284 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 } catch (RemoteException e) {
4287 return false;
4288 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004289
4290 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004291 }
4292
4293 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4294 int modeFlags) {
4295 // Root gets to do everything.
4296 if (uid == 0 || !Process.supportsProcesses()) {
4297 return true;
4298 }
4299 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4300 if (perms == null) return false;
4301 UriPermission perm = perms.get(uri);
4302 if (perm == null) return false;
4303 return (modeFlags&perm.modeFlags) == modeFlags;
4304 }
4305
4306 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4307 // Another redirected-binder-call permissions check as in
4308 // {@link checkComponentPermission}.
4309 Identity tlsIdentity = sCallerIdentity.get();
4310 if (tlsIdentity != null) {
4311 uid = tlsIdentity.uid;
4312 pid = tlsIdentity.pid;
4313 }
4314
4315 // Our own process gets to do everything.
4316 if (pid == MY_PID) {
4317 return PackageManager.PERMISSION_GRANTED;
4318 }
4319 synchronized(this) {
4320 return checkUriPermissionLocked(uri, uid, modeFlags)
4321 ? PackageManager.PERMISSION_GRANTED
4322 : PackageManager.PERMISSION_DENIED;
4323 }
4324 }
4325
Dianne Hackborn39792d22010-08-19 18:01:52 -07004326 /**
4327 * Check if the targetPkg can be granted permission to access uri by
4328 * the callingUid using the given modeFlags. Throws a security exception
4329 * if callingUid is not allowed to do this. Returns the uid of the target
4330 * if the URI permission grant should be performed; returns -1 if it is not
4331 * needed (for example targetPkg already has permission to access the URI).
4332 */
4333 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4334 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4336 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4337 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004338 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 }
4340
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004341 if (targetPkg != null) {
4342 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4343 "Checking grant " + targetPkg + " permission to " + uri);
4344 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004345
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004346 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347
4348 // If this is not a content: uri, we can't do anything with it.
4349 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004350 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004351 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004352 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004353 }
4354
4355 String name = uri.getAuthority();
4356 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004357 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 if (cpr != null) {
4359 pi = cpr.info;
4360 } else {
4361 try {
4362 pi = pm.resolveContentProvider(name,
4363 PackageManager.GET_URI_PERMISSION_PATTERNS);
4364 } catch (RemoteException ex) {
4365 }
4366 }
4367 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004368 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004369 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 }
4371
4372 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004373 if (targetPkg != null) {
4374 try {
4375 targetUid = pm.getPackageUid(targetPkg);
4376 if (targetUid < 0) {
4377 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4378 "Can't grant URI permission no uid for: " + targetPkg);
4379 return -1;
4380 }
4381 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004382 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004384 } else {
4385 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386 }
4387
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004388 if (targetUid >= 0) {
4389 // First... does the target actually need this permission?
4390 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4391 // No need to grant the target this permission.
4392 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4393 "Target " + targetPkg + " already has full permission to " + uri);
4394 return -1;
4395 }
4396 } else {
4397 // First... there is no target package, so can anyone access it?
4398 boolean allowed = pi.exported;
4399 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4400 if (pi.readPermission != null) {
4401 allowed = false;
4402 }
4403 }
4404 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4405 if (pi.writePermission != null) {
4406 allowed = false;
4407 }
4408 }
4409 if (allowed) {
4410 return -1;
4411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 }
4413
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004414 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415 if (!pi.grantUriPermissions) {
4416 throw new SecurityException("Provider " + pi.packageName
4417 + "/" + pi.name
4418 + " does not allow granting of Uri permissions (uri "
4419 + uri + ")");
4420 }
4421 if (pi.uriPermissionPatterns != null) {
4422 final int N = pi.uriPermissionPatterns.length;
4423 boolean allowed = false;
4424 for (int i=0; i<N; i++) {
4425 if (pi.uriPermissionPatterns[i] != null
4426 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4427 allowed = true;
4428 break;
4429 }
4430 }
4431 if (!allowed) {
4432 throw new SecurityException("Provider " + pi.packageName
4433 + "/" + pi.name
4434 + " does not allow granting of permission to path of Uri "
4435 + uri);
4436 }
4437 }
4438
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004439 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004441 if (callingUid != Process.myUid()) {
4442 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4443 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4444 throw new SecurityException("Uid " + callingUid
4445 + " does not have permission to uri " + uri);
4446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 }
4448 }
4449
Dianne Hackborn39792d22010-08-19 18:01:52 -07004450 return targetUid;
4451 }
4452
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004453 public int checkGrantUriPermission(int callingUid, String targetPkg,
4454 Uri uri, int modeFlags) {
4455 synchronized(this) {
4456 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4457 }
4458 }
4459
Dianne Hackborn39792d22010-08-19 18:01:52 -07004460 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4461 Uri uri, int modeFlags, UriPermissionOwner owner) {
4462 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4463 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4464 if (modeFlags == 0) {
4465 return;
4466 }
4467
4468 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004469 // to the uri, and the target doesn't. Let's now give this to
4470 // the target.
4471
Joe Onorato8a9b2202010-02-26 18:56:32 -08004472 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004473 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 HashMap<Uri, UriPermission> targetUris
4476 = mGrantedUriPermissions.get(targetUid);
4477 if (targetUris == null) {
4478 targetUris = new HashMap<Uri, UriPermission>();
4479 mGrantedUriPermissions.put(targetUid, targetUris);
4480 }
4481
4482 UriPermission perm = targetUris.get(uri);
4483 if (perm == null) {
4484 perm = new UriPermission(targetUid, uri);
4485 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004489 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 perm.globalModeFlags |= modeFlags;
4491 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004492 perm.readOwners.add(owner);
4493 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004494 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004495 perm.writeOwners.add(owner);
4496 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 }
4498 }
4499
Dianne Hackborn39792d22010-08-19 18:01:52 -07004500 void grantUriPermissionLocked(int callingUid,
4501 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004502 if (targetPkg == null) {
4503 throw new NullPointerException("targetPkg");
4504 }
4505
Dianne Hackborn39792d22010-08-19 18:01:52 -07004506 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4507 if (targetUid < 0) {
4508 return;
4509 }
4510
4511 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4512 }
4513
4514 /**
4515 * Like checkGrantUriPermissionLocked, but takes an Intent.
4516 */
4517 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4518 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004519 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004520 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004521 + " from " + intent + "; flags=0x"
4522 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4523
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004524 if (targetPkg == null) {
4525 throw new NullPointerException("targetPkg");
4526 }
4527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004529 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004530 }
4531 Uri data = intent.getData();
4532 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004533 return -1;
4534 }
4535 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4536 intent.getFlags());
4537 }
4538
4539 /**
4540 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4541 */
4542 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4543 String targetPkg, Intent intent, UriPermissionOwner owner) {
4544 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4545 intent.getFlags(), owner);
4546 }
4547
4548 void grantUriPermissionFromIntentLocked(int callingUid,
4549 String targetPkg, Intent intent, UriPermissionOwner owner) {
4550 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4551 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004552 return;
4553 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004554
4555 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 }
4557
4558 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4559 Uri uri, int modeFlags) {
4560 synchronized(this) {
4561 final ProcessRecord r = getRecordForAppLocked(caller);
4562 if (r == null) {
4563 throw new SecurityException("Unable to find app for caller "
4564 + caller
4565 + " when granting permission to uri " + uri);
4566 }
4567 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004568 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 }
4570 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004571 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 }
4573
4574 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4575 null);
4576 }
4577 }
4578
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004579 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004580 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4581 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4582 HashMap<Uri, UriPermission> perms
4583 = mGrantedUriPermissions.get(perm.uid);
4584 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004585 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004586 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587 perms.remove(perm.uri);
4588 if (perms.size() == 0) {
4589 mGrantedUriPermissions.remove(perm.uid);
4590 }
4591 }
4592 }
4593 }
4594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004595 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4596 int modeFlags) {
4597 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4598 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4599 if (modeFlags == 0) {
4600 return;
4601 }
4602
Joe Onorato8a9b2202010-02-26 18:56:32 -08004603 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004604 "Revoking all granted permissions to " + uri);
4605
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004606 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607
4608 final String authority = uri.getAuthority();
4609 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004610 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 if (cpr != null) {
4612 pi = cpr.info;
4613 } else {
4614 try {
4615 pi = pm.resolveContentProvider(authority,
4616 PackageManager.GET_URI_PERMISSION_PATTERNS);
4617 } catch (RemoteException ex) {
4618 }
4619 }
4620 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004621 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004622 return;
4623 }
4624
4625 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004626 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 // Right now, if you are not the original owner of the permission,
4628 // you are not allowed to revoke it.
4629 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4630 throw new SecurityException("Uid " + callingUid
4631 + " does not have permission to uri " + uri);
4632 //}
4633 }
4634
4635 // Go through all of the permissions and remove any that match.
4636 final List<String> SEGMENTS = uri.getPathSegments();
4637 if (SEGMENTS != null) {
4638 final int NS = SEGMENTS.size();
4639 int N = mGrantedUriPermissions.size();
4640 for (int i=0; i<N; i++) {
4641 HashMap<Uri, UriPermission> perms
4642 = mGrantedUriPermissions.valueAt(i);
4643 Iterator<UriPermission> it = perms.values().iterator();
4644 toploop:
4645 while (it.hasNext()) {
4646 UriPermission perm = it.next();
4647 Uri targetUri = perm.uri;
4648 if (!authority.equals(targetUri.getAuthority())) {
4649 continue;
4650 }
4651 List<String> targetSegments = targetUri.getPathSegments();
4652 if (targetSegments == null) {
4653 continue;
4654 }
4655 if (targetSegments.size() < NS) {
4656 continue;
4657 }
4658 for (int j=0; j<NS; j++) {
4659 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4660 continue toploop;
4661 }
4662 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004663 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004664 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 perm.clearModes(modeFlags);
4666 if (perm.modeFlags == 0) {
4667 it.remove();
4668 }
4669 }
4670 if (perms.size() == 0) {
4671 mGrantedUriPermissions.remove(
4672 mGrantedUriPermissions.keyAt(i));
4673 N--;
4674 i--;
4675 }
4676 }
4677 }
4678 }
4679
4680 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4681 int modeFlags) {
4682 synchronized(this) {
4683 final ProcessRecord r = getRecordForAppLocked(caller);
4684 if (r == null) {
4685 throw new SecurityException("Unable to find app for caller "
4686 + caller
4687 + " when revoking permission to uri " + uri);
4688 }
4689 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004690 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 return;
4692 }
4693
4694 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4695 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4696 if (modeFlags == 0) {
4697 return;
4698 }
4699
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004700 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004701
4702 final String authority = uri.getAuthority();
4703 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004704 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 if (cpr != null) {
4706 pi = cpr.info;
4707 } else {
4708 try {
4709 pi = pm.resolveContentProvider(authority,
4710 PackageManager.GET_URI_PERMISSION_PATTERNS);
4711 } catch (RemoteException ex) {
4712 }
4713 }
4714 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004715 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004716 return;
4717 }
4718
4719 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4720 }
4721 }
4722
Dianne Hackborn7e269642010-08-25 19:50:20 -07004723 @Override
4724 public IBinder newUriPermissionOwner(String name) {
4725 synchronized(this) {
4726 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4727 return owner.getExternalTokenLocked();
4728 }
4729 }
4730
4731 @Override
4732 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4733 Uri uri, int modeFlags) {
4734 synchronized(this) {
4735 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4736 if (owner == null) {
4737 throw new IllegalArgumentException("Unknown owner: " + token);
4738 }
4739 if (fromUid != Binder.getCallingUid()) {
4740 if (Binder.getCallingUid() != Process.myUid()) {
4741 // Only system code can grant URI permissions on behalf
4742 // of other users.
4743 throw new SecurityException("nice try");
4744 }
4745 }
4746 if (targetPkg == null) {
4747 throw new IllegalArgumentException("null target");
4748 }
4749 if (uri == null) {
4750 throw new IllegalArgumentException("null uri");
4751 }
4752
4753 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4754 }
4755 }
4756
4757 @Override
4758 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4759 synchronized(this) {
4760 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4761 if (owner == null) {
4762 throw new IllegalArgumentException("Unknown owner: " + token);
4763 }
4764
4765 if (uri == null) {
4766 owner.removeUriPermissionsLocked(mode);
4767 } else {
4768 owner.removeUriPermissionLocked(uri, mode);
4769 }
4770 }
4771 }
4772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4774 synchronized (this) {
4775 ProcessRecord app =
4776 who != null ? getRecordForAppLocked(who) : null;
4777 if (app == null) return;
4778
4779 Message msg = Message.obtain();
4780 msg.what = WAIT_FOR_DEBUGGER_MSG;
4781 msg.obj = app;
4782 msg.arg1 = waiting ? 1 : 0;
4783 mHandler.sendMessage(msg);
4784 }
4785 }
4786
4787 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4788 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004789 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004790 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004791 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 }
4793
4794 // =========================================================
4795 // TASK MANAGEMENT
4796 // =========================================================
4797
4798 public List getTasks(int maxNum, int flags,
4799 IThumbnailReceiver receiver) {
4800 ArrayList list = new ArrayList();
4801
4802 PendingThumbnailsRecord pending = null;
4803 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004804 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004805
4806 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004807 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004808 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4809 + ", receiver=" + receiver);
4810
4811 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4812 != PackageManager.PERMISSION_GRANTED) {
4813 if (receiver != null) {
4814 // If the caller wants to wait for pending thumbnails,
4815 // it ain't gonna get them.
4816 try {
4817 receiver.finished();
4818 } catch (RemoteException ex) {
4819 }
4820 }
4821 String msg = "Permission Denial: getTasks() from pid="
4822 + Binder.getCallingPid()
4823 + ", uid=" + Binder.getCallingUid()
4824 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004825 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 throw new SecurityException(msg);
4827 }
4828
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004829 final boolean canReadFb = checkCallingPermission(
4830 android.Manifest.permission.READ_FRAME_BUFFER)
4831 == PackageManager.PERMISSION_GRANTED;
4832
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004833 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004834 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004835 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004836 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837 CharSequence topDescription = null;
4838 TaskRecord curTask = null;
4839 int numActivities = 0;
4840 int numRunning = 0;
4841 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004842 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004843 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004844 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845
4846 // Initialize state for next task if needed.
4847 if (top == null ||
4848 (top.state == ActivityState.INITIALIZING
4849 && top.task == r.task)) {
4850 top = r;
4851 topDescription = r.description;
4852 curTask = r.task;
4853 numActivities = numRunning = 0;
4854 }
4855
4856 // Add 'r' into the current task.
4857 numActivities++;
4858 if (r.app != null && r.app.thread != null) {
4859 numRunning++;
4860 }
4861 if (topDescription == null) {
4862 topDescription = r.description;
4863 }
4864
Joe Onorato8a9b2202010-02-26 18:56:32 -08004865 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 TAG, r.intent.getComponent().flattenToShortString()
4867 + ": task=" + r.task);
4868
4869 // If the next one is a different task, generate a new
4870 // TaskInfo entry for what we have.
4871 if (next == null || next.task != curTask) {
4872 ActivityManager.RunningTaskInfo ci
4873 = new ActivityManager.RunningTaskInfo();
4874 ci.id = curTask.taskId;
4875 ci.baseActivity = r.intent.getComponent();
4876 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004877 if (canReadFb) {
4878 if (top.thumbnail != null) {
4879 ci.thumbnail = top.thumbnail;
4880 } else if (top.state == ActivityState.RESUMED) {
4881 ci.thumbnail = top.stack.screenshotActivities();
4882 }
4883 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004884 ci.description = topDescription;
4885 ci.numActivities = numActivities;
4886 ci.numRunning = numRunning;
4887 //System.out.println(
4888 // "#" + maxNum + ": " + " descr=" + ci.description);
4889 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004890 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 TAG, "State=" + top.state + "Idle=" + top.idle
4892 + " app=" + top.app
4893 + " thr=" + (top.app != null ? top.app.thread : null));
4894 if (top.state == ActivityState.RESUMED
4895 || top.state == ActivityState.PAUSING) {
4896 if (top.idle && top.app != null
4897 && top.app.thread != null) {
4898 topRecord = top;
4899 topThumbnail = top.app.thread;
4900 } else {
4901 top.thumbnailNeeded = true;
4902 }
4903 }
4904 if (pending == null) {
4905 pending = new PendingThumbnailsRecord(receiver);
4906 }
4907 pending.pendingRecords.add(top);
4908 }
4909 list.add(ci);
4910 maxNum--;
4911 top = null;
4912 }
4913 }
4914
4915 if (pending != null) {
4916 mPendingThumbnails.add(pending);
4917 }
4918 }
4919
Joe Onorato8a9b2202010-02-26 18:56:32 -08004920 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004921
4922 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004923 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004924 try {
4925 topThumbnail.requestThumbnail(topRecord);
4926 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004927 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 sendPendingThumbnail(null, topRecord, null, null, true);
4929 }
4930 }
4931
4932 if (pending == null && receiver != null) {
4933 // In this case all thumbnails were available and the client
4934 // is being asked to be told when the remaining ones come in...
4935 // which is unusually, since the top-most currently running
4936 // activity should never have a canned thumbnail! Oh well.
4937 try {
4938 receiver.finished();
4939 } catch (RemoteException ex) {
4940 }
4941 }
4942
4943 return list;
4944 }
4945
4946 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4947 int flags) {
4948 synchronized (this) {
4949 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4950 "getRecentTasks()");
4951
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004952 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004954 final int N = mRecentTasks.size();
4955 ArrayList<ActivityManager.RecentTaskInfo> res
4956 = new ArrayList<ActivityManager.RecentTaskInfo>(
4957 maxNum < N ? maxNum : N);
4958 for (int i=0; i<N && maxNum > 0; i++) {
4959 TaskRecord tr = mRecentTasks.get(i);
4960 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4961 || (tr.intent == null)
4962 || ((tr.intent.getFlags()
4963 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4964 ActivityManager.RecentTaskInfo rti
4965 = new ActivityManager.RecentTaskInfo();
4966 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4967 rti.baseIntent = new Intent(
4968 tr.intent != null ? tr.intent : tr.affinityIntent);
4969 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004970
4971 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4972 // Check whether this activity is currently available.
4973 try {
4974 if (rti.origActivity != null) {
4975 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4976 continue;
4977 }
4978 } else if (rti.baseIntent != null) {
4979 if (pm.queryIntentActivities(rti.baseIntent,
4980 null, 0) == null) {
4981 continue;
4982 }
4983 }
4984 } catch (RemoteException e) {
4985 // Will never happen.
4986 }
4987 }
4988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 res.add(rti);
4990 maxNum--;
4991 }
4992 }
4993 return res;
4994 }
4995 }
4996
4997 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4998 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004999 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 TaskRecord jt = startTask;
5001
5002 // First look backwards
5003 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005004 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005005 if (r.task != jt) {
5006 jt = r.task;
5007 if (affinity.equals(jt.affinity)) {
5008 return j;
5009 }
5010 }
5011 }
5012
5013 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005014 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005015 jt = startTask;
5016 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005017 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 if (r.task != jt) {
5019 if (affinity.equals(jt.affinity)) {
5020 return j;
5021 }
5022 jt = r.task;
5023 }
5024 }
5025
5026 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005027 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005028 return N-1;
5029 }
5030
5031 return -1;
5032 }
5033
5034 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005035 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005037 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5039 "moveTaskToFront()");
5040
5041 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005042 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5043 Binder.getCallingUid(), "Task to front")) {
5044 return;
5045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 final long origId = Binder.clearCallingIdentity();
5047 try {
5048 int N = mRecentTasks.size();
5049 for (int i=0; i<N; i++) {
5050 TaskRecord tr = mRecentTasks.get(i);
5051 if (tr.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005052 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5053 // Caller wants the home activity moved with it. To accomplish this,
5054 // we'll just move the home task to the top first.
5055 mMainStack.moveHomeToFrontLocked();
5056 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005057 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 return;
5059 }
5060 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005061 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5062 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 if (hr.task.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005064 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5065 // Caller wants the home activity moved with it. To accomplish this,
5066 // we'll just move the home task to the top first.
5067 mMainStack.moveHomeToFrontLocked();
5068 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005069 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005070 return;
5071 }
5072 }
5073 } finally {
5074 Binder.restoreCallingIdentity(origId);
5075 }
5076 }
5077 }
5078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 public void moveTaskToBack(int task) {
5080 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5081 "moveTaskToBack()");
5082
5083 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005084 if (mMainStack.mResumedActivity != null
5085 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005086 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5087 Binder.getCallingUid(), "Task to back")) {
5088 return;
5089 }
5090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005091 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005092 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 Binder.restoreCallingIdentity(origId);
5094 }
5095 }
5096
5097 /**
5098 * Moves an activity, and all of the other activities within the same task, to the bottom
5099 * of the history stack. The activity's order within the task is unchanged.
5100 *
5101 * @param token A reference to the activity we wish to move
5102 * @param nonRoot If false then this only works if the activity is the root
5103 * of a task; if true it will work for any activity in a task.
5104 * @return Returns true if the move completed, false if not.
5105 */
5106 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5107 synchronized(this) {
5108 final long origId = Binder.clearCallingIdentity();
5109 int taskId = getTaskForActivityLocked(token, !nonRoot);
5110 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005111 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 }
5113 Binder.restoreCallingIdentity(origId);
5114 }
5115 return false;
5116 }
5117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 public void moveTaskBackwards(int task) {
5119 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5120 "moveTaskBackwards()");
5121
5122 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005123 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5124 Binder.getCallingUid(), "Task backwards")) {
5125 return;
5126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005127 final long origId = Binder.clearCallingIdentity();
5128 moveTaskBackwardsLocked(task);
5129 Binder.restoreCallingIdentity(origId);
5130 }
5131 }
5132
5133 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005134 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135 }
5136
5137 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5138 synchronized(this) {
5139 return getTaskForActivityLocked(token, onlyRoot);
5140 }
5141 }
5142
5143 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005144 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 TaskRecord lastTask = null;
5146 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005147 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005148 if (r == token) {
5149 if (!onlyRoot || lastTask != r.task) {
5150 return r.task.taskId;
5151 }
5152 return -1;
5153 }
5154 lastTask = r.task;
5155 }
5156
5157 return -1;
5158 }
5159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 public void finishOtherInstances(IBinder token, ComponentName className) {
5161 synchronized(this) {
5162 final long origId = Binder.clearCallingIdentity();
5163
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005164 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 TaskRecord lastTask = null;
5166 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005167 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 if (r.realActivity.equals(className)
5169 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005170 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005171 null, "others")) {
5172 i--;
5173 N--;
5174 }
5175 }
5176 lastTask = r.task;
5177 }
5178
5179 Binder.restoreCallingIdentity(origId);
5180 }
5181 }
5182
5183 // =========================================================
5184 // THUMBNAILS
5185 // =========================================================
5186
5187 public void reportThumbnail(IBinder token,
5188 Bitmap thumbnail, CharSequence description) {
5189 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5190 final long origId = Binder.clearCallingIdentity();
5191 sendPendingThumbnail(null, token, thumbnail, description, true);
5192 Binder.restoreCallingIdentity(origId);
5193 }
5194
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005195 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005196 Bitmap thumbnail, CharSequence description, boolean always) {
5197 TaskRecord task = null;
5198 ArrayList receivers = null;
5199
5200 //System.out.println("Send pending thumbnail: " + r);
5201
5202 synchronized(this) {
5203 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005204 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005205 if (index < 0) {
5206 return;
5207 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005208 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005209 }
5210 if (thumbnail == null) {
5211 thumbnail = r.thumbnail;
5212 description = r.description;
5213 }
5214 if (thumbnail == null && !always) {
5215 // If there is no thumbnail, and this entry is not actually
5216 // going away, then abort for now and pick up the next
5217 // thumbnail we get.
5218 return;
5219 }
5220 task = r.task;
5221
5222 int N = mPendingThumbnails.size();
5223 int i=0;
5224 while (i<N) {
5225 PendingThumbnailsRecord pr =
5226 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5227 //System.out.println("Looking in " + pr.pendingRecords);
5228 if (pr.pendingRecords.remove(r)) {
5229 if (receivers == null) {
5230 receivers = new ArrayList();
5231 }
5232 receivers.add(pr);
5233 if (pr.pendingRecords.size() == 0) {
5234 pr.finished = true;
5235 mPendingThumbnails.remove(i);
5236 N--;
5237 continue;
5238 }
5239 }
5240 i++;
5241 }
5242 }
5243
5244 if (receivers != null) {
5245 final int N = receivers.size();
5246 for (int i=0; i<N; i++) {
5247 try {
5248 PendingThumbnailsRecord pr =
5249 (PendingThumbnailsRecord)receivers.get(i);
5250 pr.receiver.newThumbnail(
5251 task != null ? task.taskId : -1, thumbnail, description);
5252 if (pr.finished) {
5253 pr.receiver.finished();
5254 }
5255 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005256 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 }
5258 }
5259 }
5260 }
5261
5262 // =========================================================
5263 // CONTENT PROVIDERS
5264 // =========================================================
5265
5266 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5267 List providers = null;
5268 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005269 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005271 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 } catch (RemoteException ex) {
5273 }
5274 if (providers != null) {
5275 final int N = providers.size();
5276 for (int i=0; i<N; i++) {
5277 ProviderInfo cpi =
5278 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005279 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 if (cpr == null) {
5281 cpr = new ContentProviderRecord(cpi, app.info);
5282 mProvidersByClass.put(cpi.name, cpr);
5283 }
5284 app.pubProviders.put(cpi.name, cpr);
5285 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005286 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 }
5288 }
5289 return providers;
5290 }
5291
5292 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005293 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5295 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5296 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5297 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005298 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 return null;
5300 }
5301 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5302 cpi.exported ? -1 : cpi.applicationInfo.uid)
5303 == PackageManager.PERMISSION_GRANTED) {
5304 return null;
5305 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005306
5307 PathPermission[] pps = cpi.pathPermissions;
5308 if (pps != null) {
5309 int i = pps.length;
5310 while (i > 0) {
5311 i--;
5312 PathPermission pp = pps[i];
5313 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5314 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005315 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005316 return null;
5317 }
5318 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5319 cpi.exported ? -1 : cpi.applicationInfo.uid)
5320 == PackageManager.PERMISSION_GRANTED) {
5321 return null;
5322 }
5323 }
5324 }
5325
Dianne Hackbornb424b632010-08-18 15:59:05 -07005326 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5327 if (perms != null) {
5328 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5329 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5330 return null;
5331 }
5332 }
5333 }
5334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 String msg = "Permission Denial: opening provider " + cpi.name
5336 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5337 + ", uid=" + callingUid + ") requires "
5338 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005339 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005340 return msg;
5341 }
5342
5343 private final ContentProviderHolder getContentProviderImpl(
5344 IApplicationThread caller, String name) {
5345 ContentProviderRecord cpr;
5346 ProviderInfo cpi = null;
5347
5348 synchronized(this) {
5349 ProcessRecord r = null;
5350 if (caller != null) {
5351 r = getRecordForAppLocked(caller);
5352 if (r == null) {
5353 throw new SecurityException(
5354 "Unable to find app for caller " + caller
5355 + " (pid=" + Binder.getCallingPid()
5356 + ") when getting content provider " + name);
5357 }
5358 }
5359
5360 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005361 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362 if (cpr != null) {
5363 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005364 String msg;
5365 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5366 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367 }
5368
5369 if (r != null && cpr.canRunHere(r)) {
5370 // This provider has been published or is in the process
5371 // of being published... but it is also allowed to run
5372 // in the caller's process, so don't make a connection
5373 // and just let the caller instantiate its own instance.
5374 if (cpr.provider != null) {
5375 // don't give caller the provider object, it needs
5376 // to make its own.
5377 cpr = new ContentProviderRecord(cpr);
5378 }
5379 return cpr;
5380 }
5381
5382 final long origId = Binder.clearCallingIdentity();
5383
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005384 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 // return it right away.
5386 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005387 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005388 "Adding provider requested by "
5389 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005390 + cpr.info.processName);
5391 Integer cnt = r.conProviders.get(cpr);
5392 if (cnt == null) {
5393 r.conProviders.put(cpr, new Integer(1));
5394 } else {
5395 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005397 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005398 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5399 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005400 // make sure to count it as being accessed and thus
5401 // back up on the LRU list. This is good because
5402 // content providers are often expensive to start.
5403 updateLruProcessLocked(cpr.app, false, true);
5404 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005405 } else {
5406 cpr.externals++;
5407 }
5408
5409 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 updateOomAdjLocked(cpr.app);
5411 }
5412
5413 Binder.restoreCallingIdentity(origId);
5414
5415 } else {
5416 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005417 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005418 resolveContentProvider(name,
5419 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 } catch (RemoteException ex) {
5421 }
5422 if (cpi == null) {
5423 return null;
5424 }
5425
Dianne Hackbornb424b632010-08-18 15:59:05 -07005426 String msg;
5427 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5428 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 }
5430
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005431 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005432 && !cpi.processName.equals("system")) {
5433 // If this content provider does not run in the system
5434 // process, and the system is not yet ready to run other
5435 // processes, then fail fast instead of hanging.
5436 throw new IllegalArgumentException(
5437 "Attempt to launch content provider before system ready");
5438 }
5439
Dianne Hackborn860755f2010-06-03 18:47:52 -07005440 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005441 final boolean firstClass = cpr == null;
5442 if (firstClass) {
5443 try {
5444 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005445 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 getApplicationInfo(
5447 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005448 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005450 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 + cpi.name);
5452 return null;
5453 }
5454 cpr = new ContentProviderRecord(cpi, ai);
5455 } catch (RemoteException ex) {
5456 // pm is in same process, this will never happen.
5457 }
5458 }
5459
5460 if (r != null && cpr.canRunHere(r)) {
5461 // If this is a multiprocess provider, then just return its
5462 // info and allow the caller to instantiate it. Only do
5463 // this if the provider is the same user as the caller's
5464 // process, or can run as root (so can be in any process).
5465 return cpr;
5466 }
5467
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005468 if (DEBUG_PROVIDER) {
5469 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005470 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005471 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 }
5473
5474 // This is single process, and our app is now connecting to it.
5475 // See if we are already in the process of launching this
5476 // provider.
5477 final int N = mLaunchingProviders.size();
5478 int i;
5479 for (i=0; i<N; i++) {
5480 if (mLaunchingProviders.get(i) == cpr) {
5481 break;
5482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005483 }
5484
5485 // If the provider is not already being launched, then get it
5486 // started.
5487 if (i >= N) {
5488 final long origId = Binder.clearCallingIdentity();
5489 ProcessRecord proc = startProcessLocked(cpi.processName,
5490 cpr.appInfo, false, 0, "content provider",
5491 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005492 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005494 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005495 + cpi.applicationInfo.packageName + "/"
5496 + cpi.applicationInfo.uid + " for provider "
5497 + name + ": process is bad");
5498 return null;
5499 }
5500 cpr.launchingApp = proc;
5501 mLaunchingProviders.add(cpr);
5502 Binder.restoreCallingIdentity(origId);
5503 }
5504
5505 // Make sure the provider is published (the same provider class
5506 // may be published under multiple names).
5507 if (firstClass) {
5508 mProvidersByClass.put(cpi.name, cpr);
5509 }
5510 mProvidersByName.put(name, cpr);
5511
5512 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005513 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005514 "Adding provider requested by "
5515 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005516 + cpr.info.processName);
5517 Integer cnt = r.conProviders.get(cpr);
5518 if (cnt == null) {
5519 r.conProviders.put(cpr, new Integer(1));
5520 } else {
5521 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005523 cpr.clients.add(r);
5524 } else {
5525 cpr.externals++;
5526 }
5527 }
5528 }
5529
5530 // Wait for the provider to be published...
5531 synchronized (cpr) {
5532 while (cpr.provider == null) {
5533 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005534 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 + cpi.applicationInfo.packageName + "/"
5536 + cpi.applicationInfo.uid + " for provider "
5537 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005538 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005539 cpi.applicationInfo.packageName,
5540 cpi.applicationInfo.uid, name);
5541 return null;
5542 }
5543 try {
5544 cpr.wait();
5545 } catch (InterruptedException ex) {
5546 }
5547 }
5548 }
5549 return cpr;
5550 }
5551
5552 public final ContentProviderHolder getContentProvider(
5553 IApplicationThread caller, String name) {
5554 if (caller == null) {
5555 String msg = "null IApplicationThread when getting content provider "
5556 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005557 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 throw new SecurityException(msg);
5559 }
5560
5561 return getContentProviderImpl(caller, name);
5562 }
5563
5564 private ContentProviderHolder getContentProviderExternal(String name) {
5565 return getContentProviderImpl(null, name);
5566 }
5567
5568 /**
5569 * Drop a content provider from a ProcessRecord's bookkeeping
5570 * @param cpr
5571 */
5572 public void removeContentProvider(IApplicationThread caller, String name) {
5573 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005574 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005575 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005576 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005577 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005578 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 return;
5580 }
5581 final ProcessRecord r = getRecordForAppLocked(caller);
5582 if (r == null) {
5583 throw new SecurityException(
5584 "Unable to find app for caller " + caller +
5585 " when removing content provider " + name);
5586 }
5587 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005588 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005589 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005590 + r.info.processName + " from process "
5591 + localCpr.appInfo.processName);
5592 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005594 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005595 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005596 return;
5597 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005598 Integer cnt = r.conProviders.get(localCpr);
5599 if (cnt == null || cnt.intValue() <= 1) {
5600 localCpr.clients.remove(r);
5601 r.conProviders.remove(localCpr);
5602 } else {
5603 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005605 }
5606 updateOomAdjLocked();
5607 }
5608 }
5609
5610 private void removeContentProviderExternal(String name) {
5611 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005612 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 if(cpr == null) {
5614 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005615 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 return;
5617 }
5618
5619 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005620 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 localCpr.externals--;
5622 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005623 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624 }
5625 updateOomAdjLocked();
5626 }
5627 }
5628
5629 public final void publishContentProviders(IApplicationThread caller,
5630 List<ContentProviderHolder> providers) {
5631 if (providers == null) {
5632 return;
5633 }
5634
5635 synchronized(this) {
5636 final ProcessRecord r = getRecordForAppLocked(caller);
5637 if (r == null) {
5638 throw new SecurityException(
5639 "Unable to find app for caller " + caller
5640 + " (pid=" + Binder.getCallingPid()
5641 + ") when publishing content providers");
5642 }
5643
5644 final long origId = Binder.clearCallingIdentity();
5645
5646 final int N = providers.size();
5647 for (int i=0; i<N; i++) {
5648 ContentProviderHolder src = providers.get(i);
5649 if (src == null || src.info == null || src.provider == null) {
5650 continue;
5651 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005652 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005653 if (dst != null) {
5654 mProvidersByClass.put(dst.info.name, dst);
5655 String names[] = dst.info.authority.split(";");
5656 for (int j = 0; j < names.length; j++) {
5657 mProvidersByName.put(names[j], dst);
5658 }
5659
5660 int NL = mLaunchingProviders.size();
5661 int j;
5662 for (j=0; j<NL; j++) {
5663 if (mLaunchingProviders.get(j) == dst) {
5664 mLaunchingProviders.remove(j);
5665 j--;
5666 NL--;
5667 }
5668 }
5669 synchronized (dst) {
5670 dst.provider = src.provider;
5671 dst.app = r;
5672 dst.notifyAll();
5673 }
5674 updateOomAdjLocked(r);
5675 }
5676 }
5677
5678 Binder.restoreCallingIdentity(origId);
5679 }
5680 }
5681
5682 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005683 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005684 synchronized (mSelf) {
5685 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5686 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005687 if (providers != null) {
5688 for (int i=providers.size()-1; i>=0; i--) {
5689 ProviderInfo pi = (ProviderInfo)providers.get(i);
5690 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5691 Slog.w(TAG, "Not installing system proc provider " + pi.name
5692 + ": not system .apk");
5693 providers.remove(i);
5694 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005695 }
5696 }
5697 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005698 if (providers != null) {
5699 mSystemThread.installSystemProviders(providers);
5700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 }
5702
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005703 /**
5704 * Allows app to retrieve the MIME type of a URI without having permission
5705 * to access its content provider.
5706 *
5707 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5708 *
5709 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5710 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5711 */
5712 public String getProviderMimeType(Uri uri) {
5713 final String name = uri.getAuthority();
5714 final long ident = Binder.clearCallingIdentity();
5715 ContentProviderHolder holder = null;
5716
5717 try {
5718 holder = getContentProviderExternal(name);
5719 if (holder != null) {
5720 return holder.provider.getType(uri);
5721 }
5722 } catch (RemoteException e) {
5723 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5724 return null;
5725 } finally {
5726 if (holder != null) {
5727 removeContentProviderExternal(name);
5728 }
5729 Binder.restoreCallingIdentity(ident);
5730 }
5731
5732 return null;
5733 }
5734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005735 // =========================================================
5736 // GLOBAL MANAGEMENT
5737 // =========================================================
5738
5739 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5740 ApplicationInfo info, String customProcess) {
5741 String proc = customProcess != null ? customProcess : info.processName;
5742 BatteryStatsImpl.Uid.Proc ps = null;
5743 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5744 synchronized (stats) {
5745 ps = stats.getProcessStatsLocked(info.uid, proc);
5746 }
5747 return new ProcessRecord(ps, thread, info, proc);
5748 }
5749
5750 final ProcessRecord addAppLocked(ApplicationInfo info) {
5751 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5752
5753 if (app == null) {
5754 app = newProcessRecordLocked(null, info, null);
5755 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005756 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005757 }
5758
5759 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5760 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5761 app.persistent = true;
5762 app.maxAdj = CORE_SERVER_ADJ;
5763 }
5764 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5765 mPersistentStartingProcesses.add(app);
5766 startProcessLocked(app, "added application", app.processName);
5767 }
5768
5769 return app;
5770 }
5771
5772 public void unhandledBack() {
5773 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5774 "unhandledBack()");
5775
5776 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005777 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005778 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005779 TAG, "Performing unhandledBack(): stack size = " + count);
5780 if (count > 1) {
5781 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005782 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005783 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5784 Binder.restoreCallingIdentity(origId);
5785 }
5786 }
5787 }
5788
5789 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5790 String name = uri.getAuthority();
5791 ContentProviderHolder cph = getContentProviderExternal(name);
5792 ParcelFileDescriptor pfd = null;
5793 if (cph != null) {
5794 // We record the binder invoker's uid in thread-local storage before
5795 // going to the content provider to open the file. Later, in the code
5796 // that handles all permissions checks, we look for this uid and use
5797 // that rather than the Activity Manager's own uid. The effect is that
5798 // we do the check against the caller's permissions even though it looks
5799 // to the content provider like the Activity Manager itself is making
5800 // the request.
5801 sCallerIdentity.set(new Identity(
5802 Binder.getCallingPid(), Binder.getCallingUid()));
5803 try {
5804 pfd = cph.provider.openFile(uri, "r");
5805 } catch (FileNotFoundException e) {
5806 // do nothing; pfd will be returned null
5807 } finally {
5808 // Ensure that whatever happens, we clean up the identity state
5809 sCallerIdentity.remove();
5810 }
5811
5812 // We've got the fd now, so we're done with the provider.
5813 removeContentProviderExternal(name);
5814 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005815 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005816 }
5817 return pfd;
5818 }
5819
5820 public void goingToSleep() {
5821 synchronized(this) {
5822 mSleeping = true;
5823 mWindowManager.setEventDispatching(false);
5824
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005825 if (mMainStack.mResumedActivity != null) {
5826 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005827 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005828 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005829 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005830
5831 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005832 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005833 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5834 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005835 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005836 }
5837 }
5838
Dianne Hackborn55280a92009-05-07 15:53:46 -07005839 public boolean shutdown(int timeout) {
5840 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5841 != PackageManager.PERMISSION_GRANTED) {
5842 throw new SecurityException("Requires permission "
5843 + android.Manifest.permission.SHUTDOWN);
5844 }
5845
5846 boolean timedout = false;
5847
5848 synchronized(this) {
5849 mShuttingDown = true;
5850 mWindowManager.setEventDispatching(false);
5851
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005852 if (mMainStack.mResumedActivity != null) {
5853 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005854 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005855 while (mMainStack.mResumedActivity != null
5856 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005857 long delay = endTime - System.currentTimeMillis();
5858 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005859 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005860 timedout = true;
5861 break;
5862 }
5863 try {
5864 this.wait();
5865 } catch (InterruptedException e) {
5866 }
5867 }
5868 }
5869 }
5870
5871 mUsageStatsService.shutdown();
5872 mBatteryStatsService.shutdown();
5873
5874 return timedout;
5875 }
5876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 public void wakingUp() {
5878 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005879 if (mMainStack.mGoingToSleep.isHeld()) {
5880 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 }
5882 mWindowManager.setEventDispatching(true);
5883 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005884 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 }
5886 }
5887
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005888 public void stopAppSwitches() {
5889 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5890 != PackageManager.PERMISSION_GRANTED) {
5891 throw new SecurityException("Requires permission "
5892 + android.Manifest.permission.STOP_APP_SWITCHES);
5893 }
5894
5895 synchronized(this) {
5896 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5897 + APP_SWITCH_DELAY_TIME;
5898 mDidAppSwitch = false;
5899 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5900 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5901 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5902 }
5903 }
5904
5905 public void resumeAppSwitches() {
5906 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5907 != PackageManager.PERMISSION_GRANTED) {
5908 throw new SecurityException("Requires permission "
5909 + android.Manifest.permission.STOP_APP_SWITCHES);
5910 }
5911
5912 synchronized(this) {
5913 // Note that we don't execute any pending app switches... we will
5914 // let those wait until either the timeout, or the next start
5915 // activity request.
5916 mAppSwitchesAllowedTime = 0;
5917 }
5918 }
5919
5920 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5921 String name) {
5922 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5923 return true;
5924 }
5925
5926 final int perm = checkComponentPermission(
5927 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5928 callingUid, -1);
5929 if (perm == PackageManager.PERMISSION_GRANTED) {
5930 return true;
5931 }
5932
Joe Onorato8a9b2202010-02-26 18:56:32 -08005933 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005934 return false;
5935 }
5936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005937 public void setDebugApp(String packageName, boolean waitForDebugger,
5938 boolean persistent) {
5939 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5940 "setDebugApp()");
5941
5942 // Note that this is not really thread safe if there are multiple
5943 // callers into it at the same time, but that's not a situation we
5944 // care about.
5945 if (persistent) {
5946 final ContentResolver resolver = mContext.getContentResolver();
5947 Settings.System.putString(
5948 resolver, Settings.System.DEBUG_APP,
5949 packageName);
5950 Settings.System.putInt(
5951 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5952 waitForDebugger ? 1 : 0);
5953 }
5954
5955 synchronized (this) {
5956 if (!persistent) {
5957 mOrigDebugApp = mDebugApp;
5958 mOrigWaitForDebugger = mWaitForDebugger;
5959 }
5960 mDebugApp = packageName;
5961 mWaitForDebugger = waitForDebugger;
5962 mDebugTransient = !persistent;
5963 if (packageName != null) {
5964 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005965 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005966 Binder.restoreCallingIdentity(origId);
5967 }
5968 }
5969 }
5970
5971 public void setAlwaysFinish(boolean enabled) {
5972 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5973 "setAlwaysFinish()");
5974
5975 Settings.System.putInt(
5976 mContext.getContentResolver(),
5977 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5978
5979 synchronized (this) {
5980 mAlwaysFinishActivities = enabled;
5981 }
5982 }
5983
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005984 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005985 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005986 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005988 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 }
5990 }
5991
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005992 public boolean isUserAMonkey() {
5993 // For now the fact that there is a controller implies
5994 // we have a monkey.
5995 synchronized (this) {
5996 return mController != null;
5997 }
5998 }
5999
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006000 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006001 synchronized (this) {
6002 mWatchers.register(watcher);
6003 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006004 }
6005
6006 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006007 synchronized (this) {
6008 mWatchers.unregister(watcher);
6009 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006010 }
6011
Daniel Sandler69a48172010-06-23 16:29:36 -04006012 public void setImmersive(IBinder token, boolean immersive) {
6013 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006014 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006015 if (index < 0) {
6016 throw new IllegalArgumentException();
6017 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006018 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006019 r.immersive = immersive;
6020 }
6021 }
6022
6023 public boolean isImmersive(IBinder token) {
6024 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006025 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006026 if (index < 0) {
6027 throw new IllegalArgumentException();
6028 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006029 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006030 return r.immersive;
6031 }
6032 }
6033
6034 public boolean isTopActivityImmersive() {
6035 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006036 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006037 return (r != null) ? r.immersive : false;
6038 }
6039 }
6040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 public final void enterSafeMode() {
6042 synchronized(this) {
6043 // It only makes sense to do this before the system is ready
6044 // and started launching other packages.
6045 if (!mSystemReady) {
6046 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006047 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 } catch (RemoteException e) {
6049 }
6050
6051 View v = LayoutInflater.from(mContext).inflate(
6052 com.android.internal.R.layout.safe_mode, null);
6053 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown3b2b3542010-10-15 00:54:27 -07006054 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006055 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6056 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6057 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6058 lp.format = v.getBackground().getOpacity();
6059 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6060 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6061 ((WindowManager)mContext.getSystemService(
6062 Context.WINDOW_SERVICE)).addView(v, lp);
6063 }
6064 }
6065 }
6066
6067 public void noteWakeupAlarm(IIntentSender sender) {
6068 if (!(sender instanceof PendingIntentRecord)) {
6069 return;
6070 }
6071 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6072 synchronized (stats) {
6073 if (mBatteryStatsService.isOnBattery()) {
6074 mBatteryStatsService.enforceCallingPermission();
6075 PendingIntentRecord rec = (PendingIntentRecord)sender;
6076 int MY_UID = Binder.getCallingUid();
6077 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6078 BatteryStatsImpl.Uid.Pkg pkg =
6079 stats.getPackageStatsLocked(uid, rec.key.packageName);
6080 pkg.incWakeupsLocked();
6081 }
6082 }
6083 }
6084
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006085 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006087 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006088 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006089 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 // XXX Note: don't acquire main activity lock here, because the window
6091 // manager calls in with its locks held.
6092
6093 boolean killed = false;
6094 synchronized (mPidsSelfLocked) {
6095 int[] types = new int[pids.length];
6096 int worstType = 0;
6097 for (int i=0; i<pids.length; i++) {
6098 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6099 if (proc != null) {
6100 int type = proc.setAdj;
6101 types[i] = type;
6102 if (type > worstType) {
6103 worstType = type;
6104 }
6105 }
6106 }
6107
6108 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6109 // then constrain it so we will kill all hidden procs.
6110 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6111 worstType = HIDDEN_APP_MIN_ADJ;
6112 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006113 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006114 for (int i=0; i<pids.length; i++) {
6115 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6116 if (proc == null) {
6117 continue;
6118 }
6119 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006120 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006121 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006122 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6123 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006124 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006125 proc.killedBackground = true;
6126 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006127 }
6128 }
6129 }
6130 return killed;
6131 }
6132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006133 public final void startRunning(String pkg, String cls, String action,
6134 String data) {
6135 synchronized(this) {
6136 if (mStartRunning) {
6137 return;
6138 }
6139 mStartRunning = true;
6140 mTopComponent = pkg != null && cls != null
6141 ? new ComponentName(pkg, cls) : null;
6142 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6143 mTopData = data;
6144 if (!mSystemReady) {
6145 return;
6146 }
6147 }
6148
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006149 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006150 }
6151
6152 private void retrieveSettings() {
6153 final ContentResolver resolver = mContext.getContentResolver();
6154 String debugApp = Settings.System.getString(
6155 resolver, Settings.System.DEBUG_APP);
6156 boolean waitForDebugger = Settings.System.getInt(
6157 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6158 boolean alwaysFinishActivities = Settings.System.getInt(
6159 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6160
6161 Configuration configuration = new Configuration();
6162 Settings.System.getConfiguration(resolver, configuration);
6163
6164 synchronized (this) {
6165 mDebugApp = mOrigDebugApp = debugApp;
6166 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6167 mAlwaysFinishActivities = alwaysFinishActivities;
6168 // This happens before any activities are started, so we can
6169 // change mConfiguration in-place.
6170 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006171 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006172 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006173 }
6174 }
6175
6176 public boolean testIsSystemReady() {
6177 // no need to synchronize(this) just to read & return the value
6178 return mSystemReady;
6179 }
6180
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006181 private static File getCalledPreBootReceiversFile() {
6182 File dataDir = Environment.getDataDirectory();
6183 File systemDir = new File(dataDir, "system");
6184 File fname = new File(systemDir, "called_pre_boots.dat");
6185 return fname;
6186 }
6187
6188 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6189 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6190 File file = getCalledPreBootReceiversFile();
6191 FileInputStream fis = null;
6192 try {
6193 fis = new FileInputStream(file);
6194 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6195 int vers = dis.readInt();
6196 String codename = dis.readUTF();
6197 if (vers == android.os.Build.VERSION.SDK_INT
6198 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6199 int num = dis.readInt();
6200 while (num > 0) {
6201 num--;
6202 String pkg = dis.readUTF();
6203 String cls = dis.readUTF();
6204 lastDoneReceivers.add(new ComponentName(pkg, cls));
6205 }
6206 }
6207 } catch (FileNotFoundException e) {
6208 } catch (IOException e) {
6209 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6210 } finally {
6211 if (fis != null) {
6212 try {
6213 fis.close();
6214 } catch (IOException e) {
6215 }
6216 }
6217 }
6218 return lastDoneReceivers;
6219 }
6220
6221 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6222 File file = getCalledPreBootReceiversFile();
6223 FileOutputStream fos = null;
6224 DataOutputStream dos = null;
6225 try {
6226 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6227 fos = new FileOutputStream(file);
6228 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6229 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6230 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6231 dos.writeInt(list.size());
6232 for (int i=0; i<list.size(); i++) {
6233 dos.writeUTF(list.get(i).getPackageName());
6234 dos.writeUTF(list.get(i).getClassName());
6235 }
6236 } catch (IOException e) {
6237 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6238 file.delete();
6239 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006240 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006241 if (dos != null) {
6242 try {
6243 dos.close();
6244 } catch (IOException e) {
6245 // TODO Auto-generated catch block
6246 e.printStackTrace();
6247 }
6248 }
6249 }
6250 }
6251
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006252 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006253 // In the simulator, startRunning will never have been called, which
6254 // normally sets a few crucial variables. Do it here instead.
6255 if (!Process.supportsProcesses()) {
6256 mStartRunning = true;
6257 mTopAction = Intent.ACTION_MAIN;
6258 }
6259
6260 synchronized(this) {
6261 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006262 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006263 return;
6264 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006265
6266 // Check to see if there are any update receivers to run.
6267 if (!mDidUpdate) {
6268 if (mWaitingUpdate) {
6269 return;
6270 }
6271 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6272 List<ResolveInfo> ris = null;
6273 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006274 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006275 intent, null, 0);
6276 } catch (RemoteException e) {
6277 }
6278 if (ris != null) {
6279 for (int i=ris.size()-1; i>=0; i--) {
6280 if ((ris.get(i).activityInfo.applicationInfo.flags
6281 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6282 ris.remove(i);
6283 }
6284 }
6285 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006286
6287 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6288
6289 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006290 for (int i=0; i<ris.size(); i++) {
6291 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006292 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6293 if (lastDoneReceivers.contains(comp)) {
6294 ris.remove(i);
6295 i--;
6296 }
6297 }
6298
6299 for (int i=0; i<ris.size(); i++) {
6300 ActivityInfo ai = ris.get(i).activityInfo;
6301 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6302 doneReceivers.add(comp);
6303 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006304 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006305 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006306 finisher = new IIntentReceiver.Stub() {
6307 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006308 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006309 boolean sticky) {
6310 // The raw IIntentReceiver interface is called
6311 // with the AM lock held, so redispatch to
6312 // execute our code without the lock.
6313 mHandler.post(new Runnable() {
6314 public void run() {
6315 synchronized (ActivityManagerService.this) {
6316 mDidUpdate = true;
6317 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006318 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006319 systemReady(goingCallback);
6320 }
6321 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006322 }
6323 };
6324 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006325 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006326 broadcastIntentLocked(null, null, intent, null, finisher,
6327 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006328 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006329 mWaitingUpdate = true;
6330 }
6331 }
6332 }
6333 if (mWaitingUpdate) {
6334 return;
6335 }
6336 mDidUpdate = true;
6337 }
6338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339 mSystemReady = true;
6340 if (!mStartRunning) {
6341 return;
6342 }
6343 }
6344
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006345 ArrayList<ProcessRecord> procsToKill = null;
6346 synchronized(mPidsSelfLocked) {
6347 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6348 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6349 if (!isAllowedWhileBooting(proc.info)){
6350 if (procsToKill == null) {
6351 procsToKill = new ArrayList<ProcessRecord>();
6352 }
6353 procsToKill.add(proc);
6354 }
6355 }
6356 }
6357
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006358 synchronized(this) {
6359 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006360 for (int i=procsToKill.size()-1; i>=0; i--) {
6361 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006362 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006363 removeProcessLocked(proc, true);
6364 }
6365 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006366
6367 // Now that we have cleaned up any update processes, we
6368 // are ready to start launching real processes and know that
6369 // we won't trample on them any more.
6370 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006371 }
6372
Joe Onorato8a9b2202010-02-26 18:56:32 -08006373 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006374 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 SystemClock.uptimeMillis());
6376
6377 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006378 // Make sure we have no pre-ready processes sitting around.
6379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6381 ResolveInfo ri = mContext.getPackageManager()
6382 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006383 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 CharSequence errorMsg = null;
6385 if (ri != null) {
6386 ActivityInfo ai = ri.activityInfo;
6387 ApplicationInfo app = ai.applicationInfo;
6388 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6389 mTopAction = Intent.ACTION_FACTORY_TEST;
6390 mTopData = null;
6391 mTopComponent = new ComponentName(app.packageName,
6392 ai.name);
6393 } else {
6394 errorMsg = mContext.getResources().getText(
6395 com.android.internal.R.string.factorytest_not_system);
6396 }
6397 } else {
6398 errorMsg = mContext.getResources().getText(
6399 com.android.internal.R.string.factorytest_no_action);
6400 }
6401 if (errorMsg != null) {
6402 mTopAction = null;
6403 mTopData = null;
6404 mTopComponent = null;
6405 Message msg = Message.obtain();
6406 msg.what = SHOW_FACTORY_ERROR_MSG;
6407 msg.getData().putCharSequence("msg", errorMsg);
6408 mHandler.sendMessage(msg);
6409 }
6410 }
6411 }
6412
6413 retrieveSettings();
6414
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006415 if (goingCallback != null) goingCallback.run();
6416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006417 synchronized (this) {
6418 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6419 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006420 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006421 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006422 if (apps != null) {
6423 int N = apps.size();
6424 int i;
6425 for (i=0; i<N; i++) {
6426 ApplicationInfo info
6427 = (ApplicationInfo)apps.get(i);
6428 if (info != null &&
6429 !info.packageName.equals("android")) {
6430 addAppLocked(info);
6431 }
6432 }
6433 }
6434 } catch (RemoteException ex) {
6435 // pm is in same process, this will never happen.
6436 }
6437 }
6438
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006439 // Start up initial activity.
6440 mBooting = true;
6441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006443 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006444 Message msg = Message.obtain();
6445 msg.what = SHOW_UID_ERROR_MSG;
6446 mHandler.sendMessage(msg);
6447 }
6448 } catch (RemoteException e) {
6449 }
6450
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006451 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006452 }
6453 }
6454
Dan Egnorb7f03672009-12-09 16:22:32 -08006455 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006456 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006457 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006458 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006459 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006460 startAppProblemLocked(app);
6461 app.stopFreezingAllLocked();
6462 return handleAppCrashLocked(app);
6463 }
6464
Dan Egnorb7f03672009-12-09 16:22:32 -08006465 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006466 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006468 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006469 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6470 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 startAppProblemLocked(app);
6472 app.stopFreezingAllLocked();
6473 }
6474
6475 /**
6476 * Generate a process error record, suitable for attachment to a ProcessRecord.
6477 *
6478 * @param app The ProcessRecord in which the error occurred.
6479 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6480 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006481 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006482 * @param shortMsg Short message describing the crash.
6483 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006484 * @param stackTrace Full crash stack trace, may be null.
6485 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 * @return Returns a fully-formed AppErrorStateInfo record.
6487 */
6488 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006489 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006492 report.condition = condition;
6493 report.processName = app.processName;
6494 report.pid = app.pid;
6495 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006496 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006497 report.shortMsg = shortMsg;
6498 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006499 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006500
6501 return report;
6502 }
6503
Dan Egnor42471dd2010-01-07 17:25:22 -08006504 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 synchronized (this) {
6506 app.crashing = false;
6507 app.crashingReport = null;
6508 app.notResponding = false;
6509 app.notRespondingReport = null;
6510 if (app.anrDialog == fromDialog) {
6511 app.anrDialog = null;
6512 }
6513 if (app.waitDialog == fromDialog) {
6514 app.waitDialog = null;
6515 }
6516 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006517 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006518 Slog.i(ActivityManagerService.TAG, "Killing "
6519 + app.processName + " (pid=" + app.pid + "): user's request");
6520 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6521 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 Process.killProcess(app.pid);
6523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006524 }
6525 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006526
Dan Egnorb7f03672009-12-09 16:22:32 -08006527 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006528 long now = SystemClock.uptimeMillis();
6529
6530 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6531 app.info.uid);
6532 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6533 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006534 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006535 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006536 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006537 app.info.processName, app.info.uid);
6538 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006539 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6540 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006541 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006542 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006543 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006544 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006545 }
6546 }
6547 if (!app.persistent) {
6548 // We don't want to start this process again until the user
6549 // explicitly does so... but for persistent process, we really
6550 // need to keep it running. If a persistent process is actually
6551 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006552 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 app.info.processName);
6554 mBadProcesses.put(app.info.processName, app.info.uid, now);
6555 app.bad = true;
6556 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6557 app.removed = true;
6558 removeProcessLocked(app, false);
6559 return false;
6560 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006561 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006562 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006563 if (r.app == app) {
6564 // If the top running activity is from this crashing
6565 // process, then terminate it to avoid getting in a loop.
6566 Slog.w(TAG, " Force finishing activity "
6567 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006568 int index = mMainStack.indexOfTokenLocked(r);
6569 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006570 Activity.RESULT_CANCELED, null, "crashed");
6571 // Also terminate an activities below it that aren't yet
6572 // stopped, to avoid a situation where one will get
6573 // re-start our crashing activity once it gets resumed again.
6574 index--;
6575 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006576 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006577 if (r.state == ActivityState.RESUMED
6578 || r.state == ActivityState.PAUSING
6579 || r.state == ActivityState.PAUSED) {
6580 if (!r.isHomeActivity) {
6581 Slog.w(TAG, " Force finishing activity "
6582 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006583 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006584 Activity.RESULT_CANCELED, null, "crashed");
6585 }
6586 }
6587 }
6588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006589 }
6590
6591 // Bump up the crash count of any services currently running in the proc.
6592 if (app.services.size() != 0) {
6593 // Any services running in the application need to be placed
6594 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006595 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006596 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006597 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006598 sr.crashCount++;
6599 }
6600 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006601
6602 // If the crashing process is what we consider to be the "home process" and it has been
6603 // replaced by a third-party app, clear the package preferred activities from packages
6604 // with a home activity running in the process to prevent a repeatedly crashing app
6605 // from blocking the user to manually clear the list.
6606 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6607 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6608 Iterator it = mHomeProcess.activities.iterator();
6609 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006610 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006611 if (r.isHomeActivity) {
6612 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6613 try {
6614 ActivityThread.getPackageManager()
6615 .clearPackagePreferredActivities(r.packageName);
6616 } catch (RemoteException c) {
6617 // pm is in same process, this will never happen.
6618 }
6619 }
6620 }
6621 }
6622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006623 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6624 return true;
6625 }
6626
6627 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006628 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6629 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006630 skipCurrentReceiverLocked(app);
6631 }
6632
6633 void skipCurrentReceiverLocked(ProcessRecord app) {
6634 boolean reschedule = false;
6635 BroadcastRecord r = app.curReceiver;
6636 if (r != null) {
6637 // The current broadcast is waiting for this app's receiver
6638 // to be finished. Looks like that's not going to happen, so
6639 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006640 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6642 r.resultExtras, r.resultAbort, true);
6643 reschedule = true;
6644 }
6645 r = mPendingBroadcast;
6646 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006647 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006648 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006649 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006650 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6651 r.resultExtras, r.resultAbort, true);
6652 reschedule = true;
6653 }
6654 if (reschedule) {
6655 scheduleBroadcastsLocked();
6656 }
6657 }
6658
Dan Egnor60d87622009-12-16 16:32:58 -08006659 /**
6660 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6661 * The application process will exit immediately after this call returns.
6662 * @param app object of the crashing app, null for the system server
6663 * @param crashInfo describing the exception
6664 */
6665 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6666 ProcessRecord r = findAppProcess(app);
6667
6668 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6669 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006670 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006671 crashInfo.exceptionClassName,
6672 crashInfo.exceptionMessage,
6673 crashInfo.throwFileName,
6674 crashInfo.throwLineNumber);
6675
Dan Egnor42471dd2010-01-07 17:25:22 -08006676 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006677
6678 crashApplication(r, crashInfo);
6679 }
6680
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006681 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006682 IBinder app,
6683 int violationMask,
6684 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006685 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006686
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006687 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006688 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006689 boolean logIt = true;
6690 synchronized (mAlreadyLoggedViolatedStacks) {
6691 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6692 logIt = false;
6693 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006694 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006695 // the relative pain numbers, without logging all
6696 // the stack traces repeatedly. We'd want to do
6697 // likewise in the client code, which also does
6698 // dup suppression, before the Binder call.
6699 } else {
6700 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6701 mAlreadyLoggedViolatedStacks.clear();
6702 }
6703 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6704 }
6705 }
6706 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006707 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006708 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006709 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006710
6711 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6712 AppErrorResult result = new AppErrorResult();
6713 synchronized (this) {
6714 final long origId = Binder.clearCallingIdentity();
6715
6716 Message msg = Message.obtain();
6717 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6718 HashMap<String, Object> data = new HashMap<String, Object>();
6719 data.put("result", result);
6720 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006721 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006722 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006723 msg.obj = data;
6724 mHandler.sendMessage(msg);
6725
6726 Binder.restoreCallingIdentity(origId);
6727 }
6728 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006729 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006730 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006731 }
6732
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006733 // Depending on the policy in effect, there could be a bunch of
6734 // these in quick succession so we try to batch these together to
6735 // minimize disk writes, number of dropbox entries, and maximize
6736 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006737 private void logStrictModeViolationToDropBox(
6738 ProcessRecord process,
6739 StrictMode.ViolationInfo info) {
6740 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006741 return;
6742 }
6743 final boolean isSystemApp = process == null ||
6744 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6745 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6746 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6747 final DropBoxManager dbox = (DropBoxManager)
6748 mContext.getSystemService(Context.DROPBOX_SERVICE);
6749
6750 // Exit early if the dropbox isn't configured to accept this report type.
6751 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6752
6753 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006754 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006755 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6756 synchronized (sb) {
6757 bufferWasEmpty = sb.length() == 0;
6758 appendDropBoxProcessHeaders(process, sb);
6759 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6760 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006761 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6762 if (info.violationNumThisLoop != 0) {
6763 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6764 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006765 if (info.numAnimationsRunning != 0) {
6766 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6767 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006768 if (info.broadcastIntentAction != null) {
6769 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6770 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006771 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006772 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006773 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006774 if (info.tags != null) {
6775 for (String tag : info.tags) {
6776 sb.append("Span-Tag: ").append(tag).append("\n");
6777 }
6778 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006779 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006780 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6781 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006782 }
6783 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006784
6785 // Only buffer up to ~64k. Various logging bits truncate
6786 // things at 128k.
6787 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006788 }
6789
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006790 // Flush immediately if the buffer's grown too large, or this
6791 // is a non-system app. Non-system apps are isolated with a
6792 // different tag & policy and not batched.
6793 //
6794 // Batching is useful during internal testing with
6795 // StrictMode settings turned up high. Without batching,
6796 // thousands of separate files could be created on boot.
6797 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006798 new Thread("Error dump: " + dropboxTag) {
6799 @Override
6800 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006801 String report;
6802 synchronized (sb) {
6803 report = sb.toString();
6804 sb.delete(0, sb.length());
6805 sb.trimToSize();
6806 }
6807 if (report.length() != 0) {
6808 dbox.addText(dropboxTag, report);
6809 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006810 }
6811 }.start();
6812 return;
6813 }
6814
6815 // System app batching:
6816 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006817 // An existing dropbox-writing thread is outstanding, so
6818 // we don't need to start it up. The existing thread will
6819 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006820 return;
6821 }
6822
6823 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6824 // (After this point, we shouldn't access AMS internal data structures.)
6825 new Thread("Error dump: " + dropboxTag) {
6826 @Override
6827 public void run() {
6828 // 5 second sleep to let stacks arrive and be batched together
6829 try {
6830 Thread.sleep(5000); // 5 seconds
6831 } catch (InterruptedException e) {}
6832
6833 String errorReport;
6834 synchronized (mStrictModeBuffer) {
6835 errorReport = mStrictModeBuffer.toString();
6836 if (errorReport.length() == 0) {
6837 return;
6838 }
6839 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6840 mStrictModeBuffer.trimToSize();
6841 }
6842 dbox.addText(dropboxTag, errorReport);
6843 }
6844 }.start();
6845 }
6846
Dan Egnor60d87622009-12-16 16:32:58 -08006847 /**
6848 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6849 * @param app object of the crashing app, null for the system server
6850 * @param tag reported by the caller
6851 * @param crashInfo describing the context of the error
6852 * @return true if the process should exit immediately (WTF is fatal)
6853 */
6854 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006855 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006856 ProcessRecord r = findAppProcess(app);
6857
6858 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6859 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006860 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006861 tag, crashInfo.exceptionMessage);
6862
Dan Egnor42471dd2010-01-07 17:25:22 -08006863 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006864
Doug Zongker43866e02010-01-07 12:09:54 -08006865 if (Settings.Secure.getInt(mContext.getContentResolver(),
6866 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006867 crashApplication(r, crashInfo);
6868 return true;
6869 } else {
6870 return false;
6871 }
6872 }
6873
6874 /**
6875 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6876 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6877 */
6878 private ProcessRecord findAppProcess(IBinder app) {
6879 if (app == null) {
6880 return null;
6881 }
6882
6883 synchronized (this) {
6884 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6885 final int NA = apps.size();
6886 for (int ia=0; ia<NA; ia++) {
6887 ProcessRecord p = apps.valueAt(ia);
6888 if (p.thread != null && p.thread.asBinder() == app) {
6889 return p;
6890 }
6891 }
6892 }
6893
Joe Onorato8a9b2202010-02-26 18:56:32 -08006894 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006895 return null;
6896 }
6897 }
6898
6899 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006900 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6901 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006902 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006903 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6904 // Note: ProcessRecord 'process' is guarded by the service
6905 // instance. (notably process.pkgList, which could otherwise change
6906 // concurrently during execution of this method)
6907 synchronized (this) {
6908 if (process == null || process.pid == MY_PID) {
6909 sb.append("Process: system_server\n");
6910 } else {
6911 sb.append("Process: ").append(process.processName).append("\n");
6912 }
6913 if (process == null) {
6914 return;
6915 }
Dan Egnora455d192010-03-12 08:52:28 -08006916 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006917 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006918 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6919 for (String pkg : process.pkgList) {
6920 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006921 try {
Dan Egnora455d192010-03-12 08:52:28 -08006922 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6923 if (pi != null) {
6924 sb.append(" v").append(pi.versionCode);
6925 if (pi.versionName != null) {
6926 sb.append(" (").append(pi.versionName).append(")");
6927 }
6928 }
6929 } catch (RemoteException e) {
6930 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006931 }
Dan Egnora455d192010-03-12 08:52:28 -08006932 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006933 }
Dan Egnora455d192010-03-12 08:52:28 -08006934 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006935 }
6936
6937 private static String processClass(ProcessRecord process) {
6938 if (process == null || process.pid == MY_PID) {
6939 return "system_server";
6940 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6941 return "system_app";
6942 } else {
6943 return "data_app";
6944 }
6945 }
6946
6947 /**
6948 * Write a description of an error (crash, WTF, ANR) to the drop box.
6949 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6950 * @param process which caused the error, null means the system server
6951 * @param activity which triggered the error, null if unknown
6952 * @param parent activity related to the error, null if unknown
6953 * @param subject line related to the error, null if absent
6954 * @param report in long form describing the error, null if absent
6955 * @param logFile to include in the report, null if none
6956 * @param crashInfo giving an application stack trace, null if absent
6957 */
6958 public void addErrorToDropBox(String eventType,
6959 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6960 final String report, final File logFile,
6961 final ApplicationErrorReport.CrashInfo crashInfo) {
6962 // NOTE -- this must never acquire the ActivityManagerService lock,
6963 // otherwise the watchdog may be prevented from resetting the system.
6964
6965 final String dropboxTag = processClass(process) + "_" + eventType;
6966 final DropBoxManager dbox = (DropBoxManager)
6967 mContext.getSystemService(Context.DROPBOX_SERVICE);
6968
6969 // Exit early if the dropbox isn't configured to accept this report type.
6970 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6971
6972 final StringBuilder sb = new StringBuilder(1024);
6973 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006974 if (activity != null) {
6975 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6976 }
6977 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6978 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6979 }
6980 if (parent != null && parent != activity) {
6981 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6982 }
6983 if (subject != null) {
6984 sb.append("Subject: ").append(subject).append("\n");
6985 }
6986 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02006987 if (Debug.isDebuggerConnected()) {
6988 sb.append("Debugger: Connected\n");
6989 }
Dan Egnora455d192010-03-12 08:52:28 -08006990 sb.append("\n");
6991
6992 // Do the rest in a worker thread to avoid blocking the caller on I/O
6993 // (After this point, we shouldn't access AMS internal data structures.)
6994 Thread worker = new Thread("Error dump: " + dropboxTag) {
6995 @Override
6996 public void run() {
6997 if (report != null) {
6998 sb.append(report);
6999 }
7000 if (logFile != null) {
7001 try {
7002 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7003 } catch (IOException e) {
7004 Slog.e(TAG, "Error reading " + logFile, e);
7005 }
7006 }
7007 if (crashInfo != null && crashInfo.stackTrace != null) {
7008 sb.append(crashInfo.stackTrace);
7009 }
7010
7011 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7012 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7013 if (lines > 0) {
7014 sb.append("\n");
7015
7016 // Merge several logcat streams, and take the last N lines
7017 InputStreamReader input = null;
7018 try {
7019 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7020 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7021 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7022
7023 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7024 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7025 input = new InputStreamReader(logcat.getInputStream());
7026
7027 int num;
7028 char[] buf = new char[8192];
7029 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7030 } catch (IOException e) {
7031 Slog.e(TAG, "Error running logcat", e);
7032 } finally {
7033 if (input != null) try { input.close(); } catch (IOException e) {}
7034 }
7035 }
7036
7037 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007038 }
Dan Egnora455d192010-03-12 08:52:28 -08007039 };
7040
7041 if (process == null || process.pid == MY_PID) {
7042 worker.run(); // We may be about to die -- need to run this synchronously
7043 } else {
7044 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007045 }
7046 }
7047
7048 /**
7049 * Bring up the "unexpected error" dialog box for a crashing app.
7050 * Deal with edge cases (intercepts from instrumented applications,
7051 * ActivityController, error intent receivers, that sort of thing).
7052 * @param r the application crashing
7053 * @param crashInfo describing the failure
7054 */
7055 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007056 long timeMillis = System.currentTimeMillis();
7057 String shortMsg = crashInfo.exceptionClassName;
7058 String longMsg = crashInfo.exceptionMessage;
7059 String stackTrace = crashInfo.stackTrace;
7060 if (shortMsg != null && longMsg != null) {
7061 longMsg = shortMsg + ": " + longMsg;
7062 } else if (shortMsg != null) {
7063 longMsg = shortMsg;
7064 }
7065
Dan Egnor60d87622009-12-16 16:32:58 -08007066 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007067 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007068 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007069 try {
7070 String name = r != null ? r.processName : null;
7071 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007072 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007073 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007074 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007075 + " at watcher's request");
7076 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007077 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007078 }
7079 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007080 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007081 }
7082 }
7083
7084 final long origId = Binder.clearCallingIdentity();
7085
7086 // If this process is running instrumentation, finish it.
7087 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007088 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007090 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7091 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 Bundle info = new Bundle();
7093 info.putString("shortMsg", shortMsg);
7094 info.putString("longMsg", longMsg);
7095 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7096 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007097 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007098 }
7099
Dan Egnor60d87622009-12-16 16:32:58 -08007100 // If we can't identify the process or it's already exceeded its crash quota,
7101 // quit right away without showing a crash dialog.
7102 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007103 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007104 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007105 }
7106
7107 Message msg = Message.obtain();
7108 msg.what = SHOW_ERROR_MSG;
7109 HashMap data = new HashMap();
7110 data.put("result", result);
7111 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007112 msg.obj = data;
7113 mHandler.sendMessage(msg);
7114
7115 Binder.restoreCallingIdentity(origId);
7116 }
7117
7118 int res = result.get();
7119
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007120 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007121 synchronized (this) {
7122 if (r != null) {
7123 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7124 SystemClock.uptimeMillis());
7125 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007126 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007127 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007128 }
7129 }
7130
7131 if (appErrorIntent != null) {
7132 try {
7133 mContext.startActivity(appErrorIntent);
7134 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007135 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007138 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007139
7140 Intent createAppErrorIntentLocked(ProcessRecord r,
7141 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7142 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007143 if (report == null) {
7144 return null;
7145 }
7146 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7147 result.setComponent(r.errorReportReceiver);
7148 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7149 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7150 return result;
7151 }
7152
Dan Egnorb7f03672009-12-09 16:22:32 -08007153 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7154 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007155 if (r.errorReportReceiver == null) {
7156 return null;
7157 }
7158
7159 if (!r.crashing && !r.notResponding) {
7160 return null;
7161 }
7162
Dan Egnorb7f03672009-12-09 16:22:32 -08007163 ApplicationErrorReport report = new ApplicationErrorReport();
7164 report.packageName = r.info.packageName;
7165 report.installerPackageName = r.errorReportReceiver.getPackageName();
7166 report.processName = r.processName;
7167 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007168 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007169
Dan Egnorb7f03672009-12-09 16:22:32 -08007170 if (r.crashing) {
7171 report.type = ApplicationErrorReport.TYPE_CRASH;
7172 report.crashInfo = crashInfo;
7173 } else if (r.notResponding) {
7174 report.type = ApplicationErrorReport.TYPE_ANR;
7175 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007176
Dan Egnorb7f03672009-12-09 16:22:32 -08007177 report.anrInfo.activity = r.notRespondingReport.tag;
7178 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7179 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007180 }
7181
Dan Egnorb7f03672009-12-09 16:22:32 -08007182 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007183 }
7184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007185 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7186 // assume our apps are happy - lazy create the list
7187 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7188
7189 synchronized (this) {
7190
7191 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007192 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7193 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7195 // This one's in trouble, so we'll generate a report for it
7196 // crashes are higher priority (in case there's a crash *and* an anr)
7197 ActivityManager.ProcessErrorStateInfo report = null;
7198 if (app.crashing) {
7199 report = app.crashingReport;
7200 } else if (app.notResponding) {
7201 report = app.notRespondingReport;
7202 }
7203
7204 if (report != null) {
7205 if (errList == null) {
7206 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7207 }
7208 errList.add(report);
7209 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007210 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007211 " crashing = " + app.crashing +
7212 " notResponding = " + app.notResponding);
7213 }
7214 }
7215 }
7216 }
7217
7218 return errList;
7219 }
7220
7221 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7222 // Lazy instantiation of list
7223 List<ActivityManager.RunningAppProcessInfo> runList = null;
7224 synchronized (this) {
7225 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007226 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7227 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7229 // Generate process state info for running application
7230 ActivityManager.RunningAppProcessInfo currApp =
7231 new ActivityManager.RunningAppProcessInfo(app.processName,
7232 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007233 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007234 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007235 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007236 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007237 if (app.persistent) {
7238 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007240 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007241 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007242 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7243 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7244 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007245 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7246 } else if (adj >= HOME_APP_ADJ) {
7247 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7248 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007249 } else if (adj >= SECONDARY_SERVER_ADJ) {
7250 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007251 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007252 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007253 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7254 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007255 } else if (adj >= VISIBLE_APP_ADJ) {
7256 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7257 } else {
7258 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7259 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007260 currApp.importanceReasonCode = app.adjTypeCode;
7261 if (app.adjSource instanceof ProcessRecord) {
7262 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007263 } else if (app.adjSource instanceof ActivityRecord) {
7264 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007265 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7266 }
7267 if (app.adjTarget instanceof ComponentName) {
7268 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7269 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007270 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 // + " lru=" + currApp.lru);
7272 if (runList == null) {
7273 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7274 }
7275 runList.add(currApp);
7276 }
7277 }
7278 }
7279 return runList;
7280 }
7281
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007282 public List<ApplicationInfo> getRunningExternalApplications() {
7283 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7284 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7285 if (runningApps != null && runningApps.size() > 0) {
7286 Set<String> extList = new HashSet<String>();
7287 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7288 if (app.pkgList != null) {
7289 for (String pkg : app.pkgList) {
7290 extList.add(pkg);
7291 }
7292 }
7293 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007294 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007295 for (String pkg : extList) {
7296 try {
7297 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7298 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7299 retList.add(info);
7300 }
7301 } catch (RemoteException e) {
7302 }
7303 }
7304 }
7305 return retList;
7306 }
7307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 @Override
7309 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007310 if (checkCallingPermission(android.Manifest.permission.DUMP)
7311 != PackageManager.PERMISSION_GRANTED) {
7312 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7313 + Binder.getCallingPid()
7314 + ", uid=" + Binder.getCallingUid()
7315 + " without permission "
7316 + android.Manifest.permission.DUMP);
7317 return;
7318 }
7319
7320 boolean dumpAll = false;
7321
7322 int opti = 0;
7323 while (opti < args.length) {
7324 String opt = args[opti];
7325 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7326 break;
7327 }
7328 opti++;
7329 if ("-a".equals(opt)) {
7330 dumpAll = true;
7331 } else if ("-h".equals(opt)) {
7332 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007333 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007334 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007335 pw.println(" a[ctivities]: activity stack state");
7336 pw.println(" b[roadcasts]: broadcast state");
7337 pw.println(" i[ntents]: pending intent state");
7338 pw.println(" p[rocesses]: process state");
7339 pw.println(" o[om]: out of memory management");
7340 pw.println(" prov[iders]: content provider state");
7341 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007342 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007343 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7344 pw.println(" a partial substring in a component name, or an");
7345 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007347 } else {
7348 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007349 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007350 }
7351
7352 // Is the caller requesting to dump a particular piece of data?
7353 if (opti < args.length) {
7354 String cmd = args[opti];
7355 opti++;
7356 if ("activities".equals(cmd) || "a".equals(cmd)) {
7357 synchronized (this) {
7358 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007359 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007360 return;
7361 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7362 synchronized (this) {
7363 dumpBroadcastsLocked(fd, pw, args, opti, true);
7364 }
7365 return;
7366 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7367 synchronized (this) {
7368 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7369 }
7370 return;
7371 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7372 synchronized (this) {
7373 dumpProcessesLocked(fd, pw, args, opti, true);
7374 }
7375 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007376 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7377 synchronized (this) {
7378 dumpOomLocked(fd, pw, args, opti, true);
7379 }
7380 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007381 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7382 synchronized (this) {
7383 dumpProvidersLocked(fd, pw, args, opti, true);
7384 }
7385 return;
7386 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007387 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007388 return;
7389 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7390 synchronized (this) {
7391 dumpServicesLocked(fd, pw, args, opti, true);
7392 }
7393 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007394 } else {
7395 // Dumping a single activity?
7396 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7397 return;
7398 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007399 pw.println("Bad activity command, or no activities match: " + cmd);
7400 pw.println("Use -h for help.");
7401 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007402 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007403 }
7404
7405 // No piece of data specified, dump everything.
7406 synchronized (this) {
7407 boolean needSep;
7408 if (dumpAll) {
7409 pw.println("Providers in Current Activity Manager State:");
7410 }
7411 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7412 if (needSep) {
7413 pw.println(" ");
7414 }
7415 if (dumpAll) {
7416 pw.println("-------------------------------------------------------------------------------");
7417 pw.println("Broadcasts in Current Activity Manager State:");
7418 }
7419 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7420 if (needSep) {
7421 pw.println(" ");
7422 }
7423 if (dumpAll) {
7424 pw.println("-------------------------------------------------------------------------------");
7425 pw.println("Services in Current Activity Manager State:");
7426 }
7427 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7428 if (needSep) {
7429 pw.println(" ");
7430 }
7431 if (dumpAll) {
7432 pw.println("-------------------------------------------------------------------------------");
7433 pw.println("PendingIntents in Current Activity Manager State:");
7434 }
7435 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7436 if (needSep) {
7437 pw.println(" ");
7438 }
7439 if (dumpAll) {
7440 pw.println("-------------------------------------------------------------------------------");
7441 pw.println("Activities in Current Activity Manager State:");
7442 }
7443 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7444 if (needSep) {
7445 pw.println(" ");
7446 }
7447 if (dumpAll) {
7448 pw.println("-------------------------------------------------------------------------------");
7449 pw.println("Processes in Current Activity Manager State:");
7450 }
7451 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7452 }
7453 }
7454
7455 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7456 int opti, boolean dumpAll, boolean needHeader) {
7457 if (needHeader) {
7458 pw.println(" Activity stack:");
7459 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007460 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007461 pw.println(" ");
7462 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007463 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7464 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007466 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007467 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007468 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007469 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007471 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007472 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007473 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007474 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007475 pw.println(" ");
7476 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007477 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007479
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007480 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007481 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7482 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007483 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007484 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007485
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007486 if (dumpAll && mRecentTasks.size() > 0) {
7487 pw.println(" ");
7488 pw.println("Recent tasks in Current Activity Manager State:");
7489
7490 final int N = mRecentTasks.size();
7491 for (int i=0; i<N; i++) {
7492 TaskRecord tr = mRecentTasks.get(i);
7493 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7494 pw.println(tr);
7495 mRecentTasks.get(i).dump(pw, " ");
7496 }
7497 }
7498
7499 pw.println(" ");
7500 pw.println(" mCurTask: " + mCurTask);
7501
7502 return true;
7503 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007504
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007505 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7506 int opti, boolean dumpAll) {
7507 boolean needSep = false;
7508 int numPers = 0;
7509
7510 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007511 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7512 final int NA = procs.size();
7513 for (int ia=0; ia<NA; ia++) {
7514 if (!needSep) {
7515 pw.println(" All known processes:");
7516 needSep = true;
7517 }
7518 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007519 pw.print(r.persistent ? " *PERS*" : " *APP*");
7520 pw.print(" UID "); pw.print(procs.keyAt(ia));
7521 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007522 r.dump(pw, " ");
7523 if (r.persistent) {
7524 numPers++;
7525 }
7526 }
7527 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007528 }
7529
7530 if (mLruProcesses.size() > 0) {
7531 if (needSep) pw.println(" ");
7532 needSep = true;
7533 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007534 dumpProcessOomList(pw, this, mLruProcesses, " ",
7535 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007536 needSep = true;
7537 }
7538
7539 synchronized (mPidsSelfLocked) {
7540 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007541 if (needSep) pw.println(" ");
7542 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007543 pw.println(" PID mappings:");
7544 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7545 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7546 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007547 }
7548 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007549 }
7550
7551 if (mForegroundProcesses.size() > 0) {
7552 if (needSep) pw.println(" ");
7553 needSep = true;
7554 pw.println(" Foreground Processes:");
7555 for (int i=0; i<mForegroundProcesses.size(); i++) {
7556 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7557 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007559 }
7560
7561 if (mPersistentStartingProcesses.size() > 0) {
7562 if (needSep) pw.println(" ");
7563 needSep = true;
7564 pw.println(" Persisent processes that are starting:");
7565 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007566 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007569 if (mStartingProcesses.size() > 0) {
7570 if (needSep) pw.println(" ");
7571 needSep = true;
7572 pw.println(" Processes that are starting:");
7573 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007574 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007577 if (mRemovedProcesses.size() > 0) {
7578 if (needSep) pw.println(" ");
7579 needSep = true;
7580 pw.println(" Processes that are being removed:");
7581 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007582 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007583 }
7584
7585 if (mProcessesOnHold.size() > 0) {
7586 if (needSep) pw.println(" ");
7587 needSep = true;
7588 pw.println(" Processes that are on old until the system is ready:");
7589 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007590 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592
Dianne Hackborn287952c2010-09-22 22:34:31 -07007593 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007594
7595 if (mProcessCrashTimes.getMap().size() > 0) {
7596 if (needSep) pw.println(" ");
7597 needSep = true;
7598 pw.println(" Time since processes crashed:");
7599 long now = SystemClock.uptimeMillis();
7600 for (Map.Entry<String, SparseArray<Long>> procs
7601 : mProcessCrashTimes.getMap().entrySet()) {
7602 SparseArray<Long> uids = procs.getValue();
7603 final int N = uids.size();
7604 for (int i=0; i<N; i++) {
7605 pw.print(" Process "); pw.print(procs.getKey());
7606 pw.print(" uid "); pw.print(uids.keyAt(i));
7607 pw.print(": last crashed ");
7608 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007609 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007610 }
7611 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007614 if (mBadProcesses.getMap().size() > 0) {
7615 if (needSep) pw.println(" ");
7616 needSep = true;
7617 pw.println(" Bad processes:");
7618 for (Map.Entry<String, SparseArray<Long>> procs
7619 : mBadProcesses.getMap().entrySet()) {
7620 SparseArray<Long> uids = procs.getValue();
7621 final int N = uids.size();
7622 for (int i=0; i<N; i++) {
7623 pw.print(" Bad process "); pw.print(procs.getKey());
7624 pw.print(" uid "); pw.print(uids.keyAt(i));
7625 pw.print(": crashed at time ");
7626 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007627 }
7628 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007629 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007630
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007631 pw.println(" ");
7632 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007633 if (mHeavyWeightProcess != null) {
7634 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7635 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007636 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007637 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007638 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7639 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7640 || mOrigWaitForDebugger) {
7641 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7642 + " mDebugTransient=" + mDebugTransient
7643 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7644 }
7645 if (mAlwaysFinishActivities || mController != null) {
7646 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7647 + " mController=" + mController);
7648 }
7649 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007651 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007652 + " mProcessesReady=" + mProcessesReady
7653 + " mSystemReady=" + mSystemReady);
7654 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007655 + " mBooted=" + mBooted
7656 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007657 pw.print(" mLastPowerCheckRealtime=");
7658 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7659 pw.println("");
7660 pw.print(" mLastPowerCheckUptime=");
7661 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7662 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007663 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7664 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007665 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007667
7668 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 }
7670
Dianne Hackborn287952c2010-09-22 22:34:31 -07007671 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7672 int opti, boolean needSep, boolean dumpAll) {
7673 if (mProcessesToGc.size() > 0) {
7674 if (needSep) pw.println(" ");
7675 needSep = true;
7676 pw.println(" Processes that are waiting to GC:");
7677 long now = SystemClock.uptimeMillis();
7678 for (int i=0; i<mProcessesToGc.size(); i++) {
7679 ProcessRecord proc = mProcessesToGc.get(i);
7680 pw.print(" Process "); pw.println(proc);
7681 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7682 pw.print(", last gced=");
7683 pw.print(now-proc.lastRequestedGc);
7684 pw.print(" ms ago, last lowMem=");
7685 pw.print(now-proc.lastLowMemory);
7686 pw.println(" ms ago");
7687
7688 }
7689 }
7690 return needSep;
7691 }
7692
7693 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7694 int opti, boolean dumpAll) {
7695 boolean needSep = false;
7696
7697 if (mLruProcesses.size() > 0) {
7698 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7699
7700 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7701 @Override
7702 public int compare(ProcessRecord object1, ProcessRecord object2) {
7703 if (object1.setAdj != object2.setAdj) {
7704 return object1.setAdj > object2.setAdj ? -1 : 1;
7705 }
7706 if (object1.setSchedGroup != object2.setSchedGroup) {
7707 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7708 }
7709 if (object1.keeping != object2.keeping) {
7710 return object1.keeping ? -1 : 1;
7711 }
7712 if (object1.pid != object2.pid) {
7713 return object1.pid > object2.pid ? -1 : 1;
7714 }
7715 return 0;
7716 }
7717 };
7718
7719 Collections.sort(procs, comparator);
7720
7721 if (needSep) pw.println(" ");
7722 needSep = true;
7723 pw.println(" Process OOM control:");
7724 dumpProcessOomList(pw, this, procs, " ",
7725 "Proc", "PERS", true);
7726 needSep = true;
7727 }
7728
7729 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7730
7731 pw.println(" ");
7732 pw.println(" mHomeProcess: " + mHomeProcess);
7733 if (mHeavyWeightProcess != null) {
7734 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7735 }
7736
7737 return true;
7738 }
7739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740 /**
7741 * There are three ways to call this:
7742 * - no service specified: dump all the services
7743 * - a flattened component name that matched an existing service was specified as the
7744 * first arg: dump that one service
7745 * - the first arg isn't the flattened component name of an existing service:
7746 * dump all services whose component contains the first arg as a substring
7747 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007748 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 String[] newArgs;
7750 String componentNameString;
7751 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007752 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007753 componentNameString = null;
7754 newArgs = EMPTY_STRING_ARRAY;
7755 r = null;
7756 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007757 componentNameString = args[opti];
7758 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007759 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007760 synchronized (this) {
7761 r = componentName != null ? mServices.get(componentName) : null;
7762 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007763 newArgs = new String[args.length - opti];
7764 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007765 }
7766
7767 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007768 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007769 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007770 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7771 synchronized (this) {
7772 for (ServiceRecord r1 : mServices.values()) {
7773 if (componentNameString == null
7774 || r1.name.flattenToString().contains(componentNameString)) {
7775 services.add(r1);
7776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777 }
7778 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007779 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007780 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 }
7783 }
7784
7785 /**
7786 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7787 * there is a thread associated with the service.
7788 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007789 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7790 pw.println("------------------------------------------------------------"
7791 + "-------------------");
7792 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007793 if (r.app != null && r.app.thread != null) {
7794 try {
7795 // flush anything that is already in the PrintWriter since the thread is going
7796 // to write to the file descriptor directly
7797 pw.flush();
7798 r.app.thread.dumpService(fd, r, args);
7799 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007800 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007801 } catch (RemoteException e) {
7802 pw.println("got a RemoteException while dumping the service");
7803 }
7804 }
7805 }
7806
Dianne Hackborn625ac272010-09-17 18:29:22 -07007807 /**
7808 * There are three things that cmd can be:
7809 * - a flattened component name that matched an existing activity
7810 * - the cmd arg isn't the flattened component name of an existing activity:
7811 * dump all activity whose component contains the cmd as a substring
7812 * - A hex number of the ActivityRecord object instance.
7813 */
7814 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7815 int opti, boolean dumpAll) {
7816 String[] newArgs;
7817 ComponentName componentName = ComponentName.unflattenFromString(name);
7818 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007819 if (componentName == null) {
7820 // Not a '/' separated full component name; maybe an object ID?
7821 try {
7822 objectId = Integer.parseInt(name, 16);
7823 name = null;
7824 componentName = null;
7825 } catch (RuntimeException e) {
7826 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007827 }
7828 newArgs = new String[args.length - opti];
7829 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7830
7831 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7832 synchronized (this) {
7833 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7834 if (componentName != null) {
7835 if (r1.intent.getComponent().equals(componentName)) {
7836 activities.add(r1);
7837 }
7838 } else if (name != null) {
7839 if (r1.intent.getComponent().flattenToString().contains(name)) {
7840 activities.add(r1);
7841 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007842 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007843 activities.add(r1);
7844 }
7845 }
7846 }
7847
7848 if (activities.size() <= 0) {
7849 return false;
7850 }
7851
Dianne Hackborn30d71892010-12-11 10:37:55 -08007852 TaskRecord lastTask = null;
7853 for (int i=activities.size()-1; i>=0; i--) {
7854 ActivityRecord r = (ActivityRecord)activities.get(i);
7855 if (lastTask != r.task) {
7856 lastTask = r.task;
7857 pw.print("* Task "); pw.print(lastTask.affinity);
7858 pw.print(" id="); pw.println(lastTask.taskId);
7859 if (dumpAll) {
7860 lastTask.dump(pw, " ");
7861 }
7862 }
7863 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007864 }
7865 return true;
7866 }
7867
7868 /**
7869 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7870 * there is a thread associated with the activity.
7871 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08007872 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
7873 ActivityRecord r, String[] args, boolean dumpAll) {
7874 synchronized (this) {
7875 pw.print(prefix); pw.print("* Activity ");
7876 pw.print(Integer.toHexString(System.identityHashCode(r)));
7877 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
7878 if (r.app != null) pw.println(r.app.pid);
7879 else pw.println("(not running)");
7880 if (dumpAll) {
7881 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007882 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007883 }
7884 if (r.app != null && r.app.thread != null) {
7885 try {
7886 // flush anything that is already in the PrintWriter since the thread is going
7887 // to write to the file descriptor directly
7888 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08007889 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007890 pw.flush();
7891 } catch (RemoteException e) {
7892 pw.println("got a RemoteException while dumping the activity");
7893 }
7894 }
7895 }
7896
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007897 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7898 int opti, boolean dumpAll) {
7899 boolean needSep = false;
7900
7901 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007902 if (mRegisteredReceivers.size() > 0) {
7903 pw.println(" ");
7904 pw.println(" Registered Receivers:");
7905 Iterator it = mRegisteredReceivers.values().iterator();
7906 while (it.hasNext()) {
7907 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007908 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007909 r.dump(pw, " ");
7910 }
7911 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007913 pw.println(" ");
7914 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007915 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007916 needSep = true;
7917 }
7918
7919 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7920 || mPendingBroadcast != null) {
7921 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007922 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007923 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007924 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007925 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7926 pw.println(" Broadcast #" + i + ":");
7927 mParallelBroadcasts.get(i).dump(pw, " ");
7928 }
7929 if (mOrderedBroadcasts.size() > 0) {
7930 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007931 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007932 }
7933 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7934 pw.println(" Serialized Broadcast #" + i + ":");
7935 mOrderedBroadcasts.get(i).dump(pw, " ");
7936 }
7937 pw.println(" ");
7938 pw.println(" Pending broadcast:");
7939 if (mPendingBroadcast != null) {
7940 mPendingBroadcast.dump(pw, " ");
7941 } else {
7942 pw.println(" (null)");
7943 }
7944 needSep = true;
7945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007947 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007949 pw.println(" Historical broadcasts:");
7950 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7951 BroadcastRecord r = mBroadcastHistory[i];
7952 if (r == null) {
7953 break;
7954 }
7955 pw.println(" Historical Broadcast #" + i + ":");
7956 r.dump(pw, " ");
7957 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007958 needSep = true;
7959 }
7960
7961 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007962 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007963 pw.println(" Sticky broadcasts:");
7964 StringBuilder sb = new StringBuilder(128);
7965 for (Map.Entry<String, ArrayList<Intent>> ent
7966 : mStickyBroadcasts.entrySet()) {
7967 pw.print(" * Sticky action "); pw.print(ent.getKey());
7968 pw.println(":");
7969 ArrayList<Intent> intents = ent.getValue();
7970 final int N = intents.size();
7971 for (int i=0; i<N; i++) {
7972 sb.setLength(0);
7973 sb.append(" Intent: ");
7974 intents.get(i).toShortString(sb, true, false);
7975 pw.println(sb.toString());
7976 Bundle bundle = intents.get(i).getExtras();
7977 if (bundle != null) {
7978 pw.print(" ");
7979 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 }
7981 }
7982 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007983 needSep = true;
7984 }
7985
7986 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007988 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007989 pw.println(" mHandler:");
7990 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007991 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007992 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007993
7994 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007995 }
7996
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007997 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7998 int opti, boolean dumpAll) {
7999 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008000
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008001 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008002 if (mServices.size() > 0) {
8003 pw.println(" Active services:");
8004 Iterator<ServiceRecord> it = mServices.values().iterator();
8005 while (it.hasNext()) {
8006 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008007 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008008 r.dump(pw, " ");
8009 }
8010 needSep = true;
8011 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008012 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008013
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008014 if (mPendingServices.size() > 0) {
8015 if (needSep) pw.println(" ");
8016 pw.println(" Pending services:");
8017 for (int i=0; i<mPendingServices.size(); i++) {
8018 ServiceRecord r = mPendingServices.get(i);
8019 pw.print(" * Pending "); pw.println(r);
8020 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008022 needSep = true;
8023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008025 if (mRestartingServices.size() > 0) {
8026 if (needSep) pw.println(" ");
8027 pw.println(" Restarting services:");
8028 for (int i=0; i<mRestartingServices.size(); i++) {
8029 ServiceRecord r = mRestartingServices.get(i);
8030 pw.print(" * Restarting "); pw.println(r);
8031 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008033 needSep = true;
8034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008035
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008036 if (mStoppingServices.size() > 0) {
8037 if (needSep) pw.println(" ");
8038 pw.println(" Stopping services:");
8039 for (int i=0; i<mStoppingServices.size(); i++) {
8040 ServiceRecord r = mStoppingServices.get(i);
8041 pw.print(" * Stopping "); pw.println(r);
8042 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008043 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008044 needSep = true;
8045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008047 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 if (mServiceConnections.size() > 0) {
8049 if (needSep) pw.println(" ");
8050 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008051 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 = mServiceConnections.values().iterator();
8053 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008054 ArrayList<ConnectionRecord> r = it.next();
8055 for (int i=0; i<r.size(); i++) {
8056 pw.print(" * "); pw.println(r.get(i));
8057 r.get(i).dump(pw, " ");
8058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008059 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008060 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008061 }
8062 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008063
8064 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008065 }
8066
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008067 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8068 int opti, boolean dumpAll) {
8069 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008070
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008071 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 if (mProvidersByClass.size() > 0) {
8073 if (needSep) pw.println(" ");
8074 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008075 Iterator<Map.Entry<String, ContentProviderRecord>> it
8076 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008078 Map.Entry<String, ContentProviderRecord> e = it.next();
8079 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008080 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 r.dump(pw, " ");
8082 }
8083 needSep = true;
8084 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008085
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008086 if (mProvidersByName.size() > 0) {
8087 pw.println(" ");
8088 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008089 Iterator<Map.Entry<String, ContentProviderRecord>> it
8090 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008091 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008092 Map.Entry<String, ContentProviderRecord> e = it.next();
8093 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008094 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8095 pw.println(r);
8096 }
8097 needSep = true;
8098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008099 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008100
8101 if (mLaunchingProviders.size() > 0) {
8102 if (needSep) pw.println(" ");
8103 pw.println(" Launching content providers:");
8104 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8105 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8106 pw.println(mLaunchingProviders.get(i));
8107 }
8108 needSep = true;
8109 }
8110
8111 if (mGrantedUriPermissions.size() > 0) {
8112 pw.println();
8113 pw.println("Granted Uri Permissions:");
8114 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8115 int uid = mGrantedUriPermissions.keyAt(i);
8116 HashMap<Uri, UriPermission> perms
8117 = mGrantedUriPermissions.valueAt(i);
8118 pw.print(" * UID "); pw.print(uid);
8119 pw.println(" holds:");
8120 for (UriPermission perm : perms.values()) {
8121 pw.print(" "); pw.println(perm);
8122 perm.dump(pw, " ");
8123 }
8124 }
8125 needSep = true;
8126 }
8127
8128 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008129 }
8130
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008131 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8132 int opti, boolean dumpAll) {
8133 boolean needSep = false;
8134
8135 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008136 if (this.mIntentSenderRecords.size() > 0) {
8137 Iterator<WeakReference<PendingIntentRecord>> it
8138 = mIntentSenderRecords.values().iterator();
8139 while (it.hasNext()) {
8140 WeakReference<PendingIntentRecord> ref = it.next();
8141 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008142 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008144 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145 rec.dump(pw, " ");
8146 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008147 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008148 }
8149 }
8150 }
8151 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008152
8153 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008154 }
8155
8156 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008157 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008158 TaskRecord lastTask = null;
8159 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008160 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008161 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 if (lastTask != r.task) {
8163 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008164 pw.print(prefix);
8165 pw.print(full ? "* " : " ");
8166 pw.println(lastTask);
8167 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008168 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008170 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008171 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8172 pw.print(" #"); pw.print(i); pw.print(": ");
8173 pw.println(r);
8174 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008175 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008177 }
8178 }
8179
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008180 private static String buildOomTag(String prefix, String space, int val, int base) {
8181 if (val == base) {
8182 if (space == null) return prefix;
8183 return prefix + " ";
8184 }
8185 return prefix + "+" + Integer.toString(val-base);
8186 }
8187
8188 private static final int dumpProcessList(PrintWriter pw,
8189 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008190 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008192 final int N = list.size()-1;
8193 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008194 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008195 pw.println(String.format("%s%s #%2d: %s",
8196 prefix, (r.persistent ? persistentLabel : normalLabel),
8197 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008198 if (r.persistent) {
8199 numPers++;
8200 }
8201 }
8202 return numPers;
8203 }
8204
Dianne Hackborn287952c2010-09-22 22:34:31 -07008205 private static final void dumpProcessOomList(PrintWriter pw,
8206 ActivityManagerService service, List<ProcessRecord> list,
8207 String prefix, String normalLabel, String persistentLabel,
8208 boolean inclDetails) {
8209
8210 final long curRealtime = SystemClock.elapsedRealtime();
8211 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8212 final long curUptime = SystemClock.uptimeMillis();
8213 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8214
8215 final int N = list.size()-1;
8216 for (int i=N; i>=0; i--) {
8217 ProcessRecord r = list.get(i);
8218 String oomAdj;
8219 if (r.setAdj >= EMPTY_APP_ADJ) {
8220 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8221 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8222 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8223 } else if (r.setAdj >= HOME_APP_ADJ) {
8224 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8225 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8226 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8227 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8228 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8229 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8230 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8231 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8232 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8233 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8234 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8235 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8236 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8237 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8238 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8239 } else if (r.setAdj >= SYSTEM_ADJ) {
8240 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8241 } else {
8242 oomAdj = Integer.toString(r.setAdj);
8243 }
8244 String schedGroup;
8245 switch (r.setSchedGroup) {
8246 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8247 schedGroup = "B";
8248 break;
8249 case Process.THREAD_GROUP_DEFAULT:
8250 schedGroup = "F";
8251 break;
8252 default:
8253 schedGroup = Integer.toString(r.setSchedGroup);
8254 break;
8255 }
8256 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8257 prefix, (r.persistent ? persistentLabel : normalLabel),
8258 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8259 if (r.adjSource != null || r.adjTarget != null) {
8260 pw.print(prefix);
8261 pw.print(" ");
8262 if (r.adjTarget instanceof ComponentName) {
8263 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8264 } else if (r.adjTarget != null) {
8265 pw.print(r.adjTarget.toString());
8266 } else {
8267 pw.print("{null}");
8268 }
8269 pw.print("<=");
8270 if (r.adjSource instanceof ProcessRecord) {
8271 pw.print("Proc{");
8272 pw.print(((ProcessRecord)r.adjSource).toShortString());
8273 pw.println("}");
8274 } else if (r.adjSource != null) {
8275 pw.println(r.adjSource.toString());
8276 } else {
8277 pw.println("{null}");
8278 }
8279 }
8280 if (inclDetails) {
8281 pw.print(prefix);
8282 pw.print(" ");
8283 pw.print("oom: max="); pw.print(r.maxAdj);
8284 pw.print(" hidden="); pw.print(r.hiddenAdj);
8285 pw.print(" curRaw="); pw.print(r.curRawAdj);
8286 pw.print(" setRaw="); pw.print(r.setRawAdj);
8287 pw.print(" cur="); pw.print(r.curAdj);
8288 pw.print(" set="); pw.println(r.setAdj);
8289 pw.print(prefix);
8290 pw.print(" ");
8291 pw.print("keeping="); pw.print(r.keeping);
8292 pw.print(" hidden="); pw.print(r.hidden);
8293 pw.print(" empty="); pw.println(r.empty);
8294
8295 if (!r.keeping) {
8296 if (r.lastWakeTime != 0) {
8297 long wtime;
8298 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8299 synchronized (stats) {
8300 wtime = stats.getProcessWakeTime(r.info.uid,
8301 r.pid, curRealtime);
8302 }
8303 long timeUsed = wtime - r.lastWakeTime;
8304 pw.print(prefix);
8305 pw.print(" ");
8306 pw.print("keep awake over ");
8307 TimeUtils.formatDuration(realtimeSince, pw);
8308 pw.print(" used ");
8309 TimeUtils.formatDuration(timeUsed, pw);
8310 pw.print(" (");
8311 pw.print((timeUsed*100)/realtimeSince);
8312 pw.println("%)");
8313 }
8314 if (r.lastCpuTime != 0) {
8315 long timeUsed = r.curCpuTime - r.lastCpuTime;
8316 pw.print(prefix);
8317 pw.print(" ");
8318 pw.print("run cpu over ");
8319 TimeUtils.formatDuration(uptimeSince, pw);
8320 pw.print(" used ");
8321 TimeUtils.formatDuration(timeUsed, pw);
8322 pw.print(" (");
8323 pw.print((timeUsed*100)/uptimeSince);
8324 pw.println("%)");
8325 }
8326 }
8327 }
8328 }
8329 }
8330
Dianne Hackborn472ad872010-04-07 17:31:48 -07008331 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008332 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008333 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008334 long uptime = SystemClock.uptimeMillis();
8335 long realtime = SystemClock.elapsedRealtime();
8336
8337 if (isCheckinRequest) {
8338 // short checkin version
8339 pw.println(uptime + "," + realtime);
8340 pw.flush();
8341 } else {
8342 pw.println("Applications Memory Usage (kB):");
8343 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8344 }
8345 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8346 ProcessRecord r = (ProcessRecord)list.get(i);
8347 if (r.thread != null) {
8348 if (!isCheckinRequest) {
8349 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8350 pw.flush();
8351 }
8352 try {
8353 r.thread.asBinder().dump(fd, args);
8354 } catch (RemoteException e) {
8355 if (!isCheckinRequest) {
8356 pw.println("Got RemoteException!");
8357 pw.flush();
8358 }
8359 }
8360 }
8361 }
8362 }
8363
8364 /**
8365 * Searches array of arguments for the specified string
8366 * @param args array of argument strings
8367 * @param value value to search for
8368 * @return true if the value is contained in the array
8369 */
8370 private static boolean scanArgs(String[] args, String value) {
8371 if (args != null) {
8372 for (String arg : args) {
8373 if (value.equals(arg)) {
8374 return true;
8375 }
8376 }
8377 }
8378 return false;
8379 }
8380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008381 private final void killServicesLocked(ProcessRecord app,
8382 boolean allowRestart) {
8383 // Report disconnected services.
8384 if (false) {
8385 // XXX we are letting the client link to the service for
8386 // death notifications.
8387 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008388 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008389 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008390 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008391 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008392 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 = r.connections.values().iterator();
8394 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008395 ArrayList<ConnectionRecord> cl = jt.next();
8396 for (int i=0; i<cl.size(); i++) {
8397 ConnectionRecord c = cl.get(i);
8398 if (c.binding.client != app) {
8399 try {
8400 //c.conn.connected(r.className, null);
8401 } catch (Exception e) {
8402 // todo: this should be asynchronous!
8403 Slog.w(TAG, "Exception thrown disconnected servce "
8404 + r.shortName
8405 + " from app " + app.processName, e);
8406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 }
8408 }
8409 }
8410 }
8411 }
8412 }
8413 }
8414
8415 // Clean up any connections this application has to other services.
8416 if (app.connections.size() > 0) {
8417 Iterator<ConnectionRecord> it = app.connections.iterator();
8418 while (it.hasNext()) {
8419 ConnectionRecord r = it.next();
8420 removeConnectionLocked(r, app, null);
8421 }
8422 }
8423 app.connections.clear();
8424
8425 if (app.services.size() != 0) {
8426 // Any services running in the application need to be placed
8427 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008428 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008429 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008430 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008431 synchronized (sr.stats.getBatteryStats()) {
8432 sr.stats.stopLaunchedLocked();
8433 }
8434 sr.app = null;
8435 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008436 if (mStoppingServices.remove(sr)) {
8437 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8438 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008439
8440 boolean hasClients = sr.bindings.size() > 0;
8441 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008442 Iterator<IntentBindRecord> bindings
8443 = sr.bindings.values().iterator();
8444 while (bindings.hasNext()) {
8445 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008446 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008447 + ": shouldUnbind=" + b.hasBound);
8448 b.binder = null;
8449 b.requested = b.received = b.hasBound = false;
8450 }
8451 }
8452
8453 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008454 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008455 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008456 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008457 sr.crashCount, sr.shortName, app.pid);
8458 bringDownServiceLocked(sr, true);
8459 } else if (!allowRestart) {
8460 bringDownServiceLocked(sr, true);
8461 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008462 boolean canceled = scheduleServiceRestartLocked(sr, true);
8463
8464 // Should the service remain running? Note that in the
8465 // extreme case of so many attempts to deliver a command
8466 // that it failed, that we also will stop it here.
8467 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8468 if (sr.pendingStarts.size() == 0) {
8469 sr.startRequested = false;
8470 if (!hasClients) {
8471 // Whoops, no reason to restart!
8472 bringDownServiceLocked(sr, true);
8473 }
8474 }
8475 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008476 }
8477 }
8478
8479 if (!allowRestart) {
8480 app.services.clear();
8481 }
8482 }
8483
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008484 // Make sure we have no more records on the stopping list.
8485 int i = mStoppingServices.size();
8486 while (i > 0) {
8487 i--;
8488 ServiceRecord sr = mStoppingServices.get(i);
8489 if (sr.app == app) {
8490 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008491 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008492 }
8493 }
8494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008495 app.executingServices.clear();
8496 }
8497
8498 private final void removeDyingProviderLocked(ProcessRecord proc,
8499 ContentProviderRecord cpr) {
8500 synchronized (cpr) {
8501 cpr.launchingApp = null;
8502 cpr.notifyAll();
8503 }
8504
8505 mProvidersByClass.remove(cpr.info.name);
8506 String names[] = cpr.info.authority.split(";");
8507 for (int j = 0; j < names.length; j++) {
8508 mProvidersByName.remove(names[j]);
8509 }
8510
8511 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8512 while (cit.hasNext()) {
8513 ProcessRecord capp = cit.next();
8514 if (!capp.persistent && capp.thread != null
8515 && capp.pid != 0
8516 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008517 Slog.i(TAG, "Kill " + capp.processName
8518 + " (pid " + capp.pid + "): provider " + cpr.info.name
8519 + " in dying process " + proc.processName);
8520 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8521 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 Process.killProcess(capp.pid);
8523 }
8524 }
8525
8526 mLaunchingProviders.remove(cpr);
8527 }
8528
8529 /**
8530 * Main code for cleaning up a process when it has gone away. This is
8531 * called both as a result of the process dying, or directly when stopping
8532 * a process when running in single process mode.
8533 */
8534 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8535 boolean restarting, int index) {
8536 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008537 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 }
8539
Dianne Hackborn36124872009-10-08 16:22:03 -07008540 mProcessesToGc.remove(app);
8541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 // Dismiss any open dialogs.
8543 if (app.crashDialog != null) {
8544 app.crashDialog.dismiss();
8545 app.crashDialog = null;
8546 }
8547 if (app.anrDialog != null) {
8548 app.anrDialog.dismiss();
8549 app.anrDialog = null;
8550 }
8551 if (app.waitDialog != null) {
8552 app.waitDialog.dismiss();
8553 app.waitDialog = null;
8554 }
8555
8556 app.crashing = false;
8557 app.notResponding = false;
8558
8559 app.resetPackageList();
8560 app.thread = null;
8561 app.forcingToForeground = null;
8562 app.foregroundServices = false;
8563
8564 killServicesLocked(app, true);
8565
8566 boolean restart = false;
8567
8568 int NL = mLaunchingProviders.size();
8569
8570 // Remove published content providers.
8571 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008572 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008573 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008574 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 cpr.provider = null;
8576 cpr.app = null;
8577
8578 // See if someone is waiting for this provider... in which
8579 // case we don't remove it, but just let it restart.
8580 int i = 0;
8581 if (!app.bad) {
8582 for (; i<NL; i++) {
8583 if (mLaunchingProviders.get(i) == cpr) {
8584 restart = true;
8585 break;
8586 }
8587 }
8588 } else {
8589 i = NL;
8590 }
8591
8592 if (i >= NL) {
8593 removeDyingProviderLocked(app, cpr);
8594 NL = mLaunchingProviders.size();
8595 }
8596 }
8597 app.pubProviders.clear();
8598 }
8599
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008600 // Take care of any launching providers waiting for this process.
8601 if (checkAppInLaunchingProvidersLocked(app, false)) {
8602 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008603 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008605 // Unregister from connected content providers.
8606 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008607 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008608 while (it.hasNext()) {
8609 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8610 cpr.clients.remove(app);
8611 }
8612 app.conProviders.clear();
8613 }
8614
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008615 // At this point there may be remaining entries in mLaunchingProviders
8616 // where we were the only one waiting, so they are no longer of use.
8617 // Look for these and clean up if found.
8618 // XXX Commented out for now. Trying to figure out a way to reproduce
8619 // the actual situation to identify what is actually going on.
8620 if (false) {
8621 for (int i=0; i<NL; i++) {
8622 ContentProviderRecord cpr = (ContentProviderRecord)
8623 mLaunchingProviders.get(i);
8624 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8625 synchronized (cpr) {
8626 cpr.launchingApp = null;
8627 cpr.notifyAll();
8628 }
8629 }
8630 }
8631 }
8632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 skipCurrentReceiverLocked(app);
8634
8635 // Unregister any receivers.
8636 if (app.receivers.size() > 0) {
8637 Iterator<ReceiverList> it = app.receivers.iterator();
8638 while (it.hasNext()) {
8639 removeReceiverLocked(it.next());
8640 }
8641 app.receivers.clear();
8642 }
8643
Christopher Tate181fafa2009-05-14 11:12:14 -07008644 // If the app is undergoing backup, tell the backup manager about it
8645 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008646 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008647 try {
8648 IBackupManager bm = IBackupManager.Stub.asInterface(
8649 ServiceManager.getService(Context.BACKUP_SERVICE));
8650 bm.agentDisconnected(app.info.packageName);
8651 } catch (RemoteException e) {
8652 // can't happen; backup manager is local
8653 }
8654 }
8655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 // If the caller is restarting this app, then leave it in its
8657 // current lists and let the caller take care of it.
8658 if (restarting) {
8659 return;
8660 }
8661
8662 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008663 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008664 "Removing non-persistent process during cleanup: " + app);
8665 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008666 if (mHeavyWeightProcess == app) {
8667 mHeavyWeightProcess = null;
8668 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008670 } else if (!app.removed) {
8671 // This app is persistent, so we need to keep its record around.
8672 // If it is not already on the pending app list, add it there
8673 // and start a new process for it.
8674 app.thread = null;
8675 app.forcingToForeground = null;
8676 app.foregroundServices = false;
8677 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8678 mPersistentStartingProcesses.add(app);
8679 restart = true;
8680 }
8681 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008682 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8683 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008684 mProcessesOnHold.remove(app);
8685
The Android Open Source Project4df24232009-03-05 14:34:35 -08008686 if (app == mHomeProcess) {
8687 mHomeProcess = null;
8688 }
8689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008690 if (restart) {
8691 // We have components that still need to be running in the
8692 // process, so re-launch it.
8693 mProcessNames.put(app.processName, app.info.uid, app);
8694 startProcessLocked(app, "restart", app.processName);
8695 } else if (app.pid > 0 && app.pid != MY_PID) {
8696 // Goodbye!
8697 synchronized (mPidsSelfLocked) {
8698 mPidsSelfLocked.remove(app.pid);
8699 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8700 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008701 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008702 }
8703 }
8704
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008705 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8706 // Look through the content providers we are waiting to have launched,
8707 // and if any run in this process then either schedule a restart of
8708 // the process or kill the client waiting for it if this process has
8709 // gone bad.
8710 int NL = mLaunchingProviders.size();
8711 boolean restart = false;
8712 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008713 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008714 if (cpr.launchingApp == app) {
8715 if (!alwaysBad && !app.bad) {
8716 restart = true;
8717 } else {
8718 removeDyingProviderLocked(app, cpr);
8719 NL = mLaunchingProviders.size();
8720 }
8721 }
8722 }
8723 return restart;
8724 }
8725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008726 // =========================================================
8727 // SERVICES
8728 // =========================================================
8729
8730 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8731 ActivityManager.RunningServiceInfo info =
8732 new ActivityManager.RunningServiceInfo();
8733 info.service = r.name;
8734 if (r.app != null) {
8735 info.pid = r.app.pid;
8736 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008737 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 info.process = r.processName;
8739 info.foreground = r.isForeground;
8740 info.activeSince = r.createTime;
8741 info.started = r.startRequested;
8742 info.clientCount = r.connections.size();
8743 info.crashCount = r.crashCount;
8744 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008745 if (r.isForeground) {
8746 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8747 }
8748 if (r.startRequested) {
8749 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8750 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008751 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008752 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8753 }
8754 if (r.app != null && r.app.persistent) {
8755 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8756 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008757
8758 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8759 for (int i=0; i<connl.size(); i++) {
8760 ConnectionRecord conn = connl.get(i);
8761 if (conn.clientLabel != 0) {
8762 info.clientPackage = conn.binding.client.info.packageName;
8763 info.clientLabel = conn.clientLabel;
8764 return info;
8765 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008766 }
8767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008768 return info;
8769 }
8770
8771 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8772 int flags) {
8773 synchronized (this) {
8774 ArrayList<ActivityManager.RunningServiceInfo> res
8775 = new ArrayList<ActivityManager.RunningServiceInfo>();
8776
8777 if (mServices.size() > 0) {
8778 Iterator<ServiceRecord> it = mServices.values().iterator();
8779 while (it.hasNext() && res.size() < maxNum) {
8780 res.add(makeRunningServiceInfoLocked(it.next()));
8781 }
8782 }
8783
8784 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8785 ServiceRecord r = mRestartingServices.get(i);
8786 ActivityManager.RunningServiceInfo info =
8787 makeRunningServiceInfoLocked(r);
8788 info.restarting = r.nextRestartTime;
8789 res.add(info);
8790 }
8791
8792 return res;
8793 }
8794 }
8795
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008796 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8797 synchronized (this) {
8798 ServiceRecord r = mServices.get(name);
8799 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008800 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8801 for (int i=0; i<conn.size(); i++) {
8802 if (conn.get(i).clientIntent != null) {
8803 return conn.get(i).clientIntent;
8804 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008805 }
8806 }
8807 }
8808 }
8809 return null;
8810 }
8811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 private final ServiceRecord findServiceLocked(ComponentName name,
8813 IBinder token) {
8814 ServiceRecord r = mServices.get(name);
8815 return r == token ? r : null;
8816 }
8817
8818 private final class ServiceLookupResult {
8819 final ServiceRecord record;
8820 final String permission;
8821
8822 ServiceLookupResult(ServiceRecord _record, String _permission) {
8823 record = _record;
8824 permission = _permission;
8825 }
8826 };
8827
8828 private ServiceLookupResult findServiceLocked(Intent service,
8829 String resolvedType) {
8830 ServiceRecord r = null;
8831 if (service.getComponent() != null) {
8832 r = mServices.get(service.getComponent());
8833 }
8834 if (r == null) {
8835 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8836 r = mServicesByIntent.get(filter);
8837 }
8838
8839 if (r == null) {
8840 try {
8841 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008842 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008843 service, resolvedType, 0);
8844 ServiceInfo sInfo =
8845 rInfo != null ? rInfo.serviceInfo : null;
8846 if (sInfo == null) {
8847 return null;
8848 }
8849
8850 ComponentName name = new ComponentName(
8851 sInfo.applicationInfo.packageName, sInfo.name);
8852 r = mServices.get(name);
8853 } catch (RemoteException ex) {
8854 // pm is in same process, this will never happen.
8855 }
8856 }
8857 if (r != null) {
8858 int callingPid = Binder.getCallingPid();
8859 int callingUid = Binder.getCallingUid();
8860 if (checkComponentPermission(r.permission,
8861 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8862 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008863 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008864 + " from pid=" + callingPid
8865 + ", uid=" + callingUid
8866 + " requires " + r.permission);
8867 return new ServiceLookupResult(null, r.permission);
8868 }
8869 return new ServiceLookupResult(r, null);
8870 }
8871 return null;
8872 }
8873
8874 private class ServiceRestarter implements Runnable {
8875 private ServiceRecord mService;
8876
8877 void setService(ServiceRecord service) {
8878 mService = service;
8879 }
8880
8881 public void run() {
8882 synchronized(ActivityManagerService.this) {
8883 performServiceRestartLocked(mService);
8884 }
8885 }
8886 }
8887
8888 private ServiceLookupResult retrieveServiceLocked(Intent service,
8889 String resolvedType, int callingPid, int callingUid) {
8890 ServiceRecord r = null;
8891 if (service.getComponent() != null) {
8892 r = mServices.get(service.getComponent());
8893 }
8894 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8895 r = mServicesByIntent.get(filter);
8896 if (r == null) {
8897 try {
8898 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008899 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008900 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008901 ServiceInfo sInfo =
8902 rInfo != null ? rInfo.serviceInfo : null;
8903 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008904 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008905 ": not found");
8906 return null;
8907 }
8908
8909 ComponentName name = new ComponentName(
8910 sInfo.applicationInfo.packageName, sInfo.name);
8911 r = mServices.get(name);
8912 if (r == null) {
8913 filter = new Intent.FilterComparison(service.cloneFilter());
8914 ServiceRestarter res = new ServiceRestarter();
8915 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8916 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8917 synchronized (stats) {
8918 ss = stats.getServiceStatsLocked(
8919 sInfo.applicationInfo.uid, sInfo.packageName,
8920 sInfo.name);
8921 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008922 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008923 res.setService(r);
8924 mServices.put(name, r);
8925 mServicesByIntent.put(filter, r);
8926
8927 // Make sure this component isn't in the pending list.
8928 int N = mPendingServices.size();
8929 for (int i=0; i<N; i++) {
8930 ServiceRecord pr = mPendingServices.get(i);
8931 if (pr.name.equals(name)) {
8932 mPendingServices.remove(i);
8933 i--;
8934 N--;
8935 }
8936 }
8937 }
8938 } catch (RemoteException ex) {
8939 // pm is in same process, this will never happen.
8940 }
8941 }
8942 if (r != null) {
8943 if (checkComponentPermission(r.permission,
8944 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8945 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008946 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008947 + " from pid=" + Binder.getCallingPid()
8948 + ", uid=" + Binder.getCallingUid()
8949 + " requires " + r.permission);
8950 return new ServiceLookupResult(null, r.permission);
8951 }
8952 return new ServiceLookupResult(r, null);
8953 }
8954 return null;
8955 }
8956
Dianne Hackborn287952c2010-09-22 22:34:31 -07008957 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8958 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8959 + why + " of " + r + " in app " + r.app);
8960 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8961 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 long now = SystemClock.uptimeMillis();
8963 if (r.executeNesting == 0 && r.app != null) {
8964 if (r.app.executingServices.size() == 0) {
8965 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8966 msg.obj = r.app;
8967 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8968 }
8969 r.app.executingServices.add(r);
8970 }
8971 r.executeNesting++;
8972 r.executingStart = now;
8973 }
8974
8975 private final void sendServiceArgsLocked(ServiceRecord r,
8976 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008977 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008978 if (N == 0) {
8979 return;
8980 }
8981
Dianne Hackborn39792d22010-08-19 18:01:52 -07008982 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008983 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008984 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008985 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8986 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008987 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008988 // If somehow we got a dummy start at the front, then
8989 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008990 continue;
8991 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008992 si.deliveredTime = SystemClock.uptimeMillis();
8993 r.deliveredStarts.add(si);
8994 si.deliveryCount++;
8995 if (si.targetPermissionUid >= 0) {
8996 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008997 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008998 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008999 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000 if (!oomAdjusted) {
9001 oomAdjusted = true;
9002 updateOomAdjLocked(r.app);
9003 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009004 int flags = 0;
9005 if (si.deliveryCount > 0) {
9006 flags |= Service.START_FLAG_RETRY;
9007 }
9008 if (si.doneExecutingCount > 0) {
9009 flags |= Service.START_FLAG_REDELIVERY;
9010 }
9011 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009012 } catch (RemoteException e) {
9013 // Remote process gone... we'll let the normal cleanup take
9014 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009015 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009016 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009017 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009018 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009019 break;
9020 }
9021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009022 }
9023
9024 private final boolean requestServiceBindingLocked(ServiceRecord r,
9025 IntentBindRecord i, boolean rebind) {
9026 if (r.app == null || r.app.thread == null) {
9027 // If service is not currently running, can't yet bind.
9028 return false;
9029 }
9030 if ((!i.requested || rebind) && i.apps.size() > 0) {
9031 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009032 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009033 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9034 if (!rebind) {
9035 i.requested = true;
9036 }
9037 i.hasBound = true;
9038 i.doRebind = false;
9039 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009040 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 return false;
9042 }
9043 }
9044 return true;
9045 }
9046
9047 private final void requestServiceBindingsLocked(ServiceRecord r) {
9048 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9049 while (bindings.hasNext()) {
9050 IntentBindRecord i = bindings.next();
9051 if (!requestServiceBindingLocked(r, i, false)) {
9052 break;
9053 }
9054 }
9055 }
9056
9057 private final void realStartServiceLocked(ServiceRecord r,
9058 ProcessRecord app) throws RemoteException {
9059 if (app.thread == null) {
9060 throw new RemoteException();
9061 }
9062
9063 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009064 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009065
9066 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009067 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009068 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009069
9070 boolean created = false;
9071 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009072 mStringBuilder.setLength(0);
9073 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009074 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009075 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009076 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 synchronized (r.stats.getBatteryStats()) {
9078 r.stats.startLaunchedLocked();
9079 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009080 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009082 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009083 created = true;
9084 } finally {
9085 if (!created) {
9086 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009087 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 }
9089 }
9090
9091 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009092
9093 // If the service is in the started state, and there are no
9094 // pending arguments, then fake up one so its onStartCommand() will
9095 // be called.
9096 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9097 r.lastStartId++;
9098 if (r.lastStartId < 1) {
9099 r.lastStartId = 1;
9100 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009101 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009102 }
9103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 sendServiceArgsLocked(r, true);
9105 }
9106
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009107 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9108 boolean allowCancel) {
9109 boolean canceled = false;
9110
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009111 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009112 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009113 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009114
9115 // Any delivered but not yet finished starts should be put back
9116 // on the pending list.
9117 final int N = r.deliveredStarts.size();
9118 if (N > 0) {
9119 for (int i=N-1; i>=0; i--) {
9120 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009121 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009122 if (si.intent == null) {
9123 // We'll generate this again if needed.
9124 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9125 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9126 r.pendingStarts.add(0, si);
9127 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9128 dur *= 2;
9129 if (minDuration < dur) minDuration = dur;
9130 if (resetTime < dur) resetTime = dur;
9131 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009132 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009133 + r.name);
9134 canceled = true;
9135 }
9136 }
9137 r.deliveredStarts.clear();
9138 }
9139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 r.totalRestartCount++;
9141 if (r.restartDelay == 0) {
9142 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009143 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009144 } else {
9145 // If it has been a "reasonably long time" since the service
9146 // was started, then reset our restart duration back to
9147 // the beginning, so we don't infinitely increase the duration
9148 // on a service that just occasionally gets killed (which is
9149 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009150 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009151 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009152 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009154 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009155 if (r.restartDelay < minDuration) {
9156 r.restartDelay = minDuration;
9157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 }
9159 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009160
9161 r.nextRestartTime = now + r.restartDelay;
9162
9163 // Make sure that we don't end up restarting a bunch of services
9164 // all at the same time.
9165 boolean repeat;
9166 do {
9167 repeat = false;
9168 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9169 ServiceRecord r2 = mRestartingServices.get(i);
9170 if (r2 != r && r.nextRestartTime
9171 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9172 && r.nextRestartTime
9173 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9174 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9175 r.restartDelay = r.nextRestartTime - now;
9176 repeat = true;
9177 break;
9178 }
9179 }
9180 } while (repeat);
9181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 if (!mRestartingServices.contains(r)) {
9183 mRestartingServices.add(r);
9184 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009185
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009186 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009188 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009189 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009190 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009191 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009193 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009194 r.shortName, r.restartDelay);
9195
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009196 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009197 }
9198
9199 final void performServiceRestartLocked(ServiceRecord r) {
9200 if (!mRestartingServices.contains(r)) {
9201 return;
9202 }
9203 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9204 }
9205
9206 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9207 if (r.restartDelay == 0) {
9208 return false;
9209 }
9210 r.resetRestartCounter();
9211 mRestartingServices.remove(r);
9212 mHandler.removeCallbacks(r.restarter);
9213 return true;
9214 }
9215
9216 private final boolean bringUpServiceLocked(ServiceRecord r,
9217 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009218 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219 //r.dump(" ");
9220
Dianne Hackborn36124872009-10-08 16:22:03 -07009221 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 sendServiceArgsLocked(r, false);
9223 return true;
9224 }
9225
9226 if (!whileRestarting && r.restartDelay > 0) {
9227 // If waiting for a restart, then do nothing.
9228 return true;
9229 }
9230
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009231 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009232
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009233 // We are now bringing the service up, so no longer in the
9234 // restarting state.
9235 mRestartingServices.remove(r);
9236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009237 final String appName = r.processName;
9238 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9239 if (app != null && app.thread != null) {
9240 try {
9241 realStartServiceLocked(r, app);
9242 return true;
9243 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009244 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009245 }
9246
9247 // If a dead object exception was thrown -- fall through to
9248 // restart the application.
9249 }
9250
Dianne Hackborn36124872009-10-08 16:22:03 -07009251 // Not running -- get it started, and enqueue this service record
9252 // to be executed when the app comes up.
9253 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9254 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009255 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009256 + r.appInfo.packageName + "/"
9257 + r.appInfo.uid + " for service "
9258 + r.intent.getIntent() + ": process is bad");
9259 bringDownServiceLocked(r, true);
9260 return false;
9261 }
9262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 mPendingServices.add(r);
9265 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009267 return true;
9268 }
9269
9270 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009271 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009272 //r.dump(" ");
9273
9274 // Does it still need to run?
9275 if (!force && r.startRequested) {
9276 return;
9277 }
9278 if (r.connections.size() > 0) {
9279 if (!force) {
9280 // XXX should probably keep a count of the number of auto-create
9281 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009282 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009283 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009284 ArrayList<ConnectionRecord> cr = it.next();
9285 for (int i=0; i<cr.size(); i++) {
9286 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9287 return;
9288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 }
9290 }
9291 }
9292
9293 // Report to all of the connections that the service is no longer
9294 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009295 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009297 ArrayList<ConnectionRecord> c = it.next();
9298 for (int i=0; i<c.size(); i++) {
9299 try {
9300 c.get(i).conn.connected(r.name, null);
9301 } catch (Exception e) {
9302 Slog.w(TAG, "Failure disconnecting service " + r.name +
9303 " to connection " + c.get(i).conn.asBinder() +
9304 " (in " + c.get(i).binding.client.processName + ")", e);
9305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 }
9307 }
9308 }
9309
9310 // Tell the service that it has been unbound.
9311 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9312 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9313 while (it.hasNext()) {
9314 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009315 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009316 + ": hasBound=" + ibr.hasBound);
9317 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9318 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009319 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009320 updateOomAdjLocked(r.app);
9321 ibr.hasBound = false;
9322 r.app.thread.scheduleUnbindService(r,
9323 ibr.intent.getIntent());
9324 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009325 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 + r.shortName, e);
9327 serviceDoneExecutingLocked(r, true);
9328 }
9329 }
9330 }
9331 }
9332
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009333 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009334 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009335 System.identityHashCode(r), r.shortName,
9336 (r.app != null) ? r.app.pid : -1);
9337
9338 mServices.remove(r.name);
9339 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 r.totalRestartCount = 0;
9341 unscheduleServiceRestartLocked(r);
9342
9343 // Also make sure it is not on the pending list.
9344 int N = mPendingServices.size();
9345 for (int i=0; i<N; i++) {
9346 if (mPendingServices.get(i) == r) {
9347 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009348 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349 i--;
9350 N--;
9351 }
9352 }
9353
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009354 r.cancelNotification();
9355 r.isForeground = false;
9356 r.foregroundId = 0;
9357 r.foregroundNoti = null;
9358
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009359 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009360 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009361 r.pendingStarts.clear();
9362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009363 if (r.app != null) {
9364 synchronized (r.stats.getBatteryStats()) {
9365 r.stats.stopLaunchedLocked();
9366 }
9367 r.app.services.remove(r);
9368 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009369 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009370 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009371 mStoppingServices.add(r);
9372 updateOomAdjLocked(r.app);
9373 r.app.thread.scheduleStopService(r);
9374 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009375 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009376 + r.shortName, e);
9377 serviceDoneExecutingLocked(r, true);
9378 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009379 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009380 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009381 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009382 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009383 }
9384 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009385 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009386 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009387 }
9388 }
9389
9390 ComponentName startServiceLocked(IApplicationThread caller,
9391 Intent service, String resolvedType,
9392 int callingPid, int callingUid) {
9393 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009394 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 + " type=" + resolvedType + " args=" + service.getExtras());
9396
9397 if (caller != null) {
9398 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9399 if (callerApp == null) {
9400 throw new SecurityException(
9401 "Unable to find app for caller " + caller
9402 + " (pid=" + Binder.getCallingPid()
9403 + ") when starting service " + service);
9404 }
9405 }
9406
9407 ServiceLookupResult res =
9408 retrieveServiceLocked(service, resolvedType,
9409 callingPid, callingUid);
9410 if (res == null) {
9411 return null;
9412 }
9413 if (res.record == null) {
9414 return new ComponentName("!", res.permission != null
9415 ? res.permission : "private to package");
9416 }
9417 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009418 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9419 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009421 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009422 }
9423 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009424 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009425 r.lastStartId++;
9426 if (r.lastStartId < 1) {
9427 r.lastStartId = 1;
9428 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009429 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9430 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009431 r.lastActivity = SystemClock.uptimeMillis();
9432 synchronized (r.stats.getBatteryStats()) {
9433 r.stats.startRunningLocked();
9434 }
9435 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9436 return new ComponentName("!", "Service process is bad");
9437 }
9438 return r.name;
9439 }
9440 }
9441
9442 public ComponentName startService(IApplicationThread caller, Intent service,
9443 String resolvedType) {
9444 // Refuse possible leaked file descriptors
9445 if (service != null && service.hasFileDescriptors() == true) {
9446 throw new IllegalArgumentException("File descriptors passed in Intent");
9447 }
9448
9449 synchronized(this) {
9450 final int callingPid = Binder.getCallingPid();
9451 final int callingUid = Binder.getCallingUid();
9452 final long origId = Binder.clearCallingIdentity();
9453 ComponentName res = startServiceLocked(caller, service,
9454 resolvedType, callingPid, callingUid);
9455 Binder.restoreCallingIdentity(origId);
9456 return res;
9457 }
9458 }
9459
9460 ComponentName startServiceInPackage(int uid,
9461 Intent service, String resolvedType) {
9462 synchronized(this) {
9463 final long origId = Binder.clearCallingIdentity();
9464 ComponentName res = startServiceLocked(null, service,
9465 resolvedType, -1, uid);
9466 Binder.restoreCallingIdentity(origId);
9467 return res;
9468 }
9469 }
9470
9471 public int stopService(IApplicationThread caller, Intent service,
9472 String resolvedType) {
9473 // Refuse possible leaked file descriptors
9474 if (service != null && service.hasFileDescriptors() == true) {
9475 throw new IllegalArgumentException("File descriptors passed in Intent");
9476 }
9477
9478 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009479 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009480 + " type=" + resolvedType);
9481
9482 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9483 if (caller != null && callerApp == null) {
9484 throw new SecurityException(
9485 "Unable to find app for caller " + caller
9486 + " (pid=" + Binder.getCallingPid()
9487 + ") when stopping service " + service);
9488 }
9489
9490 // If this service is active, make sure it is stopped.
9491 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9492 if (r != null) {
9493 if (r.record != null) {
9494 synchronized (r.record.stats.getBatteryStats()) {
9495 r.record.stats.stopRunningLocked();
9496 }
9497 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009498 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009499 final long origId = Binder.clearCallingIdentity();
9500 bringDownServiceLocked(r.record, false);
9501 Binder.restoreCallingIdentity(origId);
9502 return 1;
9503 }
9504 return -1;
9505 }
9506 }
9507
9508 return 0;
9509 }
9510
9511 public IBinder peekService(Intent service, String resolvedType) {
9512 // Refuse possible leaked file descriptors
9513 if (service != null && service.hasFileDescriptors() == true) {
9514 throw new IllegalArgumentException("File descriptors passed in Intent");
9515 }
9516
9517 IBinder ret = null;
9518
9519 synchronized(this) {
9520 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9521
9522 if (r != null) {
9523 // r.record is null if findServiceLocked() failed the caller permission check
9524 if (r.record == null) {
9525 throw new SecurityException(
9526 "Permission Denial: Accessing service " + r.record.name
9527 + " from pid=" + Binder.getCallingPid()
9528 + ", uid=" + Binder.getCallingUid()
9529 + " requires " + r.permission);
9530 }
9531 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9532 if (ib != null) {
9533 ret = ib.binder;
9534 }
9535 }
9536 }
9537
9538 return ret;
9539 }
9540
9541 public boolean stopServiceToken(ComponentName className, IBinder token,
9542 int startId) {
9543 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009544 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 + " " + token + " startId=" + startId);
9546 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009547 if (r != null) {
9548 if (startId >= 0) {
9549 // Asked to only stop if done with all work. Note that
9550 // to avoid leaks, we will take this as dropping all
9551 // start items up to and including this one.
9552 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9553 if (si != null) {
9554 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009555 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9556 cur.removeUriPermissionsLocked();
9557 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009558 break;
9559 }
9560 }
9561 }
9562
9563 if (r.lastStartId != startId) {
9564 return false;
9565 }
9566
9567 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009568 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009569 + " is last, but have " + r.deliveredStarts.size()
9570 + " remaining args");
9571 }
9572 }
9573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574 synchronized (r.stats.getBatteryStats()) {
9575 r.stats.stopRunningLocked();
9576 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009577 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 }
9579 final long origId = Binder.clearCallingIdentity();
9580 bringDownServiceLocked(r, false);
9581 Binder.restoreCallingIdentity(origId);
9582 return true;
9583 }
9584 }
9585 return false;
9586 }
9587
9588 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009589 int id, Notification notification, boolean removeNotification) {
9590 final long origId = Binder.clearCallingIdentity();
9591 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009592 synchronized(this) {
9593 ServiceRecord r = findServiceLocked(className, token);
9594 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009595 if (id != 0) {
9596 if (notification == null) {
9597 throw new IllegalArgumentException("null notification");
9598 }
9599 if (r.foregroundId != id) {
9600 r.cancelNotification();
9601 r.foregroundId = id;
9602 }
9603 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9604 r.foregroundNoti = notification;
9605 r.isForeground = true;
9606 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009607 if (r.app != null) {
9608 updateServiceForegroundLocked(r.app, true);
9609 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009610 } else {
9611 if (r.isForeground) {
9612 r.isForeground = false;
9613 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009614 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009615 updateServiceForegroundLocked(r.app, true);
9616 }
9617 }
9618 if (removeNotification) {
9619 r.cancelNotification();
9620 r.foregroundId = 0;
9621 r.foregroundNoti = null;
9622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009623 }
9624 }
9625 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009626 } finally {
9627 Binder.restoreCallingIdentity(origId);
9628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009629 }
9630
9631 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9632 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009633 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634 if (sr.isForeground) {
9635 anyForeground = true;
9636 break;
9637 }
9638 }
9639 if (anyForeground != proc.foregroundServices) {
9640 proc.foregroundServices = anyForeground;
9641 if (oomAdj) {
9642 updateOomAdjLocked();
9643 }
9644 }
9645 }
9646
9647 public int bindService(IApplicationThread caller, IBinder token,
9648 Intent service, String resolvedType,
9649 IServiceConnection connection, int flags) {
9650 // Refuse possible leaked file descriptors
9651 if (service != null && service.hasFileDescriptors() == true) {
9652 throw new IllegalArgumentException("File descriptors passed in Intent");
9653 }
9654
9655 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009656 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009657 + " type=" + resolvedType + " conn=" + connection.asBinder()
9658 + " flags=0x" + Integer.toHexString(flags));
9659 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9660 if (callerApp == null) {
9661 throw new SecurityException(
9662 "Unable to find app for caller " + caller
9663 + " (pid=" + Binder.getCallingPid()
9664 + ") when binding service " + service);
9665 }
9666
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009667 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009668 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009669 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009670 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009671 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009672 return 0;
9673 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009674 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009675 }
9676
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009677 int clientLabel = 0;
9678 PendingIntent clientIntent = null;
9679
9680 if (callerApp.info.uid == Process.SYSTEM_UID) {
9681 // Hacky kind of thing -- allow system stuff to tell us
9682 // what they are, so we can report this elsewhere for
9683 // others to know why certain services are running.
9684 try {
9685 clientIntent = (PendingIntent)service.getParcelableExtra(
9686 Intent.EXTRA_CLIENT_INTENT);
9687 } catch (RuntimeException e) {
9688 }
9689 if (clientIntent != null) {
9690 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9691 if (clientLabel != 0) {
9692 // There are no useful extras in the intent, trash them.
9693 // System code calling with this stuff just needs to know
9694 // this will happen.
9695 service = service.cloneFilter();
9696 }
9697 }
9698 }
9699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 ServiceLookupResult res =
9701 retrieveServiceLocked(service, resolvedType,
9702 Binder.getCallingPid(), Binder.getCallingUid());
9703 if (res == null) {
9704 return 0;
9705 }
9706 if (res.record == null) {
9707 return -1;
9708 }
9709 ServiceRecord s = res.record;
9710
9711 final long origId = Binder.clearCallingIdentity();
9712
9713 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009714 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009715 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009716 }
9717
9718 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9719 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009720 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721
9722 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009723 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9724 if (clist == null) {
9725 clist = new ArrayList<ConnectionRecord>();
9726 s.connections.put(binder, clist);
9727 }
9728 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009729 b.connections.add(c);
9730 if (activity != null) {
9731 if (activity.connections == null) {
9732 activity.connections = new HashSet<ConnectionRecord>();
9733 }
9734 activity.connections.add(c);
9735 }
9736 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009737 clist = mServiceConnections.get(binder);
9738 if (clist == null) {
9739 clist = new ArrayList<ConnectionRecord>();
9740 mServiceConnections.put(binder, clist);
9741 }
9742 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009743
9744 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9745 s.lastActivity = SystemClock.uptimeMillis();
9746 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9747 return 0;
9748 }
9749 }
9750
9751 if (s.app != null) {
9752 // This could have made the service more important.
9753 updateOomAdjLocked(s.app);
9754 }
9755
Joe Onorato8a9b2202010-02-26 18:56:32 -08009756 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 + ": received=" + b.intent.received
9758 + " apps=" + b.intent.apps.size()
9759 + " doRebind=" + b.intent.doRebind);
9760
9761 if (s.app != null && b.intent.received) {
9762 // Service is already running, so we can immediately
9763 // publish the connection.
9764 try {
9765 c.conn.connected(s.name, b.intent.binder);
9766 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009767 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009768 + " to connection " + c.conn.asBinder()
9769 + " (in " + c.binding.client.processName + ")", e);
9770 }
9771
9772 // If this is the first app connected back to this binding,
9773 // and the service had previously asked to be told when
9774 // rebound, then do so.
9775 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9776 requestServiceBindingLocked(s, b.intent, true);
9777 }
9778 } else if (!b.intent.requested) {
9779 requestServiceBindingLocked(s, b.intent, false);
9780 }
9781
9782 Binder.restoreCallingIdentity(origId);
9783 }
9784
9785 return 1;
9786 }
9787
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009788 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009789 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009790 IBinder binder = c.conn.asBinder();
9791 AppBindRecord b = c.binding;
9792 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009793 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9794 if (clist != null) {
9795 clist.remove(c);
9796 if (clist.size() == 0) {
9797 s.connections.remove(binder);
9798 }
9799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009800 b.connections.remove(c);
9801 if (c.activity != null && c.activity != skipAct) {
9802 if (c.activity.connections != null) {
9803 c.activity.connections.remove(c);
9804 }
9805 }
9806 if (b.client != skipApp) {
9807 b.client.connections.remove(c);
9808 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009809 clist = mServiceConnections.get(binder);
9810 if (clist != null) {
9811 clist.remove(c);
9812 if (clist.size() == 0) {
9813 mServiceConnections.remove(binder);
9814 }
9815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009816
9817 if (b.connections.size() == 0) {
9818 b.intent.apps.remove(b.client);
9819 }
9820
Joe Onorato8a9b2202010-02-26 18:56:32 -08009821 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009822 + ": shouldUnbind=" + b.intent.hasBound);
9823 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9824 && b.intent.hasBound) {
9825 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009826 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009827 updateOomAdjLocked(s.app);
9828 b.intent.hasBound = false;
9829 // Assume the client doesn't want to know about a rebind;
9830 // we will deal with that later if it asks for one.
9831 b.intent.doRebind = false;
9832 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9833 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009834 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835 serviceDoneExecutingLocked(s, true);
9836 }
9837 }
9838
9839 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9840 bringDownServiceLocked(s, false);
9841 }
9842 }
9843
9844 public boolean unbindService(IServiceConnection connection) {
9845 synchronized (this) {
9846 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009847 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009848 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9849 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009850 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009851 + connection.asBinder());
9852 return false;
9853 }
9854
9855 final long origId = Binder.clearCallingIdentity();
9856
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009857 while (clist.size() > 0) {
9858 ConnectionRecord r = clist.get(0);
9859 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009861 if (r.binding.service.app != null) {
9862 // This could have made the service less important.
9863 updateOomAdjLocked(r.binding.service.app);
9864 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 }
9866
9867 Binder.restoreCallingIdentity(origId);
9868 }
9869
9870 return true;
9871 }
9872
9873 public void publishService(IBinder token, Intent intent, IBinder service) {
9874 // Refuse possible leaked file descriptors
9875 if (intent != null && intent.hasFileDescriptors() == true) {
9876 throw new IllegalArgumentException("File descriptors passed in Intent");
9877 }
9878
9879 synchronized(this) {
9880 if (!(token instanceof ServiceRecord)) {
9881 throw new IllegalArgumentException("Invalid service token");
9882 }
9883 ServiceRecord r = (ServiceRecord)token;
9884
9885 final long origId = Binder.clearCallingIdentity();
9886
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009887 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009888 + " " + intent + ": " + service);
9889 if (r != null) {
9890 Intent.FilterComparison filter
9891 = new Intent.FilterComparison(intent);
9892 IntentBindRecord b = r.bindings.get(filter);
9893 if (b != null && !b.received) {
9894 b.binder = service;
9895 b.requested = true;
9896 b.received = true;
9897 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009898 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009899 = r.connections.values().iterator();
9900 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009901 ArrayList<ConnectionRecord> clist = it.next();
9902 for (int i=0; i<clist.size(); i++) {
9903 ConnectionRecord c = clist.get(i);
9904 if (!filter.equals(c.binding.intent.intent)) {
9905 if (DEBUG_SERVICE) Slog.v(
9906 TAG, "Not publishing to: " + c);
9907 if (DEBUG_SERVICE) Slog.v(
9908 TAG, "Bound intent: " + c.binding.intent.intent);
9909 if (DEBUG_SERVICE) Slog.v(
9910 TAG, "Published intent: " + intent);
9911 continue;
9912 }
9913 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9914 try {
9915 c.conn.connected(r.name, service);
9916 } catch (Exception e) {
9917 Slog.w(TAG, "Failure sending service " + r.name +
9918 " to connection " + c.conn.asBinder() +
9919 " (in " + c.binding.client.processName + ")", e);
9920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009921 }
9922 }
9923 }
9924 }
9925
9926 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9927
9928 Binder.restoreCallingIdentity(origId);
9929 }
9930 }
9931 }
9932
9933 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9934 // Refuse possible leaked file descriptors
9935 if (intent != null && intent.hasFileDescriptors() == true) {
9936 throw new IllegalArgumentException("File descriptors passed in Intent");
9937 }
9938
9939 synchronized(this) {
9940 if (!(token instanceof ServiceRecord)) {
9941 throw new IllegalArgumentException("Invalid service token");
9942 }
9943 ServiceRecord r = (ServiceRecord)token;
9944
9945 final long origId = Binder.clearCallingIdentity();
9946
9947 if (r != null) {
9948 Intent.FilterComparison filter
9949 = new Intent.FilterComparison(intent);
9950 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009951 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009952 + " at " + b + ": apps="
9953 + (b != null ? b.apps.size() : 0));
9954 if (b != null) {
9955 if (b.apps.size() > 0) {
9956 // Applications have already bound since the last
9957 // unbind, so just rebind right here.
9958 requestServiceBindingLocked(r, b, true);
9959 } else {
9960 // Note to tell the service the next time there is
9961 // a new client.
9962 b.doRebind = true;
9963 }
9964 }
9965
9966 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9967
9968 Binder.restoreCallingIdentity(origId);
9969 }
9970 }
9971 }
9972
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009973 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009974 synchronized(this) {
9975 if (!(token instanceof ServiceRecord)) {
9976 throw new IllegalArgumentException("Invalid service token");
9977 }
9978 ServiceRecord r = (ServiceRecord)token;
9979 boolean inStopping = mStoppingServices.contains(token);
9980 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009982 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009983 + " with incorrect token: given " + token
9984 + ", expected " + r);
9985 return;
9986 }
9987
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009988 if (type == 1) {
9989 // This is a call from a service start... take care of
9990 // book-keeping.
9991 r.callStart = true;
9992 switch (res) {
9993 case Service.START_STICKY_COMPATIBILITY:
9994 case Service.START_STICKY: {
9995 // We are done with the associated start arguments.
9996 r.findDeliveredStart(startId, true);
9997 // Don't stop if killed.
9998 r.stopIfKilled = false;
9999 break;
10000 }
10001 case Service.START_NOT_STICKY: {
10002 // We are done with the associated start arguments.
10003 r.findDeliveredStart(startId, true);
10004 if (r.lastStartId == startId) {
10005 // There is no more work, and this service
10006 // doesn't want to hang around if killed.
10007 r.stopIfKilled = true;
10008 }
10009 break;
10010 }
10011 case Service.START_REDELIVER_INTENT: {
10012 // We'll keep this item until they explicitly
10013 // call stop for it, but keep track of the fact
10014 // that it was delivered.
10015 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10016 if (si != null) {
10017 si.deliveryCount = 0;
10018 si.doneExecutingCount++;
10019 // Don't stop if killed.
10020 r.stopIfKilled = true;
10021 }
10022 break;
10023 }
10024 default:
10025 throw new IllegalArgumentException(
10026 "Unknown service start result: " + res);
10027 }
10028 if (res == Service.START_STICKY_COMPATIBILITY) {
10029 r.callStart = false;
10030 }
10031 }
10032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010033 final long origId = Binder.clearCallingIdentity();
10034 serviceDoneExecutingLocked(r, inStopping);
10035 Binder.restoreCallingIdentity(origId);
10036 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010037 Slog.w(TAG, "Done executing unknown service from pid "
10038 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010039 }
10040 }
10041 }
10042
10043 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010044 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10045 + ": nesting=" + r.executeNesting
10046 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010047 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010048 r.executeNesting--;
10049 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010050 if (DEBUG_SERVICE) Slog.v(TAG,
10051 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010052 r.app.executingServices.remove(r);
10053 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010054 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10055 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10057 }
10058 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010059 if (DEBUG_SERVICE) Slog.v(TAG,
10060 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010061 mStoppingServices.remove(r);
10062 }
10063 updateOomAdjLocked(r.app);
10064 }
10065 }
10066
10067 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010068 String anrMessage = null;
10069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010070 synchronized(this) {
10071 if (proc.executingServices.size() == 0 || proc.thread == null) {
10072 return;
10073 }
10074 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10075 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10076 ServiceRecord timeout = null;
10077 long nextTime = 0;
10078 while (it.hasNext()) {
10079 ServiceRecord sr = it.next();
10080 if (sr.executingStart < maxTime) {
10081 timeout = sr;
10082 break;
10083 }
10084 if (sr.executingStart > nextTime) {
10085 nextTime = sr.executingStart;
10086 }
10087 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010088 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010089 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010090 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010091 } else {
10092 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10093 msg.obj = proc;
10094 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10095 }
10096 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010097
10098 if (anrMessage != null) {
10099 appNotResponding(proc, null, null, anrMessage);
10100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010101 }
10102
10103 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010104 // BACKUP AND RESTORE
10105 // =========================================================
10106
10107 // Cause the target app to be launched if necessary and its backup agent
10108 // instantiated. The backup agent will invoke backupAgentCreated() on the
10109 // activity manager to announce its creation.
10110 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010111 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010112 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10113
10114 synchronized(this) {
10115 // !!! TODO: currently no check here that we're already bound
10116 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10117 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10118 synchronized (stats) {
10119 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10120 }
10121
10122 BackupRecord r = new BackupRecord(ss, app, backupMode);
10123 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10124 // startProcessLocked() returns existing proc's record if it's already running
10125 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010126 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010127 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010128 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010129 return false;
10130 }
10131
10132 r.app = proc;
10133 mBackupTarget = r;
10134 mBackupAppName = app.packageName;
10135
Christopher Tate6fa95972009-06-05 18:43:55 -070010136 // Try not to kill the process during backup
10137 updateOomAdjLocked(proc);
10138
Christopher Tate181fafa2009-05-14 11:12:14 -070010139 // If the process is already attached, schedule the creation of the backup agent now.
10140 // If it is not yet live, this will be done when it attaches to the framework.
10141 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010142 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010143 try {
10144 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10145 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010146 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010147 }
10148 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010149 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010150 }
10151 // Invariants: at this point, the target app process exists and the application
10152 // is either already running or in the process of coming up. mBackupTarget and
10153 // mBackupAppName describe the app, so that when it binds back to the AM we
10154 // know that it's scheduled for a backup-agent operation.
10155 }
10156
10157 return true;
10158 }
10159
10160 // A backup agent has just come up
10161 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010162 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010163 + " = " + agent);
10164
10165 synchronized(this) {
10166 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010167 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010168 return;
10169 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010170 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010171
Dianne Hackborn06740692010-09-22 22:46:21 -070010172 long oldIdent = Binder.clearCallingIdentity();
10173 try {
10174 IBackupManager bm = IBackupManager.Stub.asInterface(
10175 ServiceManager.getService(Context.BACKUP_SERVICE));
10176 bm.agentConnected(agentPackageName, agent);
10177 } catch (RemoteException e) {
10178 // can't happen; the backup manager service is local
10179 } catch (Exception e) {
10180 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10181 e.printStackTrace();
10182 } finally {
10183 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010184 }
10185 }
10186
10187 // done with this agent
10188 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010189 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010190 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010191 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010192 return;
10193 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010194
10195 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010196 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010197 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010198 return;
10199 }
10200
Christopher Tate181fafa2009-05-14 11:12:14 -070010201 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010202 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010203 return;
10204 }
10205
Christopher Tate6fa95972009-06-05 18:43:55 -070010206 ProcessRecord proc = mBackupTarget.app;
10207 mBackupTarget = null;
10208 mBackupAppName = null;
10209
10210 // Not backing this app up any more; reset its OOM adjustment
10211 updateOomAdjLocked(proc);
10212
Christopher Tatec7b31e32009-06-10 15:49:30 -070010213 // If the app crashed during backup, 'thread' will be null here
10214 if (proc.thread != null) {
10215 try {
10216 proc.thread.scheduleDestroyBackupAgent(appInfo);
10217 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010218 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010219 e.printStackTrace();
10220 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010221 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010222 }
10223 }
10224 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010225 // BROADCASTS
10226 // =========================================================
10227
Josh Bartel7f208742010-02-25 11:01:44 -060010228 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 List cur) {
10230 final ContentResolver resolver = mContext.getContentResolver();
10231 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10232 if (list == null) {
10233 return cur;
10234 }
10235 int N = list.size();
10236 for (int i=0; i<N; i++) {
10237 Intent intent = list.get(i);
10238 if (filter.match(resolver, intent, true, TAG) >= 0) {
10239 if (cur == null) {
10240 cur = new ArrayList<Intent>();
10241 }
10242 cur.add(intent);
10243 }
10244 }
10245 return cur;
10246 }
10247
10248 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010249 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010250 + mBroadcastsScheduled);
10251
10252 if (mBroadcastsScheduled) {
10253 return;
10254 }
10255 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10256 mBroadcastsScheduled = true;
10257 }
10258
10259 public Intent registerReceiver(IApplicationThread caller,
10260 IIntentReceiver receiver, IntentFilter filter, String permission) {
10261 synchronized(this) {
10262 ProcessRecord callerApp = null;
10263 if (caller != null) {
10264 callerApp = getRecordForAppLocked(caller);
10265 if (callerApp == null) {
10266 throw new SecurityException(
10267 "Unable to find app for caller " + caller
10268 + " (pid=" + Binder.getCallingPid()
10269 + ") when registering receiver " + receiver);
10270 }
10271 }
10272
10273 List allSticky = null;
10274
10275 // Look for any matching sticky broadcasts...
10276 Iterator actions = filter.actionsIterator();
10277 if (actions != null) {
10278 while (actions.hasNext()) {
10279 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010280 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 }
10282 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010283 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 }
10285
10286 // The first sticky in the list is returned directly back to
10287 // the client.
10288 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10289
Joe Onorato8a9b2202010-02-26 18:56:32 -080010290 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291 + ": " + sticky);
10292
10293 if (receiver == null) {
10294 return sticky;
10295 }
10296
10297 ReceiverList rl
10298 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10299 if (rl == null) {
10300 rl = new ReceiverList(this, callerApp,
10301 Binder.getCallingPid(),
10302 Binder.getCallingUid(), receiver);
10303 if (rl.app != null) {
10304 rl.app.receivers.add(rl);
10305 } else {
10306 try {
10307 receiver.asBinder().linkToDeath(rl, 0);
10308 } catch (RemoteException e) {
10309 return sticky;
10310 }
10311 rl.linkedToDeath = true;
10312 }
10313 mRegisteredReceivers.put(receiver.asBinder(), rl);
10314 }
10315 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10316 rl.add(bf);
10317 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010318 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 }
10320 mReceiverResolver.addFilter(bf);
10321
10322 // Enqueue broadcasts for all existing stickies that match
10323 // this filter.
10324 if (allSticky != null) {
10325 ArrayList receivers = new ArrayList();
10326 receivers.add(bf);
10327
10328 int N = allSticky.size();
10329 for (int i=0; i<N; i++) {
10330 Intent intent = (Intent)allSticky.get(i);
10331 BroadcastRecord r = new BroadcastRecord(intent, null,
10332 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010333 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010334 if (mParallelBroadcasts.size() == 0) {
10335 scheduleBroadcastsLocked();
10336 }
10337 mParallelBroadcasts.add(r);
10338 }
10339 }
10340
10341 return sticky;
10342 }
10343 }
10344
10345 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010346 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010347
10348 boolean doNext = false;
10349
10350 synchronized(this) {
10351 ReceiverList rl
10352 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10353 if (rl != null) {
10354 if (rl.curBroadcast != null) {
10355 BroadcastRecord r = rl.curBroadcast;
10356 doNext = finishReceiverLocked(
10357 receiver.asBinder(), r.resultCode, r.resultData,
10358 r.resultExtras, r.resultAbort, true);
10359 }
10360
10361 if (rl.app != null) {
10362 rl.app.receivers.remove(rl);
10363 }
10364 removeReceiverLocked(rl);
10365 if (rl.linkedToDeath) {
10366 rl.linkedToDeath = false;
10367 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10368 }
10369 }
10370 }
10371
10372 if (!doNext) {
10373 return;
10374 }
10375
10376 final long origId = Binder.clearCallingIdentity();
10377 processNextBroadcast(false);
10378 trimApplications();
10379 Binder.restoreCallingIdentity(origId);
10380 }
10381
10382 void removeReceiverLocked(ReceiverList rl) {
10383 mRegisteredReceivers.remove(rl.receiver.asBinder());
10384 int N = rl.size();
10385 for (int i=0; i<N; i++) {
10386 mReceiverResolver.removeFilter(rl.get(i));
10387 }
10388 }
10389
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010390 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10391 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10392 ProcessRecord r = mLruProcesses.get(i);
10393 if (r.thread != null) {
10394 try {
10395 r.thread.dispatchPackageBroadcast(cmd, packages);
10396 } catch (RemoteException ex) {
10397 }
10398 }
10399 }
10400 }
10401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 private final int broadcastIntentLocked(ProcessRecord callerApp,
10403 String callerPackage, Intent intent, String resolvedType,
10404 IIntentReceiver resultTo, int resultCode, String resultData,
10405 Bundle map, String requiredPermission,
10406 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10407 intent = new Intent(intent);
10408
Joe Onorato8a9b2202010-02-26 18:56:32 -080010409 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010410 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10411 + " ordered=" + ordered);
10412 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010413 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 }
10415
10416 // Handle special intents: if this broadcast is from the package
10417 // manager about a package being removed, we need to remove all of
10418 // its activities from the history stack.
10419 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10420 intent.getAction());
10421 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10422 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010423 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010424 || uidRemoved) {
10425 if (checkComponentPermission(
10426 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10427 callingPid, callingUid, -1)
10428 == PackageManager.PERMISSION_GRANTED) {
10429 if (uidRemoved) {
10430 final Bundle intentExtras = intent.getExtras();
10431 final int uid = intentExtras != null
10432 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10433 if (uid >= 0) {
10434 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10435 synchronized (bs) {
10436 bs.removeUidStatsLocked(uid);
10437 }
10438 }
10439 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010440 // If resources are unvailble just force stop all
10441 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010442 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010443 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10444 if (list != null && (list.length > 0)) {
10445 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010446 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010447 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010448 sendPackageBroadcastLocked(
10449 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010450 }
10451 } else {
10452 Uri data = intent.getData();
10453 String ssp;
10454 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10455 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10456 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010457 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010458 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010459 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10460 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10461 new String[] {ssp});
10462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010463 }
10464 }
10465 }
10466 } else {
10467 String msg = "Permission Denial: " + intent.getAction()
10468 + " broadcast from " + callerPackage + " (pid=" + callingPid
10469 + ", uid=" + callingUid + ")"
10470 + " requires "
10471 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010472 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010473 throw new SecurityException(msg);
10474 }
10475 }
10476
10477 /*
10478 * If this is the time zone changed action, queue up a message that will reset the timezone
10479 * of all currently running processes. This message will get queued up before the broadcast
10480 * happens.
10481 */
10482 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10483 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10484 }
10485
Robert Greenwalt03595d02010-11-02 14:08:23 -070010486 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10487 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10488 }
10489
Robert Greenwalt434203a2010-10-11 16:00:27 -070010490 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10491 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10492 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10493 }
10494
Dianne Hackborn854060af2009-07-09 18:14:31 -070010495 /*
10496 * Prevent non-system code (defined here to be non-persistent
10497 * processes) from sending protected broadcasts.
10498 */
10499 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10500 || callingUid == Process.SHELL_UID || callingUid == 0) {
10501 // Always okay.
10502 } else if (callerApp == null || !callerApp.persistent) {
10503 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010504 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010505 intent.getAction())) {
10506 String msg = "Permission Denial: not allowed to send broadcast "
10507 + intent.getAction() + " from pid="
10508 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010509 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010510 throw new SecurityException(msg);
10511 }
10512 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010513 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010514 return BROADCAST_SUCCESS;
10515 }
10516 }
10517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518 // Add to the sticky list if requested.
10519 if (sticky) {
10520 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10521 callingPid, callingUid)
10522 != PackageManager.PERMISSION_GRANTED) {
10523 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10524 + callingPid + ", uid=" + callingUid
10525 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010526 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010527 throw new SecurityException(msg);
10528 }
10529 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010530 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 + " and enforce permission " + requiredPermission);
10532 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10533 }
10534 if (intent.getComponent() != null) {
10535 throw new SecurityException(
10536 "Sticky broadcasts can't target a specific component");
10537 }
10538 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10539 if (list == null) {
10540 list = new ArrayList<Intent>();
10541 mStickyBroadcasts.put(intent.getAction(), list);
10542 }
10543 int N = list.size();
10544 int i;
10545 for (i=0; i<N; i++) {
10546 if (intent.filterEquals(list.get(i))) {
10547 // This sticky already exists, replace it.
10548 list.set(i, new Intent(intent));
10549 break;
10550 }
10551 }
10552 if (i >= N) {
10553 list.add(new Intent(intent));
10554 }
10555 }
10556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010557 // Figure out who all will receive this broadcast.
10558 List receivers = null;
10559 List<BroadcastFilter> registeredReceivers = null;
10560 try {
10561 if (intent.getComponent() != null) {
10562 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010563 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010564 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010565 if (ai != null) {
10566 receivers = new ArrayList();
10567 ResolveInfo ri = new ResolveInfo();
10568 ri.activityInfo = ai;
10569 receivers.add(ri);
10570 }
10571 } else {
10572 // Need to resolve the intent to interested receivers...
10573 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10574 == 0) {
10575 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010576 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010577 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010578 }
Mihai Preda074edef2009-05-18 17:13:31 +020010579 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010580 }
10581 } catch (RemoteException ex) {
10582 // pm is in same process, this will never happen.
10583 }
10584
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010585 final boolean replacePending =
10586 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10587
Joe Onorato8a9b2202010-02-26 18:56:32 -080010588 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010589 + " replacePending=" + replacePending);
10590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010591 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10592 if (!ordered && NR > 0) {
10593 // If we are not serializing this broadcast, then send the
10594 // registered receivers separately so they don't wait for the
10595 // components to be launched.
10596 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10597 callerPackage, callingPid, callingUid, requiredPermission,
10598 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010599 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010600 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010601 TAG, "Enqueueing parallel broadcast " + r
10602 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010603 boolean replaced = false;
10604 if (replacePending) {
10605 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10606 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010607 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010608 "***** DROPPING PARALLEL: " + intent);
10609 mParallelBroadcasts.set(i, r);
10610 replaced = true;
10611 break;
10612 }
10613 }
10614 }
10615 if (!replaced) {
10616 mParallelBroadcasts.add(r);
10617 scheduleBroadcastsLocked();
10618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010619 registeredReceivers = null;
10620 NR = 0;
10621 }
10622
10623 // Merge into one list.
10624 int ir = 0;
10625 if (receivers != null) {
10626 // A special case for PACKAGE_ADDED: do not allow the package
10627 // being added to see this broadcast. This prevents them from
10628 // using this as a back door to get run as soon as they are
10629 // installed. Maybe in the future we want to have a special install
10630 // broadcast or such for apps, but we'd like to deliberately make
10631 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010632 String skipPackages[] = null;
10633 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10634 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10635 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10636 Uri data = intent.getData();
10637 if (data != null) {
10638 String pkgName = data.getSchemeSpecificPart();
10639 if (pkgName != null) {
10640 skipPackages = new String[] { pkgName };
10641 }
10642 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010643 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010644 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010645 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010646 if (skipPackages != null && (skipPackages.length > 0)) {
10647 for (String skipPackage : skipPackages) {
10648 if (skipPackage != null) {
10649 int NT = receivers.size();
10650 for (int it=0; it<NT; it++) {
10651 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10652 if (curt.activityInfo.packageName.equals(skipPackage)) {
10653 receivers.remove(it);
10654 it--;
10655 NT--;
10656 }
10657 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010658 }
10659 }
10660 }
10661
10662 int NT = receivers != null ? receivers.size() : 0;
10663 int it = 0;
10664 ResolveInfo curt = null;
10665 BroadcastFilter curr = null;
10666 while (it < NT && ir < NR) {
10667 if (curt == null) {
10668 curt = (ResolveInfo)receivers.get(it);
10669 }
10670 if (curr == null) {
10671 curr = registeredReceivers.get(ir);
10672 }
10673 if (curr.getPriority() >= curt.priority) {
10674 // Insert this broadcast record into the final list.
10675 receivers.add(it, curr);
10676 ir++;
10677 curr = null;
10678 it++;
10679 NT++;
10680 } else {
10681 // Skip to the next ResolveInfo in the final list.
10682 it++;
10683 curt = null;
10684 }
10685 }
10686 }
10687 while (ir < NR) {
10688 if (receivers == null) {
10689 receivers = new ArrayList();
10690 }
10691 receivers.add(registeredReceivers.get(ir));
10692 ir++;
10693 }
10694
10695 if ((receivers != null && receivers.size() > 0)
10696 || resultTo != null) {
10697 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10698 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010699 receivers, resultTo, resultCode, resultData, map, ordered,
10700 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010701 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 TAG, "Enqueueing ordered broadcast " + r
10703 + ": prev had " + mOrderedBroadcasts.size());
10704 if (DEBUG_BROADCAST) {
10705 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010706 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010708 boolean replaced = false;
10709 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010710 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010711 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010712 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010713 "***** DROPPING ORDERED: " + intent);
10714 mOrderedBroadcasts.set(i, r);
10715 replaced = true;
10716 break;
10717 }
10718 }
10719 }
10720 if (!replaced) {
10721 mOrderedBroadcasts.add(r);
10722 scheduleBroadcastsLocked();
10723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010724 }
10725
10726 return BROADCAST_SUCCESS;
10727 }
10728
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010729 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010730 // Refuse possible leaked file descriptors
10731 if (intent != null && intent.hasFileDescriptors() == true) {
10732 throw new IllegalArgumentException("File descriptors passed in Intent");
10733 }
10734
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010735 int flags = intent.getFlags();
10736
10737 if (!mProcessesReady) {
10738 // if the caller really truly claims to know what they're doing, go
10739 // ahead and allow the broadcast without launching any receivers
10740 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10741 intent = new Intent(intent);
10742 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10743 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10744 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10745 + " before boot completion");
10746 throw new IllegalStateException("Cannot broadcast before boot completed");
10747 }
10748 }
10749
10750 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10751 throw new IllegalArgumentException(
10752 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10753 }
10754
10755 return intent;
10756 }
10757
10758 public final int broadcastIntent(IApplicationThread caller,
10759 Intent intent, String resolvedType, IIntentReceiver resultTo,
10760 int resultCode, String resultData, Bundle map,
10761 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010762 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010763 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10766 final int callingPid = Binder.getCallingPid();
10767 final int callingUid = Binder.getCallingUid();
10768 final long origId = Binder.clearCallingIdentity();
10769 int res = broadcastIntentLocked(callerApp,
10770 callerApp != null ? callerApp.info.packageName : null,
10771 intent, resolvedType, resultTo,
10772 resultCode, resultData, map, requiredPermission, serialized,
10773 sticky, callingPid, callingUid);
10774 Binder.restoreCallingIdentity(origId);
10775 return res;
10776 }
10777 }
10778
10779 int broadcastIntentInPackage(String packageName, int uid,
10780 Intent intent, String resolvedType, IIntentReceiver resultTo,
10781 int resultCode, String resultData, Bundle map,
10782 String requiredPermission, boolean serialized, boolean sticky) {
10783 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010784 intent = verifyBroadcastLocked(intent);
10785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786 final long origId = Binder.clearCallingIdentity();
10787 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10788 resultTo, resultCode, resultData, map, requiredPermission,
10789 serialized, sticky, -1, uid);
10790 Binder.restoreCallingIdentity(origId);
10791 return res;
10792 }
10793 }
10794
10795 public final void unbroadcastIntent(IApplicationThread caller,
10796 Intent intent) {
10797 // Refuse possible leaked file descriptors
10798 if (intent != null && intent.hasFileDescriptors() == true) {
10799 throw new IllegalArgumentException("File descriptors passed in Intent");
10800 }
10801
10802 synchronized(this) {
10803 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10804 != PackageManager.PERMISSION_GRANTED) {
10805 String msg = "Permission Denial: unbroadcastIntent() from pid="
10806 + Binder.getCallingPid()
10807 + ", uid=" + Binder.getCallingUid()
10808 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010809 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810 throw new SecurityException(msg);
10811 }
10812 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10813 if (list != null) {
10814 int N = list.size();
10815 int i;
10816 for (i=0; i<N; i++) {
10817 if (intent.filterEquals(list.get(i))) {
10818 list.remove(i);
10819 break;
10820 }
10821 }
10822 }
10823 }
10824 }
10825
10826 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10827 String resultData, Bundle resultExtras, boolean resultAbort,
10828 boolean explicit) {
10829 if (mOrderedBroadcasts.size() == 0) {
10830 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010831 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010832 }
10833 return false;
10834 }
10835 BroadcastRecord r = mOrderedBroadcasts.get(0);
10836 if (r.receiver == null) {
10837 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010838 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 }
10840 return false;
10841 }
10842 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010843 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 return false;
10845 }
10846 int state = r.state;
10847 r.state = r.IDLE;
10848 if (state == r.IDLE) {
10849 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010850 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010851 }
10852 }
10853 r.receiver = null;
10854 r.intent.setComponent(null);
10855 if (r.curApp != null) {
10856 r.curApp.curReceiver = null;
10857 }
10858 if (r.curFilter != null) {
10859 r.curFilter.receiverList.curBroadcast = null;
10860 }
10861 r.curFilter = null;
10862 r.curApp = null;
10863 r.curComponent = null;
10864 r.curReceiver = null;
10865 mPendingBroadcast = null;
10866
10867 r.resultCode = resultCode;
10868 r.resultData = resultData;
10869 r.resultExtras = resultExtras;
10870 r.resultAbort = resultAbort;
10871
10872 // We will process the next receiver right now if this is finishing
10873 // an app receiver (which is always asynchronous) or after we have
10874 // come back from calling a receiver.
10875 return state == BroadcastRecord.APP_RECEIVE
10876 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10877 }
10878
10879 public void finishReceiver(IBinder who, int resultCode, String resultData,
10880 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010881 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882
10883 // Refuse possible leaked file descriptors
10884 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10885 throw new IllegalArgumentException("File descriptors passed in Bundle");
10886 }
10887
10888 boolean doNext;
10889
10890 final long origId = Binder.clearCallingIdentity();
10891
10892 synchronized(this) {
10893 doNext = finishReceiverLocked(
10894 who, resultCode, resultData, resultExtras, resultAbort, true);
10895 }
10896
10897 if (doNext) {
10898 processNextBroadcast(false);
10899 }
10900 trimApplications();
10901
10902 Binder.restoreCallingIdentity(origId);
10903 }
10904
Jeff Brown4d94a762010-09-23 11:33:28 -070010905 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 if (r.nextReceiver > 0) {
10907 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10908 if (curReceiver instanceof BroadcastFilter) {
10909 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010910 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010911 System.identityHashCode(r),
10912 r.intent.getAction(),
10913 r.nextReceiver - 1,
10914 System.identityHashCode(bf));
10915 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010916 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 System.identityHashCode(r),
10918 r.intent.getAction(),
10919 r.nextReceiver - 1,
10920 ((ResolveInfo)curReceiver).toString());
10921 }
10922 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010923 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010924 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010925 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 System.identityHashCode(r),
10927 r.intent.getAction(),
10928 r.nextReceiver,
10929 "NONE");
10930 }
10931 }
10932
Jeff Brown4d94a762010-09-23 11:33:28 -070010933 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10934 if (! mPendingBroadcastTimeoutMessage) {
10935 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10936 mHandler.sendMessageAtTime(msg, timeoutTime);
10937 mPendingBroadcastTimeoutMessage = true;
10938 }
10939 }
10940
10941 private final void cancelBroadcastTimeoutLocked() {
10942 if (mPendingBroadcastTimeoutMessage) {
10943 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10944 mPendingBroadcastTimeoutMessage = false;
10945 }
10946 }
10947
10948 private final void broadcastTimeoutLocked(boolean fromMsg) {
10949 if (fromMsg) {
10950 mPendingBroadcastTimeoutMessage = false;
10951 }
10952
10953 if (mOrderedBroadcasts.size() == 0) {
10954 return;
10955 }
10956
10957 long now = SystemClock.uptimeMillis();
10958 BroadcastRecord r = mOrderedBroadcasts.get(0);
10959 if (fromMsg) {
10960 if (mDidDexOpt) {
10961 // Delay timeouts until dexopt finishes.
10962 mDidDexOpt = false;
10963 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10964 setBroadcastTimeoutLocked(timeoutTime);
10965 return;
10966 }
10967 if (! mProcessesReady) {
10968 // Only process broadcast timeouts if the system is ready. That way
10969 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10970 // to do heavy lifting for system up.
10971 return;
10972 }
10973
10974 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10975 if (timeoutTime > now) {
10976 // We can observe premature timeouts because we do not cancel and reset the
10977 // broadcast timeout message after each receiver finishes. Instead, we set up
10978 // an initial timeout then kick it down the road a little further as needed
10979 // when it expires.
10980 if (DEBUG_BROADCAST) Slog.v(TAG,
10981 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10982 + timeoutTime);
10983 setBroadcastTimeoutLocked(timeoutTime);
10984 return;
10985 }
10986 }
10987
10988 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10989 + ", started " + (now - r.receiverTime) + "ms ago");
10990 r.receiverTime = now;
10991 r.anrCount++;
10992
10993 // Current receiver has passed its expiration date.
10994 if (r.nextReceiver <= 0) {
10995 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10996 return;
10997 }
10998
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010999 ProcessRecord app = null;
11000 String anrMessage = null;
11001
Jeff Brown4d94a762010-09-23 11:33:28 -070011002 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11003 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11004 logBroadcastReceiverDiscardLocked(r);
11005 if (curReceiver instanceof BroadcastFilter) {
11006 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11007 if (bf.receiverList.pid != 0
11008 && bf.receiverList.pid != MY_PID) {
11009 synchronized (this.mPidsSelfLocked) {
11010 app = this.mPidsSelfLocked.get(
11011 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011012 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011014 } else {
11015 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011017
Jeff Brown4d94a762010-09-23 11:33:28 -070011018 if (app != null) {
11019 anrMessage = "Broadcast of " + r.intent.toString();
11020 }
11021
11022 if (mPendingBroadcast == r) {
11023 mPendingBroadcast = null;
11024 }
11025
11026 // Move on to the next receiver.
11027 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11028 r.resultExtras, r.resultAbort, true);
11029 scheduleBroadcastsLocked();
11030
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011031 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011032 // Post the ANR to the handler since we do not want to process ANRs while
11033 // potentially holding our lock.
11034 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 }
11037
11038 private final void processCurBroadcastLocked(BroadcastRecord r,
11039 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011040 if (DEBUG_BROADCAST) Slog.v(TAG,
11041 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 if (app.thread == null) {
11043 throw new RemoteException();
11044 }
11045 r.receiver = app.thread.asBinder();
11046 r.curApp = app;
11047 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011048 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049
11050 // Tell the application to launch this receiver.
11051 r.intent.setComponent(r.curComponent);
11052
11053 boolean started = false;
11054 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011055 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 "Delivering to component " + r.curComponent
11057 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011058 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11060 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011061 if (DEBUG_BROADCAST) Slog.v(TAG,
11062 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063 started = true;
11064 } finally {
11065 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011066 if (DEBUG_BROADCAST) Slog.v(TAG,
11067 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011068 r.receiver = null;
11069 r.curApp = null;
11070 app.curReceiver = null;
11071 }
11072 }
11073
11074 }
11075
Jeff Brown4d94a762010-09-23 11:33:28 -070011076 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011077 Intent intent, int resultCode, String data, Bundle extras,
11078 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011079 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 if (app != null && app.thread != null) {
11081 // If we have an app thread, do the call through that so it is
11082 // correctly ordered with other one-way calls.
11083 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011084 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011085 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011086 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 }
11088 }
11089
Jeff Brown4d94a762010-09-23 11:33:28 -070011090 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 BroadcastFilter filter, boolean ordered) {
11092 boolean skip = false;
11093 if (filter.requiredPermission != null) {
11094 int perm = checkComponentPermission(filter.requiredPermission,
11095 r.callingPid, r.callingUid, -1);
11096 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011097 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011098 + r.intent.toString()
11099 + " from " + r.callerPackage + " (pid="
11100 + r.callingPid + ", uid=" + r.callingUid + ")"
11101 + " requires " + filter.requiredPermission
11102 + " due to registered receiver " + filter);
11103 skip = true;
11104 }
11105 }
11106 if (r.requiredPermission != null) {
11107 int perm = checkComponentPermission(r.requiredPermission,
11108 filter.receiverList.pid, filter.receiverList.uid, -1);
11109 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011110 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011111 + r.intent.toString()
11112 + " to " + filter.receiverList.app
11113 + " (pid=" + filter.receiverList.pid
11114 + ", uid=" + filter.receiverList.uid + ")"
11115 + " requires " + r.requiredPermission
11116 + " due to sender " + r.callerPackage
11117 + " (uid " + r.callingUid + ")");
11118 skip = true;
11119 }
11120 }
11121
11122 if (!skip) {
11123 // If this is not being sent as an ordered broadcast, then we
11124 // don't want to touch the fields that keep track of the current
11125 // state of ordered broadcasts.
11126 if (ordered) {
11127 r.receiver = filter.receiverList.receiver.asBinder();
11128 r.curFilter = filter;
11129 filter.receiverList.curBroadcast = r;
11130 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011131 if (filter.receiverList.app != null) {
11132 // Bump hosting application to no longer be in background
11133 // scheduling class. Note that we can't do that if there
11134 // isn't an app... but we can only be in that case for
11135 // things that directly call the IActivityManager API, which
11136 // are already core system stuff so don't matter for this.
11137 r.curApp = filter.receiverList.app;
11138 filter.receiverList.app.curReceiver = r;
11139 updateOomAdjLocked();
11140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141 }
11142 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011143 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011145 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011146 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011147 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011148 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011150 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 if (ordered) {
11152 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11153 }
11154 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011155 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 if (ordered) {
11157 r.receiver = null;
11158 r.curFilter = null;
11159 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011160 if (filter.receiverList.app != null) {
11161 filter.receiverList.app.curReceiver = null;
11162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011163 }
11164 }
11165 }
11166 }
11167
Dianne Hackborn12527f92009-11-11 17:39:50 -080011168 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11169 if (r.callingUid < 0) {
11170 // This was from a registerReceiver() call; ignore it.
11171 return;
11172 }
11173 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11174 MAX_BROADCAST_HISTORY-1);
11175 r.finishTime = SystemClock.uptimeMillis();
11176 mBroadcastHistory[0] = r;
11177 }
11178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011179 private final void processNextBroadcast(boolean fromMsg) {
11180 synchronized(this) {
11181 BroadcastRecord r;
11182
Joe Onorato8a9b2202010-02-26 18:56:32 -080011183 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011185 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186
11187 updateCpuStats();
11188
11189 if (fromMsg) {
11190 mBroadcastsScheduled = false;
11191 }
11192
11193 // First, deliver any non-serialized broadcasts right away.
11194 while (mParallelBroadcasts.size() > 0) {
11195 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011196 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011197 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011198 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011199 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011200 for (int i=0; i<N; i++) {
11201 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011202 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011203 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011205 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011206 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011207 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011208 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011209 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 }
11211
11212 // Now take care of the next serialized one...
11213
11214 // If we are waiting for a process to come up to handle the next
11215 // broadcast, then do nothing at this point. Just in case, we
11216 // check that the process we're waiting for still exists.
11217 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011218 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011219 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011220 + mPendingBroadcast.curApp);
11221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011222
11223 boolean isDead;
11224 synchronized (mPidsSelfLocked) {
11225 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11226 }
11227 if (!isDead) {
11228 // It's still alive, so keep waiting
11229 return;
11230 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011231 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011232 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011233 mPendingBroadcast.state = BroadcastRecord.IDLE;
11234 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 mPendingBroadcast = null;
11236 }
11237 }
11238
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011239 boolean looped = false;
11240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011241 do {
11242 if (mOrderedBroadcasts.size() == 0) {
11243 // No more broadcasts pending, so all done!
11244 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011245 if (looped) {
11246 // If we had finished the last ordered broadcast, then
11247 // make sure all processes have correct oom and sched
11248 // adjustments.
11249 updateOomAdjLocked();
11250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011251 return;
11252 }
11253 r = mOrderedBroadcasts.get(0);
11254 boolean forceReceive = false;
11255
11256 // Ensure that even if something goes awry with the timeout
11257 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011258 // and continue to make progress.
11259 //
11260 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011261 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011262 // one time heavy lifting after system upgrades and can take
11263 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011265 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011266 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 if ((numReceivers > 0) &&
11268 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011269 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011270 + " now=" + now
11271 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011272 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011273 + " intent=" + r.intent
11274 + " numReceivers=" + numReceivers
11275 + " nextReceiver=" + r.nextReceiver
11276 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011277 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 forceReceive = true;
11279 r.state = BroadcastRecord.IDLE;
11280 }
11281 }
11282
11283 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011284 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 "processNextBroadcast() called when not idle (state="
11286 + r.state + ")");
11287 return;
11288 }
11289
11290 if (r.receivers == null || r.nextReceiver >= numReceivers
11291 || r.resultAbort || forceReceive) {
11292 // No more receivers for this broadcast! Send the final
11293 // result if requested...
11294 if (r.resultTo != null) {
11295 try {
11296 if (DEBUG_BROADCAST) {
11297 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011298 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011299 + " seq=" + seq + " app=" + r.callerApp);
11300 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011301 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011302 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011303 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011304 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011305 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011306 }
11307 }
11308
Joe Onorato8a9b2202010-02-26 18:56:32 -080011309 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011310 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011311
Joe Onorato8a9b2202010-02-26 18:56:32 -080011312 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011313 + r);
11314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011315 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011316 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011317 mOrderedBroadcasts.remove(0);
11318 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011319 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011320 continue;
11321 }
11322 } while (r == null);
11323
11324 // Get the next receiver...
11325 int recIdx = r.nextReceiver++;
11326
11327 // Keep track of when this receiver started, and make sure there
11328 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011329 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011330 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011331 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011332
Joe Onorato8a9b2202010-02-26 18:56:32 -080011333 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011334 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011335 }
11336 if (! mPendingBroadcastTimeoutMessage) {
11337 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011338 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011339 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11340 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 }
11342
11343 Object nextReceiver = r.receivers.get(recIdx);
11344 if (nextReceiver instanceof BroadcastFilter) {
11345 // Simple case: this is a registered receiver who gets
11346 // a direct call.
11347 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011348 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011349 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011350 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011351 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011352 if (r.receiver == null || !r.ordered) {
11353 // The receiver has already finished, so schedule to
11354 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011355 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11356 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 r.state = BroadcastRecord.IDLE;
11358 scheduleBroadcastsLocked();
11359 }
11360 return;
11361 }
11362
11363 // Hard case: need to instantiate the receiver, possibly
11364 // starting its application process to host it.
11365
11366 ResolveInfo info =
11367 (ResolveInfo)nextReceiver;
11368
11369 boolean skip = false;
11370 int perm = checkComponentPermission(info.activityInfo.permission,
11371 r.callingPid, r.callingUid,
11372 info.activityInfo.exported
11373 ? -1 : info.activityInfo.applicationInfo.uid);
11374 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011375 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011376 + r.intent.toString()
11377 + " from " + r.callerPackage + " (pid=" + r.callingPid
11378 + ", uid=" + r.callingUid + ")"
11379 + " requires " + info.activityInfo.permission
11380 + " due to receiver " + info.activityInfo.packageName
11381 + "/" + info.activityInfo.name);
11382 skip = true;
11383 }
11384 if (r.callingUid != Process.SYSTEM_UID &&
11385 r.requiredPermission != null) {
11386 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011387 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011388 checkPermission(r.requiredPermission,
11389 info.activityInfo.applicationInfo.packageName);
11390 } catch (RemoteException e) {
11391 perm = PackageManager.PERMISSION_DENIED;
11392 }
11393 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011394 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011395 + r.intent + " to "
11396 + info.activityInfo.applicationInfo.packageName
11397 + " requires " + r.requiredPermission
11398 + " due to sender " + r.callerPackage
11399 + " (uid " + r.callingUid + ")");
11400 skip = true;
11401 }
11402 }
11403 if (r.curApp != null && r.curApp.crashing) {
11404 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011405 if (DEBUG_BROADCAST) Slog.v(TAG,
11406 "Skipping deliver ordered " + r + " to " + r.curApp
11407 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 skip = true;
11409 }
11410
11411 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011412 if (DEBUG_BROADCAST) Slog.v(TAG,
11413 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 r.receiver = null;
11415 r.curFilter = null;
11416 r.state = BroadcastRecord.IDLE;
11417 scheduleBroadcastsLocked();
11418 return;
11419 }
11420
11421 r.state = BroadcastRecord.APP_RECEIVE;
11422 String targetProcess = info.activityInfo.processName;
11423 r.curComponent = new ComponentName(
11424 info.activityInfo.applicationInfo.packageName,
11425 info.activityInfo.name);
11426 r.curReceiver = info.activityInfo;
11427
11428 // Is this receiver's application already running?
11429 ProcessRecord app = getProcessRecordLocked(targetProcess,
11430 info.activityInfo.applicationInfo.uid);
11431 if (app != null && app.thread != null) {
11432 try {
11433 processCurBroadcastLocked(r, app);
11434 return;
11435 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011436 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011437 + r.curComponent, e);
11438 }
11439
11440 // If a dead object exception was thrown -- fall through to
11441 // restart the application.
11442 }
11443
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011444 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011445 if (DEBUG_BROADCAST) Slog.v(TAG,
11446 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011447 if ((r.curApp=startProcessLocked(targetProcess,
11448 info.activityInfo.applicationInfo, true,
11449 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011450 "broadcast", r.curComponent,
11451 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11452 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 // Ah, this recipient is unavailable. Finish it if necessary,
11454 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011455 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 + info.activityInfo.applicationInfo.packageName + "/"
11457 + info.activityInfo.applicationInfo.uid + " for broadcast "
11458 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011459 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011460 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11461 r.resultExtras, r.resultAbort, true);
11462 scheduleBroadcastsLocked();
11463 r.state = BroadcastRecord.IDLE;
11464 return;
11465 }
11466
11467 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011468 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011469 }
11470 }
11471
11472 // =========================================================
11473 // INSTRUMENTATION
11474 // =========================================================
11475
11476 public boolean startInstrumentation(ComponentName className,
11477 String profileFile, int flags, Bundle arguments,
11478 IInstrumentationWatcher watcher) {
11479 // Refuse possible leaked file descriptors
11480 if (arguments != null && arguments.hasFileDescriptors()) {
11481 throw new IllegalArgumentException("File descriptors passed in Bundle");
11482 }
11483
11484 synchronized(this) {
11485 InstrumentationInfo ii = null;
11486 ApplicationInfo ai = null;
11487 try {
11488 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011489 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011490 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011491 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011492 } catch (PackageManager.NameNotFoundException e) {
11493 }
11494 if (ii == null) {
11495 reportStartInstrumentationFailure(watcher, className,
11496 "Unable to find instrumentation info for: " + className);
11497 return false;
11498 }
11499 if (ai == null) {
11500 reportStartInstrumentationFailure(watcher, className,
11501 "Unable to find instrumentation target package: " + ii.targetPackage);
11502 return false;
11503 }
11504
11505 int match = mContext.getPackageManager().checkSignatures(
11506 ii.targetPackage, ii.packageName);
11507 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11508 String msg = "Permission Denial: starting instrumentation "
11509 + className + " from pid="
11510 + Binder.getCallingPid()
11511 + ", uid=" + Binder.getCallingPid()
11512 + " not allowed because package " + ii.packageName
11513 + " does not have a signature matching the target "
11514 + ii.targetPackage;
11515 reportStartInstrumentationFailure(watcher, className, msg);
11516 throw new SecurityException(msg);
11517 }
11518
11519 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011520 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011521 ProcessRecord app = addAppLocked(ai);
11522 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011523 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011524 app.instrumentationProfileFile = profileFile;
11525 app.instrumentationArguments = arguments;
11526 app.instrumentationWatcher = watcher;
11527 app.instrumentationResultClass = className;
11528 Binder.restoreCallingIdentity(origId);
11529 }
11530
11531 return true;
11532 }
11533
11534 /**
11535 * Report errors that occur while attempting to start Instrumentation. Always writes the
11536 * error to the logs, but if somebody is watching, send the report there too. This enables
11537 * the "am" command to report errors with more information.
11538 *
11539 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11540 * @param cn The component name of the instrumentation.
11541 * @param report The error report.
11542 */
11543 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11544 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011545 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 try {
11547 if (watcher != null) {
11548 Bundle results = new Bundle();
11549 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11550 results.putString("Error", report);
11551 watcher.instrumentationStatus(cn, -1, results);
11552 }
11553 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011554 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011555 }
11556 }
11557
11558 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11559 if (app.instrumentationWatcher != null) {
11560 try {
11561 // NOTE: IInstrumentationWatcher *must* be oneway here
11562 app.instrumentationWatcher.instrumentationFinished(
11563 app.instrumentationClass,
11564 resultCode,
11565 results);
11566 } catch (RemoteException e) {
11567 }
11568 }
11569 app.instrumentationWatcher = null;
11570 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011571 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 app.instrumentationProfileFile = null;
11573 app.instrumentationArguments = null;
11574
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011575 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 }
11577
11578 public void finishInstrumentation(IApplicationThread target,
11579 int resultCode, Bundle results) {
11580 // Refuse possible leaked file descriptors
11581 if (results != null && results.hasFileDescriptors()) {
11582 throw new IllegalArgumentException("File descriptors passed in Intent");
11583 }
11584
11585 synchronized(this) {
11586 ProcessRecord app = getRecordForAppLocked(target);
11587 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011588 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011589 return;
11590 }
11591 final long origId = Binder.clearCallingIdentity();
11592 finishInstrumentationLocked(app, resultCode, results);
11593 Binder.restoreCallingIdentity(origId);
11594 }
11595 }
11596
11597 // =========================================================
11598 // CONFIGURATION
11599 // =========================================================
11600
11601 public ConfigurationInfo getDeviceConfigurationInfo() {
11602 ConfigurationInfo config = new ConfigurationInfo();
11603 synchronized (this) {
11604 config.reqTouchScreen = mConfiguration.touchscreen;
11605 config.reqKeyboardType = mConfiguration.keyboard;
11606 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011607 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11608 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011609 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11610 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011611 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11612 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11614 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011615 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 }
11617 return config;
11618 }
11619
11620 public Configuration getConfiguration() {
11621 Configuration ci;
11622 synchronized(this) {
11623 ci = new Configuration(mConfiguration);
11624 }
11625 return ci;
11626 }
11627
11628 public void updateConfiguration(Configuration values) {
11629 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11630 "updateConfiguration()");
11631
11632 synchronized(this) {
11633 if (values == null && mWindowManager != null) {
11634 // sentinel: fetch the current configuration from the window manager
11635 values = mWindowManager.computeNewConfiguration();
11636 }
11637
11638 final long origId = Binder.clearCallingIdentity();
11639 updateConfigurationLocked(values, null);
11640 Binder.restoreCallingIdentity(origId);
11641 }
11642 }
11643
11644 /**
11645 * Do either or both things: (1) change the current configuration, and (2)
11646 * make sure the given activity is running with the (now) current
11647 * configuration. Returns true if the activity has been left running, or
11648 * false if <var>starting</var> is being destroyed to match the new
11649 * configuration.
11650 */
11651 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011652 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 int changes = 0;
11654
11655 boolean kept = true;
11656
11657 if (values != null) {
11658 Configuration newConfig = new Configuration(mConfiguration);
11659 changes = newConfig.updateFrom(values);
11660 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011661 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011662 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663 }
11664
Doug Zongker2bec3d42009-12-04 12:52:44 -080011665 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666
11667 if (values.locale != null) {
11668 saveLocaleLocked(values.locale,
11669 !values.locale.equals(mConfiguration.locale),
11670 values.userSetLocale);
11671 }
11672
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011673 mConfigurationSeq++;
11674 if (mConfigurationSeq <= 0) {
11675 mConfigurationSeq = 1;
11676 }
11677 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011678 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011679 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011680
11681 AttributeCache ac = AttributeCache.instance();
11682 if (ac != null) {
11683 ac.updateConfiguration(mConfiguration);
11684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011685
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011686 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11687 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11688 msg.obj = new Configuration(mConfiguration);
11689 mHandler.sendMessage(msg);
11690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011691
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011692 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11693 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011694 try {
11695 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011696 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011697 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011698 app.thread.scheduleConfigurationChanged(mConfiguration);
11699 }
11700 } catch (Exception e) {
11701 }
11702 }
11703 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011704 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11705 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11707 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011708 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11709 broadcastIntentLocked(null, null,
11710 new Intent(Intent.ACTION_LOCALE_CHANGED),
11711 null, null, 0, null, null,
11712 null, false, false, MY_PID, Process.SYSTEM_UID);
11713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011714 }
11715 }
11716
11717 if (changes != 0 && starting == null) {
11718 // If the configuration changed, and the caller is not already
11719 // in the process of starting an activity, then find the top
11720 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011721 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 }
11723
11724 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011725 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011726 if (kept) {
11727 // If this didn't result in the starting activity being
11728 // destroyed, then we need to make sure at this point that all
11729 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011730 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011732 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011733 }
11734 }
11735
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011736 if (values != null && mWindowManager != null) {
11737 mWindowManager.setNewConfiguration(mConfiguration);
11738 }
11739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011740 return kept;
11741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011742
11743 /**
11744 * Save the locale. You must be inside a synchronized (this) block.
11745 */
11746 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11747 if(isDiff) {
11748 SystemProperties.set("user.language", l.getLanguage());
11749 SystemProperties.set("user.region", l.getCountry());
11750 }
11751
11752 if(isPersist) {
11753 SystemProperties.set("persist.sys.language", l.getLanguage());
11754 SystemProperties.set("persist.sys.country", l.getCountry());
11755 SystemProperties.set("persist.sys.localevar", l.getVariant());
11756 }
11757 }
11758
11759 // =========================================================
11760 // LIFETIME MANAGEMENT
11761 // =========================================================
11762
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011763 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11764 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011765 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011766 // This adjustment has already been computed. If we are calling
11767 // from the top, we may have already computed our adjustment with
11768 // an earlier hidden adjustment that isn't really for us... if
11769 // so, use the new hidden adjustment.
11770 if (!recursed && app.hidden) {
11771 app.curAdj = hiddenAdj;
11772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011773 return app.curAdj;
11774 }
11775
11776 if (app.thread == null) {
11777 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011778 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 return (app.curAdj=EMPTY_APP_ADJ);
11780 }
11781
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011782 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11783 // The max adjustment doesn't allow this app to be anything
11784 // below foreground, so it is not worth doing work for it.
11785 app.adjType = "fixed";
11786 app.adjSeq = mAdjSeq;
11787 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011788 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011789 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11790 return (app.curAdj=app.maxAdj);
11791 }
11792
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011793 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011794 app.adjSource = null;
11795 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011796 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011797 app.empty = false;
11798 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011799
The Android Open Source Project4df24232009-03-05 14:34:35 -080011800 // Determine the importance of the process, starting with most
11801 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011803 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011805 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011806 // The last app on the list is the foreground app.
11807 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011808 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011809 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011810 } else if (app.instrumentationClass != null) {
11811 // Don't want to kill running instrumentation.
11812 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011813 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011814 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011815 } else if (app.curReceiver != null ||
11816 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11817 // An app that is currently receiving a broadcast also
11818 // counts as being in the foreground.
11819 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011820 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011821 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011822 } else if (app.executingServices.size() > 0) {
11823 // An app that is currently executing a service callback also
11824 // counts as being in the foreground.
11825 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011826 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011827 app.adjType = "exec-service";
11828 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011829 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011830 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011831 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011832 app.adjType = "foreground-service";
11833 } else if (app.forcingToForeground != null) {
11834 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011835 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011836 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011837 app.adjType = "force-foreground";
11838 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011839 } else if (app == mHeavyWeightProcess) {
11840 // We don't want to kill the current heavy-weight process.
11841 adj = HEAVY_WEIGHT_APP_ADJ;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011842 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011843 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011844 } else if (app == mHomeProcess) {
11845 // This process is hosting what we currently consider to be the
11846 // home app, so we don't want to let it go into the background.
11847 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011848 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011849 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 } else if ((N=app.activities.size()) != 0) {
11851 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011852 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011853 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011854 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011855 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011856 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011857 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011858 ActivityRecord r = app.activities.get(j);
11859 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011860 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011861 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011862 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011863 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011864 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011866 } else if (r.state == ActivityState.PAUSING
11867 || r.state == ActivityState.PAUSED
11868 || r.state == ActivityState.STOPPING) {
11869 adj = PERCEPTIBLE_APP_ADJ;
11870 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011871 }
11872 }
11873 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011874 // A very not-needed process. If this is lower in the lru list,
11875 // we will push it in to the empty bucket.
11876 app.hidden = true;
11877 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011878 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011879 adj = hiddenAdj;
11880 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881 }
11882
Joe Onorato8a9b2202010-02-26 18:56:32 -080011883 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011884
The Android Open Source Project4df24232009-03-05 14:34:35 -080011885 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011886 // there are applications dependent on our services or providers, but
11887 // this gives us a baseline and makes sure we don't get into an
11888 // infinite recursion.
11889 app.adjSeq = mAdjSeq;
11890 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011891
Christopher Tate6fa95972009-06-05 18:43:55 -070011892 if (mBackupTarget != null && app == mBackupTarget.app) {
11893 // If possible we want to avoid killing apps while they're being backed up
11894 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011895 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011896 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011897 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011898 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011899 }
11900 }
11901
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011902 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11903 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011904 final long now = SystemClock.uptimeMillis();
11905 // This process is more important if the top activity is
11906 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011907 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011908 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011909 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 if (s.startRequested) {
11911 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11912 // This service has seen some activity within
11913 // recent memory, so we will keep its process ahead
11914 // of the background processes.
11915 if (adj > SECONDARY_SERVER_ADJ) {
11916 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011917 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011918 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011919 }
11920 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011921 // If we have let the service slide into the background
11922 // state, still have some text describing what it is doing
11923 // even though the service no longer has an impact.
11924 if (adj > SECONDARY_SERVER_ADJ) {
11925 app.adjType = "started-bg-services";
11926 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011927 // Don't kill this process because it is doing work; it
11928 // has said it is doing work.
11929 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011930 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011931 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11932 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011933 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934 = s.connections.values().iterator();
11935 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011936 ArrayList<ConnectionRecord> clist = kt.next();
11937 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11938 // XXX should compute this based on the max of
11939 // all connected clients.
11940 ConnectionRecord cr = clist.get(i);
11941 if (cr.binding.client == app) {
11942 // Binding to ourself is not interesting.
11943 continue;
11944 }
11945 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11946 ProcessRecord client = cr.binding.client;
11947 int myHiddenAdj = hiddenAdj;
11948 if (myHiddenAdj > client.hiddenAdj) {
11949 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11950 myHiddenAdj = client.hiddenAdj;
11951 } else {
11952 myHiddenAdj = VISIBLE_APP_ADJ;
11953 }
11954 }
11955 int clientAdj = computeOomAdjLocked(
11956 client, myHiddenAdj, TOP_APP, true);
11957 if (adj > clientAdj) {
11958 adj = clientAdj >= VISIBLE_APP_ADJ
11959 ? clientAdj : VISIBLE_APP_ADJ;
11960 if (!client.hidden) {
11961 app.hidden = false;
11962 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011963 if (client.keeping) {
11964 app.keeping = true;
11965 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011966 app.adjType = "service";
11967 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11968 .REASON_SERVICE_IN_USE;
11969 app.adjSource = cr.binding.client;
11970 app.adjTarget = s.name;
11971 }
11972 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11973 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11974 schedGroup = Process.THREAD_GROUP_DEFAULT;
11975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011976 }
11977 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011978 ActivityRecord a = cr.activity;
11979 //if (a != null) {
11980 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11981 //}
11982 if (a != null && adj > FOREGROUND_APP_ADJ &&
11983 (a.state == ActivityState.RESUMED
11984 || a.state == ActivityState.PAUSING)) {
11985 adj = FOREGROUND_APP_ADJ;
11986 schedGroup = Process.THREAD_GROUP_DEFAULT;
11987 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011988 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011989 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11990 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011991 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011992 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011994 }
11995 }
11996 }
11997 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011998
Dianne Hackborn287952c2010-09-22 22:34:31 -070011999 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012000 // would like to avoid killing it unless it would prevent the current
12001 // application from running. By default we put the process in
12002 // with the rest of the background processes; as we scan through
12003 // its services we may bump it up from there.
12004 if (adj > hiddenAdj) {
12005 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012006 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012007 app.adjType = "bg-services";
12008 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012009 }
12010
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012011 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12012 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012013 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012014 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12015 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012016 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 if (cpr.clients.size() != 0) {
12018 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12019 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12020 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012021 if (client == app) {
12022 // Being our own client is not interesting.
12023 continue;
12024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 int myHiddenAdj = hiddenAdj;
12026 if (myHiddenAdj > client.hiddenAdj) {
12027 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12028 myHiddenAdj = client.hiddenAdj;
12029 } else {
12030 myHiddenAdj = FOREGROUND_APP_ADJ;
12031 }
12032 }
12033 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012034 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012035 if (adj > clientAdj) {
12036 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012037 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012038 if (!client.hidden) {
12039 app.hidden = false;
12040 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012041 if (client.keeping) {
12042 app.keeping = true;
12043 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012044 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012045 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12046 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012047 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012048 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012050 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12051 schedGroup = Process.THREAD_GROUP_DEFAULT;
12052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012053 }
12054 }
12055 // If the provider has external (non-framework) process
12056 // dependencies, ensure that its adjustment is at least
12057 // FOREGROUND_APP_ADJ.
12058 if (cpr.externals != 0) {
12059 if (adj > FOREGROUND_APP_ADJ) {
12060 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012061 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012062 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012063 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012064 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012065 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012066 }
12067 }
12068 }
12069 }
12070
12071 app.curRawAdj = adj;
12072
Joe Onorato8a9b2202010-02-26 18:56:32 -080012073 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012074 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12075 if (adj > app.maxAdj) {
12076 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012077 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012078 schedGroup = Process.THREAD_GROUP_DEFAULT;
12079 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012080 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012081 if (adj < HIDDEN_APP_MIN_ADJ) {
12082 app.keeping = true;
12083 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012084
12085 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012086 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012088 return adj;
12089 }
12090
12091 /**
12092 * Ask a given process to GC right now.
12093 */
12094 final void performAppGcLocked(ProcessRecord app) {
12095 try {
12096 app.lastRequestedGc = SystemClock.uptimeMillis();
12097 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012098 if (app.reportLowMemory) {
12099 app.reportLowMemory = false;
12100 app.thread.scheduleLowMemory();
12101 } else {
12102 app.thread.processInBackground();
12103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012104 }
12105 } catch (Exception e) {
12106 // whatever.
12107 }
12108 }
12109
12110 /**
12111 * Returns true if things are idle enough to perform GCs.
12112 */
Josh Bartel7f208742010-02-25 11:01:44 -060012113 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012114 return mParallelBroadcasts.size() == 0
12115 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012116 && (mSleeping || (mMainStack.mResumedActivity != null &&
12117 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012118 }
12119
12120 /**
12121 * Perform GCs on all processes that are waiting for it, but only
12122 * if things are idle.
12123 */
12124 final void performAppGcsLocked() {
12125 final int N = mProcessesToGc.size();
12126 if (N <= 0) {
12127 return;
12128 }
Josh Bartel7f208742010-02-25 11:01:44 -060012129 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012130 while (mProcessesToGc.size() > 0) {
12131 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012132 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012133 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12134 <= SystemClock.uptimeMillis()) {
12135 // To avoid spamming the system, we will GC processes one
12136 // at a time, waiting a few seconds between each.
12137 performAppGcLocked(proc);
12138 scheduleAppGcsLocked();
12139 return;
12140 } else {
12141 // It hasn't been long enough since we last GCed this
12142 // process... put it in the list to wait for its time.
12143 addProcessToGcListLocked(proc);
12144 break;
12145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012146 }
12147 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012148
12149 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012150 }
12151 }
12152
12153 /**
12154 * If all looks good, perform GCs on all processes waiting for them.
12155 */
12156 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012157 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012158 performAppGcsLocked();
12159 return;
12160 }
12161 // Still not idle, wait some more.
12162 scheduleAppGcsLocked();
12163 }
12164
12165 /**
12166 * Schedule the execution of all pending app GCs.
12167 */
12168 final void scheduleAppGcsLocked() {
12169 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012170
12171 if (mProcessesToGc.size() > 0) {
12172 // Schedule a GC for the time to the next process.
12173 ProcessRecord proc = mProcessesToGc.get(0);
12174 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12175
12176 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12177 long now = SystemClock.uptimeMillis();
12178 if (when < (now+GC_TIMEOUT)) {
12179 when = now + GC_TIMEOUT;
12180 }
12181 mHandler.sendMessageAtTime(msg, when);
12182 }
12183 }
12184
12185 /**
12186 * Add a process to the array of processes waiting to be GCed. Keeps the
12187 * list in sorted order by the last GC time. The process can't already be
12188 * on the list.
12189 */
12190 final void addProcessToGcListLocked(ProcessRecord proc) {
12191 boolean added = false;
12192 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12193 if (mProcessesToGc.get(i).lastRequestedGc <
12194 proc.lastRequestedGc) {
12195 added = true;
12196 mProcessesToGc.add(i+1, proc);
12197 break;
12198 }
12199 }
12200 if (!added) {
12201 mProcessesToGc.add(0, proc);
12202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012203 }
12204
12205 /**
12206 * Set up to ask a process to GC itself. This will either do it
12207 * immediately, or put it on the list of processes to gc the next
12208 * time things are idle.
12209 */
12210 final void scheduleAppGcLocked(ProcessRecord app) {
12211 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012212 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012213 return;
12214 }
12215 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012216 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012217 scheduleAppGcsLocked();
12218 }
12219 }
12220
Dianne Hackborn287952c2010-09-22 22:34:31 -070012221 final void checkExcessivePowerUsageLocked(boolean doKills) {
12222 updateCpuStatsNow();
12223
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012224 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012225 boolean doWakeKills = doKills;
12226 boolean doCpuKills = doKills;
12227 if (mLastPowerCheckRealtime == 0) {
12228 doWakeKills = false;
12229 }
12230 if (mLastPowerCheckUptime == 0) {
12231 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012232 }
12233 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012234 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012235 }
12236 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012237 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12238 final long curUptime = SystemClock.uptimeMillis();
12239 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12240 mLastPowerCheckRealtime = curRealtime;
12241 mLastPowerCheckUptime = curUptime;
12242 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12243 doWakeKills = false;
12244 }
12245 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12246 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012247 }
12248 int i = mLruProcesses.size();
12249 while (i > 0) {
12250 i--;
12251 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012252 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012253 long wtime;
12254 synchronized (stats) {
12255 wtime = stats.getProcessWakeTime(app.info.uid,
12256 app.pid, curRealtime);
12257 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012258 long wtimeUsed = wtime - app.lastWakeTime;
12259 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12260 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012261 StringBuilder sb = new StringBuilder(128);
12262 sb.append("Wake for ");
12263 app.toShortString(sb);
12264 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012265 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012266 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012267 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012268 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012269 sb.append((wtimeUsed*100)/realtimeSince);
12270 sb.append("%)");
12271 Slog.i(TAG, sb.toString());
12272 sb.setLength(0);
12273 sb.append("CPU for ");
12274 app.toShortString(sb);
12275 sb.append(": over ");
12276 TimeUtils.formatDuration(uptimeSince, sb);
12277 sb.append(" used ");
12278 TimeUtils.formatDuration(cputimeUsed, sb);
12279 sb.append(" (");
12280 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012281 sb.append("%)");
12282 Slog.i(TAG, sb.toString());
12283 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012284 // If a process has held a wake lock for more
12285 // than 50% of the time during this period,
12286 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012287 if (doWakeKills && realtimeSince > 0
12288 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12289 synchronized (stats) {
12290 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12291 realtimeSince, wtimeUsed);
12292 }
12293 Slog.w(TAG, "Excessive wake lock in " + app.processName
12294 + " (pid " + app.pid + "): held " + wtimeUsed
12295 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012296 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12297 app.processName, app.setAdj, "excessive wake lock");
12298 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012299 } else if (doCpuKills && uptimeSince > 0
12300 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12301 synchronized (stats) {
12302 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12303 uptimeSince, cputimeUsed);
12304 }
12305 Slog.w(TAG, "Excessive CPU in " + app.processName
12306 + " (pid " + app.pid + "): used " + cputimeUsed
12307 + " during " + uptimeSince);
12308 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12309 app.processName, app.setAdj, "excessive cpu");
12310 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012311 } else {
12312 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012313 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012314 }
12315 }
12316 }
12317 }
12318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012319 private final boolean updateOomAdjLocked(
12320 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12321 app.hiddenAdj = hiddenAdj;
12322
12323 if (app.thread == null) {
12324 return true;
12325 }
12326
Dianne Hackborn287952c2010-09-22 22:34:31 -070012327 final boolean wasKeeping = app.keeping;
12328
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012329 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012330
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012331 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012332 if (app.curRawAdj != app.setRawAdj) {
12333 if (app.curRawAdj > FOREGROUND_APP_ADJ
12334 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12335 // If this app is transitioning from foreground to
12336 // non-foreground, have it do a gc.
12337 scheduleAppGcLocked(app);
12338 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12339 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12340 // Likewise do a gc when an app is moving in to the
12341 // background (such as a service stopping).
12342 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012343 }
12344
12345 if (wasKeeping && !app.keeping) {
12346 // This app is no longer something we want to keep. Note
12347 // its current wake lock time to later know to kill it if
12348 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012349 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12350 synchronized (stats) {
12351 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12352 app.pid, SystemClock.elapsedRealtime());
12353 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012354 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012355 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012357 app.setRawAdj = app.curRawAdj;
12358 }
12359 if (adj != app.setAdj) {
12360 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012361 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012362 TAG, "Set app " + app.processName +
12363 " oom adj to " + adj);
12364 app.setAdj = adj;
12365 } else {
12366 return false;
12367 }
12368 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012369 if (app.setSchedGroup != app.curSchedGroup) {
12370 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012371 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012372 "Setting process group of " + app.processName
12373 + " to " + app.curSchedGroup);
12374 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012375 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012376 try {
12377 Process.setProcessGroup(app.pid, app.curSchedGroup);
12378 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012379 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012380 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012381 e.printStackTrace();
12382 } finally {
12383 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012384 }
12385 }
12386 if (false) {
12387 if (app.thread != null) {
12388 try {
12389 app.thread.setSchedulingGroup(app.curSchedGroup);
12390 } catch (RemoteException e) {
12391 }
12392 }
12393 }
12394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012395 }
12396
12397 return true;
12398 }
12399
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012400 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012401 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012402 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012403 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012404 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012405 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012406 }
12407 }
12408 return resumedActivity;
12409 }
12410
12411 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012412 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012413 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12414 int curAdj = app.curAdj;
12415 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12416 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12417
12418 mAdjSeq++;
12419
12420 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12421 if (res) {
12422 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12423 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12424 if (nowHidden != wasHidden) {
12425 // Changed to/from hidden state, so apps after it in the LRU
12426 // list may also be changed.
12427 updateOomAdjLocked();
12428 }
12429 }
12430 return res;
12431 }
12432
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012433 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012434 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012435 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012436 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12437
12438 if (false) {
12439 RuntimeException e = new RuntimeException();
12440 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012441 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012442 }
12443
12444 mAdjSeq++;
12445
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012446 // Let's determine how many processes we have running vs.
12447 // how many slots we have for background processes; we may want
12448 // to put multiple processes in a slot of there are enough of
12449 // them.
12450 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12451 int factor = (mLruProcesses.size()-4)/numSlots;
12452 if (factor < 1) factor = 1;
12453 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012454 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012456 // First try updating the OOM adjustment for each of the
12457 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012458 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012459 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12460 while (i > 0) {
12461 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012462 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012463 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012464 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012465 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012466 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012467 step++;
12468 if (step >= factor) {
12469 step = 0;
12470 curHiddenAdj++;
12471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012472 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012473 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012474 if (!app.killedBackground) {
12475 numHidden++;
12476 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012477 Slog.i(TAG, "No longer want " + app.processName
12478 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012479 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12480 app.processName, app.setAdj, "too many background");
12481 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012482 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012483 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012484 }
12485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012486 } else {
12487 didOomAdj = false;
12488 }
12489 }
12490
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012491 // If we return false, we will fall back on killing processes to
12492 // have a fixed limit. Do this if a limit has been requested; else
12493 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012494 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12495 }
12496
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012497 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012498 synchronized (this) {
12499 int i;
12500
12501 // First remove any unused application processes whose package
12502 // has been removed.
12503 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12504 final ProcessRecord app = mRemovedProcesses.get(i);
12505 if (app.activities.size() == 0
12506 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012507 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012508 TAG, "Exiting empty application process "
12509 + app.processName + " ("
12510 + (app.thread != null ? app.thread.asBinder() : null)
12511 + ")\n");
12512 if (app.pid > 0 && app.pid != MY_PID) {
12513 Process.killProcess(app.pid);
12514 } else {
12515 try {
12516 app.thread.scheduleExit();
12517 } catch (Exception e) {
12518 // Ignore exceptions.
12519 }
12520 }
12521 cleanUpApplicationRecordLocked(app, false, -1);
12522 mRemovedProcesses.remove(i);
12523
12524 if (app.persistent) {
12525 if (app.persistent) {
12526 addAppLocked(app.info);
12527 }
12528 }
12529 }
12530 }
12531
12532 // Now try updating the OOM adjustment for each of the
12533 // application processes based on their current state.
12534 // If the setOomAdj() API is not supported, then go with our
12535 // back-up plan...
12536 if (!updateOomAdjLocked()) {
12537
12538 // Count how many processes are running services.
12539 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012540 for (i=mLruProcesses.size()-1; i>=0; i--) {
12541 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012542
12543 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012544 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012545 // Don't count processes holding services against our
12546 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012547 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012548 TAG, "Not trimming app " + app + " with services: "
12549 + app.services);
12550 numServiceProcs++;
12551 }
12552 }
12553
12554 int curMaxProcs = mProcessLimit;
12555 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12556 if (mAlwaysFinishActivities) {
12557 curMaxProcs = 1;
12558 }
12559 curMaxProcs += numServiceProcs;
12560
12561 // Quit as many processes as we can to get down to the desired
12562 // process count. First remove any processes that no longer
12563 // have activites running in them.
12564 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012565 i<mLruProcesses.size()
12566 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012567 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012568 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012569 // Quit an application only if it is not currently
12570 // running any activities.
12571 if (!app.persistent && app.activities.size() == 0
12572 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012573 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012574 TAG, "Exiting empty application process "
12575 + app.processName + " ("
12576 + (app.thread != null ? app.thread.asBinder() : null)
12577 + ")\n");
12578 if (app.pid > 0 && app.pid != MY_PID) {
12579 Process.killProcess(app.pid);
12580 } else {
12581 try {
12582 app.thread.scheduleExit();
12583 } catch (Exception e) {
12584 // Ignore exceptions.
12585 }
12586 }
12587 // todo: For now we assume the application is not buggy
12588 // or evil, and will quit as a result of our request.
12589 // Eventually we need to drive this off of the death
12590 // notification, and kill the process if it takes too long.
12591 cleanUpApplicationRecordLocked(app, false, i);
12592 i--;
12593 }
12594 }
12595
12596 // If we still have too many processes, now from the least
12597 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012598 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012599 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012600 " of " + curMaxProcs + " processes");
12601 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012602 i<mLruProcesses.size()
12603 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012604 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012605 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012606 // Quit the application only if we have a state saved for
12607 // all of its activities.
12608 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012609 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012610 int NUMA = app.activities.size();
12611 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012612 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012613 TAG, "Looking to quit " + app.processName);
12614 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012615 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012616 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012617 TAG, " " + r.intent.getComponent().flattenToShortString()
12618 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12619 canQuit = (r.haveState || !r.stateNotNeeded)
12620 && !r.visible && r.stopped;
12621 }
12622 if (canQuit) {
12623 // Finish all of the activities, and then the app itself.
12624 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012625 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012626 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012627 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012628 }
12629 r.resultTo = null;
12630 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012631 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012632 + app.processName + " ("
12633 + (app.thread != null ? app.thread.asBinder() : null)
12634 + ")\n");
12635 if (app.pid > 0 && app.pid != MY_PID) {
12636 Process.killProcess(app.pid);
12637 } else {
12638 try {
12639 app.thread.scheduleExit();
12640 } catch (Exception e) {
12641 // Ignore exceptions.
12642 }
12643 }
12644 // todo: For now we assume the application is not buggy
12645 // or evil, and will quit as a result of our request.
12646 // Eventually we need to drive this off of the death
12647 // notification, and kill the process if it takes too long.
12648 cleanUpApplicationRecordLocked(app, false, i);
12649 i--;
12650 //dump();
12651 }
12652 }
12653
12654 }
12655
12656 int curMaxActivities = MAX_ACTIVITIES;
12657 if (mAlwaysFinishActivities) {
12658 curMaxActivities = 1;
12659 }
12660
12661 // Finally, if there are too many activities now running, try to
12662 // finish as many as we can to get back down to the limit.
12663 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012664 i<mMainStack.mLRUActivities.size()
12665 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012666 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012667 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012668 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012669
12670 // We can finish this one if we have its icicle saved and
12671 // it is not persistent.
12672 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012673 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012674 final int origSize = mMainStack.mLRUActivities.size();
12675 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012676
12677 // This will remove it from the LRU list, so keep
12678 // our index at the same value. Note that this check to
12679 // see if the size changes is just paranoia -- if
12680 // something unexpected happens, we don't want to end up
12681 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012682 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012683 i--;
12684 }
12685 }
12686 }
12687 }
12688 }
12689
12690 /** This method sends the specified signal to each of the persistent apps */
12691 public void signalPersistentProcesses(int sig) throws RemoteException {
12692 if (sig != Process.SIGNAL_USR1) {
12693 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12694 }
12695
12696 synchronized (this) {
12697 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12698 != PackageManager.PERMISSION_GRANTED) {
12699 throw new SecurityException("Requires permission "
12700 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12701 }
12702
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012703 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12704 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012705 if (r.thread != null && r.persistent) {
12706 Process.sendSignal(r.pid, sig);
12707 }
12708 }
12709 }
12710 }
12711
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012712 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012713 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012714
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012715 try {
12716 synchronized (this) {
12717 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12718 // its own permission.
12719 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12720 != PackageManager.PERMISSION_GRANTED) {
12721 throw new SecurityException("Requires permission "
12722 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012723 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012724
12725 if (start && fd == null) {
12726 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012727 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012728
12729 ProcessRecord proc = null;
12730 try {
12731 int pid = Integer.parseInt(process);
12732 synchronized (mPidsSelfLocked) {
12733 proc = mPidsSelfLocked.get(pid);
12734 }
12735 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012736 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012737
12738 if (proc == null) {
12739 HashMap<String, SparseArray<ProcessRecord>> all
12740 = mProcessNames.getMap();
12741 SparseArray<ProcessRecord> procs = all.get(process);
12742 if (procs != null && procs.size() > 0) {
12743 proc = procs.valueAt(0);
12744 }
12745 }
12746
12747 if (proc == null || proc.thread == null) {
12748 throw new IllegalArgumentException("Unknown process: " + process);
12749 }
12750
12751 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12752 if (isSecure) {
12753 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12754 throw new SecurityException("Process not debuggable: " + proc);
12755 }
12756 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012757
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012758 proc.thread.profilerControl(start, path, fd);
12759 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012760 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012761 }
12762 } catch (RemoteException e) {
12763 throw new IllegalStateException("Process disappeared");
12764 } finally {
12765 if (fd != null) {
12766 try {
12767 fd.close();
12768 } catch (IOException e) {
12769 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012770 }
12771 }
12772 }
Andy McFadden824c5102010-07-09 16:26:57 -070012773
12774 public boolean dumpHeap(String process, boolean managed,
12775 String path, ParcelFileDescriptor fd) throws RemoteException {
12776
12777 try {
12778 synchronized (this) {
12779 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12780 // its own permission (same as profileControl).
12781 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12782 != PackageManager.PERMISSION_GRANTED) {
12783 throw new SecurityException("Requires permission "
12784 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12785 }
12786
12787 if (fd == null) {
12788 throw new IllegalArgumentException("null fd");
12789 }
12790
12791 ProcessRecord proc = null;
12792 try {
12793 int pid = Integer.parseInt(process);
12794 synchronized (mPidsSelfLocked) {
12795 proc = mPidsSelfLocked.get(pid);
12796 }
12797 } catch (NumberFormatException e) {
12798 }
12799
12800 if (proc == null) {
12801 HashMap<String, SparseArray<ProcessRecord>> all
12802 = mProcessNames.getMap();
12803 SparseArray<ProcessRecord> procs = all.get(process);
12804 if (procs != null && procs.size() > 0) {
12805 proc = procs.valueAt(0);
12806 }
12807 }
12808
12809 if (proc == null || proc.thread == null) {
12810 throw new IllegalArgumentException("Unknown process: " + process);
12811 }
12812
12813 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12814 if (isSecure) {
12815 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12816 throw new SecurityException("Process not debuggable: " + proc);
12817 }
12818 }
12819
12820 proc.thread.dumpHeap(managed, path, fd);
12821 fd = null;
12822 return true;
12823 }
12824 } catch (RemoteException e) {
12825 throw new IllegalStateException("Process disappeared");
12826 } finally {
12827 if (fd != null) {
12828 try {
12829 fd.close();
12830 } catch (IOException e) {
12831 }
12832 }
12833 }
12834 }
12835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012836 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12837 public void monitor() {
12838 synchronized (this) { }
12839 }
12840}