blob: a26fe5fa26c806ecf88acb3085a3118d97b74c8e [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;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003811 if (r.task != null) {
3812 r.task.lastThumbnail = r.thumbnail;
3813 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 r.description = description;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003816 if (r.task != null) {
3817 r.task.lastDescription = r.description;
3818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 r.stopped = true;
3820 r.state = ActivityState.STOPPED;
3821 if (!r.finishing) {
3822 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003823 r.stack.destroyActivityLocked(r, true);
3824 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003825 }
3826 }
3827 }
3828 }
3829
3830 if (r != null) {
3831 sendPendingThumbnail(r, null, null, null, false);
3832 }
3833
3834 trimApplications();
3835
3836 Binder.restoreCallingIdentity(origId);
3837 }
3838
3839 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003840 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003841 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003842 }
3843
3844 public String getCallingPackage(IBinder token) {
3845 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003846 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003847 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003848 }
3849 }
3850
3851 public ComponentName getCallingActivity(IBinder token) {
3852 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003853 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 return r != null ? r.intent.getComponent() : null;
3855 }
3856 }
3857
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003858 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003859 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003861 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 if (r != null) {
3863 return r.resultTo;
3864 }
3865 }
3866 return null;
3867 }
3868
3869 public ComponentName getActivityClassForToken(IBinder token) {
3870 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003871 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003873 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003874 return r.intent.getComponent();
3875 }
3876 return null;
3877 }
3878 }
3879
3880 public String getPackageForToken(IBinder token) {
3881 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003882 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003883 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003884 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003885 return r.packageName;
3886 }
3887 return null;
3888 }
3889 }
3890
3891 public IIntentSender getIntentSender(int type,
3892 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003893 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003895 if (intents != null) {
3896 if (intents.length < 1) {
3897 throw new IllegalArgumentException("Intents array length must be >= 1");
3898 }
3899 for (int i=0; i<intents.length; i++) {
3900 Intent intent = intents[i];
3901 if (intent == null) {
3902 throw new IllegalArgumentException("Null intent at index " + i);
3903 }
3904 if (intent.hasFileDescriptors()) {
3905 throw new IllegalArgumentException("File descriptors passed in Intent");
3906 }
3907 if (type == INTENT_SENDER_BROADCAST &&
3908 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3909 throw new IllegalArgumentException(
3910 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3911 }
3912 intents[i] = new Intent(intent);
3913 }
3914 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003915 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003916 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003917 }
3918 }
3919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 synchronized(this) {
3921 int callingUid = Binder.getCallingUid();
3922 try {
3923 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3924 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003925 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 .getPackageUid(packageName);
3927 if (uid != Binder.getCallingUid()) {
3928 String msg = "Permission Denial: getIntentSender() from pid="
3929 + Binder.getCallingPid()
3930 + ", uid=" + Binder.getCallingUid()
3931 + ", (need uid=" + uid + ")"
3932 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003933 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 throw new SecurityException(msg);
3935 }
3936 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003937
3938 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003939 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003941 } catch (RemoteException e) {
3942 throw new SecurityException(e);
3943 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003944 }
3945 }
3946
3947 IIntentSender getIntentSenderLocked(int type,
3948 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003949 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003950 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003951 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003952 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003953 if (index < 0) {
3954 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003956 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003957 if (activity.finishing) {
3958 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003959 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003960 }
3961
3962 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3963 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3964 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3965 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3966 |PendingIntent.FLAG_UPDATE_CURRENT);
3967
3968 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3969 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003970 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003971 WeakReference<PendingIntentRecord> ref;
3972 ref = mIntentSenderRecords.get(key);
3973 PendingIntentRecord rec = ref != null ? ref.get() : null;
3974 if (rec != null) {
3975 if (!cancelCurrent) {
3976 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003977 if (rec.key.requestIntent != null) {
3978 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3979 }
3980 if (intents != null) {
3981 intents[intents.length-1] = rec.key.requestIntent;
3982 rec.key.allIntents = intents;
3983 rec.key.allResolvedTypes = resolvedTypes;
3984 } else {
3985 rec.key.allIntents = null;
3986 rec.key.allResolvedTypes = null;
3987 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003989 return rec;
3990 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003991 rec.canceled = true;
3992 mIntentSenderRecords.remove(key);
3993 }
3994 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 return rec;
3996 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003997 rec = new PendingIntentRecord(this, key, callingUid);
3998 mIntentSenderRecords.put(key, rec.ref);
3999 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4000 if (activity.pendingResults == null) {
4001 activity.pendingResults
4002 = new HashSet<WeakReference<PendingIntentRecord>>();
4003 }
4004 activity.pendingResults.add(rec.ref);
4005 }
4006 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 }
4008
4009 public void cancelIntentSender(IIntentSender sender) {
4010 if (!(sender instanceof PendingIntentRecord)) {
4011 return;
4012 }
4013 synchronized(this) {
4014 PendingIntentRecord rec = (PendingIntentRecord)sender;
4015 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004016 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 .getPackageUid(rec.key.packageName);
4018 if (uid != Binder.getCallingUid()) {
4019 String msg = "Permission Denial: cancelIntentSender() from pid="
4020 + Binder.getCallingPid()
4021 + ", uid=" + Binder.getCallingUid()
4022 + " is not allowed to cancel packges "
4023 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004024 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004025 throw new SecurityException(msg);
4026 }
4027 } catch (RemoteException e) {
4028 throw new SecurityException(e);
4029 }
4030 cancelIntentSenderLocked(rec, true);
4031 }
4032 }
4033
4034 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4035 rec.canceled = true;
4036 mIntentSenderRecords.remove(rec.key);
4037 if (cleanActivity && rec.key.activity != null) {
4038 rec.key.activity.pendingResults.remove(rec.ref);
4039 }
4040 }
4041
4042 public String getPackageForIntentSender(IIntentSender pendingResult) {
4043 if (!(pendingResult instanceof PendingIntentRecord)) {
4044 return null;
4045 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004046 try {
4047 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4048 return res.key.packageName;
4049 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004050 }
4051 return null;
4052 }
4053
4054 public void setProcessLimit(int max) {
4055 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4056 "setProcessLimit()");
4057 mProcessLimit = max;
4058 }
4059
4060 public int getProcessLimit() {
4061 return mProcessLimit;
4062 }
4063
4064 void foregroundTokenDied(ForegroundToken token) {
4065 synchronized (ActivityManagerService.this) {
4066 synchronized (mPidsSelfLocked) {
4067 ForegroundToken cur
4068 = mForegroundProcesses.get(token.pid);
4069 if (cur != token) {
4070 return;
4071 }
4072 mForegroundProcesses.remove(token.pid);
4073 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4074 if (pr == null) {
4075 return;
4076 }
4077 pr.forcingToForeground = null;
4078 pr.foregroundServices = false;
4079 }
4080 updateOomAdjLocked();
4081 }
4082 }
4083
4084 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4085 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4086 "setProcessForeground()");
4087 synchronized(this) {
4088 boolean changed = false;
4089
4090 synchronized (mPidsSelfLocked) {
4091 ProcessRecord pr = mPidsSelfLocked.get(pid);
4092 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004093 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004094 return;
4095 }
4096 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4097 if (oldToken != null) {
4098 oldToken.token.unlinkToDeath(oldToken, 0);
4099 mForegroundProcesses.remove(pid);
4100 pr.forcingToForeground = null;
4101 changed = true;
4102 }
4103 if (isForeground && token != null) {
4104 ForegroundToken newToken = new ForegroundToken() {
4105 public void binderDied() {
4106 foregroundTokenDied(this);
4107 }
4108 };
4109 newToken.pid = pid;
4110 newToken.token = token;
4111 try {
4112 token.linkToDeath(newToken, 0);
4113 mForegroundProcesses.put(pid, newToken);
4114 pr.forcingToForeground = token;
4115 changed = true;
4116 } catch (RemoteException e) {
4117 // If the process died while doing this, we will later
4118 // do the cleanup with the process death link.
4119 }
4120 }
4121 }
4122
4123 if (changed) {
4124 updateOomAdjLocked();
4125 }
4126 }
4127 }
4128
4129 // =========================================================
4130 // PERMISSIONS
4131 // =========================================================
4132
4133 static class PermissionController extends IPermissionController.Stub {
4134 ActivityManagerService mActivityManagerService;
4135 PermissionController(ActivityManagerService activityManagerService) {
4136 mActivityManagerService = activityManagerService;
4137 }
4138
4139 public boolean checkPermission(String permission, int pid, int uid) {
4140 return mActivityManagerService.checkPermission(permission, pid,
4141 uid) == PackageManager.PERMISSION_GRANTED;
4142 }
4143 }
4144
4145 /**
4146 * This can be called with or without the global lock held.
4147 */
4148 int checkComponentPermission(String permission, int pid, int uid,
4149 int reqUid) {
4150 // We might be performing an operation on behalf of an indirect binder
4151 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4152 // client identity accordingly before proceeding.
4153 Identity tlsIdentity = sCallerIdentity.get();
4154 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004155 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004156 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4157 uid = tlsIdentity.uid;
4158 pid = tlsIdentity.pid;
4159 }
4160
4161 // Root, system server and our own process get to do everything.
4162 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4163 !Process.supportsProcesses()) {
4164 return PackageManager.PERMISSION_GRANTED;
4165 }
4166 // If the target requires a specific UID, always fail for others.
4167 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004168 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 return PackageManager.PERMISSION_DENIED;
4170 }
4171 if (permission == null) {
4172 return PackageManager.PERMISSION_GRANTED;
4173 }
4174 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004175 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004176 .checkUidPermission(permission, uid);
4177 } catch (RemoteException e) {
4178 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004179 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 }
4181 return PackageManager.PERMISSION_DENIED;
4182 }
4183
4184 /**
4185 * As the only public entry point for permissions checking, this method
4186 * can enforce the semantic that requesting a check on a null global
4187 * permission is automatically denied. (Internally a null permission
4188 * string is used when calling {@link #checkComponentPermission} in cases
4189 * when only uid-based security is needed.)
4190 *
4191 * This can be called with or without the global lock held.
4192 */
4193 public int checkPermission(String permission, int pid, int uid) {
4194 if (permission == null) {
4195 return PackageManager.PERMISSION_DENIED;
4196 }
4197 return checkComponentPermission(permission, pid, uid, -1);
4198 }
4199
4200 /**
4201 * Binder IPC calls go through the public entry point.
4202 * This can be called with or without the global lock held.
4203 */
4204 int checkCallingPermission(String permission) {
4205 return checkPermission(permission,
4206 Binder.getCallingPid(),
4207 Binder.getCallingUid());
4208 }
4209
4210 /**
4211 * This can be called with or without the global lock held.
4212 */
4213 void enforceCallingPermission(String permission, String func) {
4214 if (checkCallingPermission(permission)
4215 == PackageManager.PERMISSION_GRANTED) {
4216 return;
4217 }
4218
4219 String msg = "Permission Denial: " + func + " from pid="
4220 + Binder.getCallingPid()
4221 + ", uid=" + Binder.getCallingUid()
4222 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004223 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 throw new SecurityException(msg);
4225 }
4226
4227 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004228 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4229 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4230 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4231 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4232 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004233 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004234 // Is the component private from the target uid?
4235 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4236
4237 // Acceptable if the there is no read permission needed from the
4238 // target or the target is holding the read permission.
4239 if (!readPerm) {
4240 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004241 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004242 == PackageManager.PERMISSION_GRANTED)) {
4243 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004244 }
4245 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004246
4247 // Acceptable if the there is no write permission needed from the
4248 // target or the target is holding the read permission.
4249 if (!writePerm) {
4250 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004252 == PackageManager.PERMISSION_GRANTED)) {
4253 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 }
4255 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004256
4257 // Acceptable if there is a path permission matching the URI that
4258 // the target holds the permission on.
4259 PathPermission[] pps = pi.pathPermissions;
4260 if (pps != null && (!readPerm || !writePerm)) {
4261 final String path = uri.getPath();
4262 int i = pps.length;
4263 while (i > 0 && (!readPerm || !writePerm)) {
4264 i--;
4265 PathPermission pp = pps[i];
4266 if (!readPerm) {
4267 final String pprperm = pp.getReadPermission();
4268 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4269 + pprperm + " for " + pp.getPath()
4270 + ": match=" + pp.match(path)
4271 + " check=" + pm.checkUidPermission(pprperm, uid));
4272 if (pprperm != null && pp.match(path) &&
4273 (pm.checkUidPermission(pprperm, uid)
4274 == PackageManager.PERMISSION_GRANTED)) {
4275 readPerm = true;
4276 }
4277 }
4278 if (!writePerm) {
4279 final String ppwperm = pp.getWritePermission();
4280 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4281 + ppwperm + " for " + pp.getPath()
4282 + ": match=" + pp.match(path)
4283 + " check=" + pm.checkUidPermission(ppwperm, uid));
4284 if (ppwperm != null && pp.match(path) &&
4285 (pm.checkUidPermission(ppwperm, uid)
4286 == PackageManager.PERMISSION_GRANTED)) {
4287 writePerm = true;
4288 }
4289 }
4290 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 } catch (RemoteException e) {
4293 return false;
4294 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004295
4296 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004297 }
4298
4299 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4300 int modeFlags) {
4301 // Root gets to do everything.
4302 if (uid == 0 || !Process.supportsProcesses()) {
4303 return true;
4304 }
4305 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4306 if (perms == null) return false;
4307 UriPermission perm = perms.get(uri);
4308 if (perm == null) return false;
4309 return (modeFlags&perm.modeFlags) == modeFlags;
4310 }
4311
4312 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4313 // Another redirected-binder-call permissions check as in
4314 // {@link checkComponentPermission}.
4315 Identity tlsIdentity = sCallerIdentity.get();
4316 if (tlsIdentity != null) {
4317 uid = tlsIdentity.uid;
4318 pid = tlsIdentity.pid;
4319 }
4320
4321 // Our own process gets to do everything.
4322 if (pid == MY_PID) {
4323 return PackageManager.PERMISSION_GRANTED;
4324 }
4325 synchronized(this) {
4326 return checkUriPermissionLocked(uri, uid, modeFlags)
4327 ? PackageManager.PERMISSION_GRANTED
4328 : PackageManager.PERMISSION_DENIED;
4329 }
4330 }
4331
Dianne Hackborn39792d22010-08-19 18:01:52 -07004332 /**
4333 * Check if the targetPkg can be granted permission to access uri by
4334 * the callingUid using the given modeFlags. Throws a security exception
4335 * if callingUid is not allowed to do this. Returns the uid of the target
4336 * if the URI permission grant should be performed; returns -1 if it is not
4337 * needed (for example targetPkg already has permission to access the URI).
4338 */
4339 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4340 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4342 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4343 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004344 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 }
4346
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004347 if (targetPkg != null) {
4348 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4349 "Checking grant " + targetPkg + " permission to " + uri);
4350 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004351
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004352 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004353
4354 // If this is not a content: uri, we can't do anything with it.
4355 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004356 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004357 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004358 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 }
4360
4361 String name = uri.getAuthority();
4362 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004363 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 if (cpr != null) {
4365 pi = cpr.info;
4366 } else {
4367 try {
4368 pi = pm.resolveContentProvider(name,
4369 PackageManager.GET_URI_PERMISSION_PATTERNS);
4370 } catch (RemoteException ex) {
4371 }
4372 }
4373 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004374 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004375 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 }
4377
4378 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004379 if (targetPkg != null) {
4380 try {
4381 targetUid = pm.getPackageUid(targetPkg);
4382 if (targetUid < 0) {
4383 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4384 "Can't grant URI permission no uid for: " + targetPkg);
4385 return -1;
4386 }
4387 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004388 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004389 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004390 } else {
4391 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004392 }
4393
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004394 if (targetUid >= 0) {
4395 // First... does the target actually need this permission?
4396 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4397 // No need to grant the target this permission.
4398 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4399 "Target " + targetPkg + " already has full permission to " + uri);
4400 return -1;
4401 }
4402 } else {
4403 // First... there is no target package, so can anyone access it?
4404 boolean allowed = pi.exported;
4405 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4406 if (pi.readPermission != null) {
4407 allowed = false;
4408 }
4409 }
4410 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4411 if (pi.writePermission != null) {
4412 allowed = false;
4413 }
4414 }
4415 if (allowed) {
4416 return -1;
4417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004418 }
4419
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004420 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421 if (!pi.grantUriPermissions) {
4422 throw new SecurityException("Provider " + pi.packageName
4423 + "/" + pi.name
4424 + " does not allow granting of Uri permissions (uri "
4425 + uri + ")");
4426 }
4427 if (pi.uriPermissionPatterns != null) {
4428 final int N = pi.uriPermissionPatterns.length;
4429 boolean allowed = false;
4430 for (int i=0; i<N; i++) {
4431 if (pi.uriPermissionPatterns[i] != null
4432 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4433 allowed = true;
4434 break;
4435 }
4436 }
4437 if (!allowed) {
4438 throw new SecurityException("Provider " + pi.packageName
4439 + "/" + pi.name
4440 + " does not allow granting of permission to path of Uri "
4441 + uri);
4442 }
4443 }
4444
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004445 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004446 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004447 if (callingUid != Process.myUid()) {
4448 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4449 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4450 throw new SecurityException("Uid " + callingUid
4451 + " does not have permission to uri " + uri);
4452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 }
4454 }
4455
Dianne Hackborn39792d22010-08-19 18:01:52 -07004456 return targetUid;
4457 }
4458
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004459 public int checkGrantUriPermission(int callingUid, String targetPkg,
4460 Uri uri, int modeFlags) {
4461 synchronized(this) {
4462 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4463 }
4464 }
4465
Dianne Hackborn39792d22010-08-19 18:01:52 -07004466 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4467 Uri uri, int modeFlags, UriPermissionOwner owner) {
4468 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4469 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4470 if (modeFlags == 0) {
4471 return;
4472 }
4473
4474 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 // to the uri, and the target doesn't. Let's now give this to
4476 // the target.
4477
Joe Onorato8a9b2202010-02-26 18:56:32 -08004478 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004479 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004481 HashMap<Uri, UriPermission> targetUris
4482 = mGrantedUriPermissions.get(targetUid);
4483 if (targetUris == null) {
4484 targetUris = new HashMap<Uri, UriPermission>();
4485 mGrantedUriPermissions.put(targetUid, targetUris);
4486 }
4487
4488 UriPermission perm = targetUris.get(uri);
4489 if (perm == null) {
4490 perm = new UriPermission(targetUid, uri);
4491 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004494 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004495 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 perm.globalModeFlags |= modeFlags;
4497 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004498 perm.readOwners.add(owner);
4499 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004501 perm.writeOwners.add(owner);
4502 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 }
4504 }
4505
Dianne Hackborn39792d22010-08-19 18:01:52 -07004506 void grantUriPermissionLocked(int callingUid,
4507 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004508 if (targetPkg == null) {
4509 throw new NullPointerException("targetPkg");
4510 }
4511
Dianne Hackborn39792d22010-08-19 18:01:52 -07004512 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4513 if (targetUid < 0) {
4514 return;
4515 }
4516
4517 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4518 }
4519
4520 /**
4521 * Like checkGrantUriPermissionLocked, but takes an Intent.
4522 */
4523 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4524 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004525 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004526 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004527 + " from " + intent + "; flags=0x"
4528 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4529
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004530 if (targetPkg == null) {
4531 throw new NullPointerException("targetPkg");
4532 }
4533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004535 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 }
4537 Uri data = intent.getData();
4538 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004539 return -1;
4540 }
4541 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4542 intent.getFlags());
4543 }
4544
4545 /**
4546 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4547 */
4548 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4549 String targetPkg, Intent intent, UriPermissionOwner owner) {
4550 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4551 intent.getFlags(), owner);
4552 }
4553
4554 void grantUriPermissionFromIntentLocked(int callingUid,
4555 String targetPkg, Intent intent, UriPermissionOwner owner) {
4556 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4557 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004558 return;
4559 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004560
4561 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 }
4563
4564 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4565 Uri uri, int modeFlags) {
4566 synchronized(this) {
4567 final ProcessRecord r = getRecordForAppLocked(caller);
4568 if (r == null) {
4569 throw new SecurityException("Unable to find app for caller "
4570 + caller
4571 + " when granting permission to uri " + uri);
4572 }
4573 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004574 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 }
4576 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004577 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004578 }
4579
4580 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4581 null);
4582 }
4583 }
4584
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004585 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4587 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4588 HashMap<Uri, UriPermission> perms
4589 = mGrantedUriPermissions.get(perm.uid);
4590 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004591 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004592 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 perms.remove(perm.uri);
4594 if (perms.size() == 0) {
4595 mGrantedUriPermissions.remove(perm.uid);
4596 }
4597 }
4598 }
4599 }
4600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004601 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4602 int modeFlags) {
4603 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4604 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4605 if (modeFlags == 0) {
4606 return;
4607 }
4608
Joe Onorato8a9b2202010-02-26 18:56:32 -08004609 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004610 "Revoking all granted permissions to " + uri);
4611
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004612 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004613
4614 final String authority = uri.getAuthority();
4615 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004616 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617 if (cpr != null) {
4618 pi = cpr.info;
4619 } else {
4620 try {
4621 pi = pm.resolveContentProvider(authority,
4622 PackageManager.GET_URI_PERMISSION_PATTERNS);
4623 } catch (RemoteException ex) {
4624 }
4625 }
4626 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004627 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004628 return;
4629 }
4630
4631 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004632 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 // Right now, if you are not the original owner of the permission,
4634 // you are not allowed to revoke it.
4635 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4636 throw new SecurityException("Uid " + callingUid
4637 + " does not have permission to uri " + uri);
4638 //}
4639 }
4640
4641 // Go through all of the permissions and remove any that match.
4642 final List<String> SEGMENTS = uri.getPathSegments();
4643 if (SEGMENTS != null) {
4644 final int NS = SEGMENTS.size();
4645 int N = mGrantedUriPermissions.size();
4646 for (int i=0; i<N; i++) {
4647 HashMap<Uri, UriPermission> perms
4648 = mGrantedUriPermissions.valueAt(i);
4649 Iterator<UriPermission> it = perms.values().iterator();
4650 toploop:
4651 while (it.hasNext()) {
4652 UriPermission perm = it.next();
4653 Uri targetUri = perm.uri;
4654 if (!authority.equals(targetUri.getAuthority())) {
4655 continue;
4656 }
4657 List<String> targetSegments = targetUri.getPathSegments();
4658 if (targetSegments == null) {
4659 continue;
4660 }
4661 if (targetSegments.size() < NS) {
4662 continue;
4663 }
4664 for (int j=0; j<NS; j++) {
4665 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4666 continue toploop;
4667 }
4668 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004669 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004670 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004671 perm.clearModes(modeFlags);
4672 if (perm.modeFlags == 0) {
4673 it.remove();
4674 }
4675 }
4676 if (perms.size() == 0) {
4677 mGrantedUriPermissions.remove(
4678 mGrantedUriPermissions.keyAt(i));
4679 N--;
4680 i--;
4681 }
4682 }
4683 }
4684 }
4685
4686 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4687 int modeFlags) {
4688 synchronized(this) {
4689 final ProcessRecord r = getRecordForAppLocked(caller);
4690 if (r == null) {
4691 throw new SecurityException("Unable to find app for caller "
4692 + caller
4693 + " when revoking permission to uri " + uri);
4694 }
4695 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004696 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 return;
4698 }
4699
4700 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4701 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4702 if (modeFlags == 0) {
4703 return;
4704 }
4705
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004706 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707
4708 final String authority = uri.getAuthority();
4709 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004710 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 if (cpr != null) {
4712 pi = cpr.info;
4713 } else {
4714 try {
4715 pi = pm.resolveContentProvider(authority,
4716 PackageManager.GET_URI_PERMISSION_PATTERNS);
4717 } catch (RemoteException ex) {
4718 }
4719 }
4720 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004721 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 return;
4723 }
4724
4725 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4726 }
4727 }
4728
Dianne Hackborn7e269642010-08-25 19:50:20 -07004729 @Override
4730 public IBinder newUriPermissionOwner(String name) {
4731 synchronized(this) {
4732 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4733 return owner.getExternalTokenLocked();
4734 }
4735 }
4736
4737 @Override
4738 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4739 Uri uri, int modeFlags) {
4740 synchronized(this) {
4741 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4742 if (owner == null) {
4743 throw new IllegalArgumentException("Unknown owner: " + token);
4744 }
4745 if (fromUid != Binder.getCallingUid()) {
4746 if (Binder.getCallingUid() != Process.myUid()) {
4747 // Only system code can grant URI permissions on behalf
4748 // of other users.
4749 throw new SecurityException("nice try");
4750 }
4751 }
4752 if (targetPkg == null) {
4753 throw new IllegalArgumentException("null target");
4754 }
4755 if (uri == null) {
4756 throw new IllegalArgumentException("null uri");
4757 }
4758
4759 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4760 }
4761 }
4762
4763 @Override
4764 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4765 synchronized(this) {
4766 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4767 if (owner == null) {
4768 throw new IllegalArgumentException("Unknown owner: " + token);
4769 }
4770
4771 if (uri == null) {
4772 owner.removeUriPermissionsLocked(mode);
4773 } else {
4774 owner.removeUriPermissionLocked(uri, mode);
4775 }
4776 }
4777 }
4778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004779 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4780 synchronized (this) {
4781 ProcessRecord app =
4782 who != null ? getRecordForAppLocked(who) : null;
4783 if (app == null) return;
4784
4785 Message msg = Message.obtain();
4786 msg.what = WAIT_FOR_DEBUGGER_MSG;
4787 msg.obj = app;
4788 msg.arg1 = waiting ? 1 : 0;
4789 mHandler.sendMessage(msg);
4790 }
4791 }
4792
4793 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4794 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004795 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004797 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004798 }
4799
4800 // =========================================================
4801 // TASK MANAGEMENT
4802 // =========================================================
4803
4804 public List getTasks(int maxNum, int flags,
4805 IThumbnailReceiver receiver) {
4806 ArrayList list = new ArrayList();
4807
4808 PendingThumbnailsRecord pending = null;
4809 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004810 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811
4812 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004813 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4815 + ", receiver=" + receiver);
4816
4817 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4818 != PackageManager.PERMISSION_GRANTED) {
4819 if (receiver != null) {
4820 // If the caller wants to wait for pending thumbnails,
4821 // it ain't gonna get them.
4822 try {
4823 receiver.finished();
4824 } catch (RemoteException ex) {
4825 }
4826 }
4827 String msg = "Permission Denial: getTasks() from pid="
4828 + Binder.getCallingPid()
4829 + ", uid=" + Binder.getCallingUid()
4830 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004831 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 throw new SecurityException(msg);
4833 }
4834
Dianne Hackbornd2835932010-12-13 16:28:46 -08004835 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4836 && checkCallingPermission(
4837 android.Manifest.permission.READ_FRAME_BUFFER)
4838 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004839
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004840 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004841 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004842 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004843 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 CharSequence topDescription = null;
4845 TaskRecord curTask = null;
4846 int numActivities = 0;
4847 int numRunning = 0;
4848 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004849 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004850 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004851 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004852
4853 // Initialize state for next task if needed.
4854 if (top == null ||
4855 (top.state == ActivityState.INITIALIZING
4856 && top.task == r.task)) {
4857 top = r;
4858 topDescription = r.description;
4859 curTask = r.task;
4860 numActivities = numRunning = 0;
4861 }
4862
4863 // Add 'r' into the current task.
4864 numActivities++;
4865 if (r.app != null && r.app.thread != null) {
4866 numRunning++;
4867 }
4868 if (topDescription == null) {
4869 topDescription = r.description;
4870 }
4871
Joe Onorato8a9b2202010-02-26 18:56:32 -08004872 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873 TAG, r.intent.getComponent().flattenToShortString()
4874 + ": task=" + r.task);
4875
4876 // If the next one is a different task, generate a new
4877 // TaskInfo entry for what we have.
4878 if (next == null || next.task != curTask) {
4879 ActivityManager.RunningTaskInfo ci
4880 = new ActivityManager.RunningTaskInfo();
4881 ci.id = curTask.taskId;
4882 ci.baseActivity = r.intent.getComponent();
4883 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004884 if (canReadFb) {
4885 if (top.thumbnail != null) {
4886 ci.thumbnail = top.thumbnail;
4887 } else if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004888 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004889 }
4890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 ci.description = topDescription;
4892 ci.numActivities = numActivities;
4893 ci.numRunning = numRunning;
4894 //System.out.println(
4895 // "#" + maxNum + ": " + " descr=" + ci.description);
4896 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004897 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004898 TAG, "State=" + top.state + "Idle=" + top.idle
4899 + " app=" + top.app
4900 + " thr=" + (top.app != null ? top.app.thread : null));
4901 if (top.state == ActivityState.RESUMED
4902 || top.state == ActivityState.PAUSING) {
4903 if (top.idle && top.app != null
4904 && top.app.thread != null) {
4905 topRecord = top;
4906 topThumbnail = top.app.thread;
4907 } else {
4908 top.thumbnailNeeded = true;
4909 }
4910 }
4911 if (pending == null) {
4912 pending = new PendingThumbnailsRecord(receiver);
4913 }
4914 pending.pendingRecords.add(top);
4915 }
4916 list.add(ci);
4917 maxNum--;
4918 top = null;
4919 }
4920 }
4921
4922 if (pending != null) {
4923 mPendingThumbnails.add(pending);
4924 }
4925 }
4926
Joe Onorato8a9b2202010-02-26 18:56:32 -08004927 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928
4929 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004930 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004931 try {
4932 topThumbnail.requestThumbnail(topRecord);
4933 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004934 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004935 sendPendingThumbnail(null, topRecord, null, null, true);
4936 }
4937 }
4938
4939 if (pending == null && receiver != null) {
4940 // In this case all thumbnails were available and the client
4941 // is being asked to be told when the remaining ones come in...
4942 // which is unusually, since the top-most currently running
4943 // activity should never have a canned thumbnail! Oh well.
4944 try {
4945 receiver.finished();
4946 } catch (RemoteException ex) {
4947 }
4948 }
4949
4950 return list;
4951 }
4952
4953 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4954 int flags) {
4955 synchronized (this) {
4956 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4957 "getRecentTasks()");
4958
Dianne Hackbornd2835932010-12-13 16:28:46 -08004959 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4960 && checkCallingPermission(
4961 android.Manifest.permission.READ_FRAME_BUFFER)
4962 == PackageManager.PERMISSION_GRANTED;
4963
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004964 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004965
Dianne Hackbornd2835932010-12-13 16:28:46 -08004966 ActivityRecord resumed = mMainStack.mResumedActivity;
4967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968 final int N = mRecentTasks.size();
4969 ArrayList<ActivityManager.RecentTaskInfo> res
4970 = new ArrayList<ActivityManager.RecentTaskInfo>(
4971 maxNum < N ? maxNum : N);
4972 for (int i=0; i<N && maxNum > 0; i++) {
4973 TaskRecord tr = mRecentTasks.get(i);
4974 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4975 || (tr.intent == null)
4976 || ((tr.intent.getFlags()
4977 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4978 ActivityManager.RecentTaskInfo rti
4979 = new ActivityManager.RecentTaskInfo();
4980 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4981 rti.baseIntent = new Intent(
4982 tr.intent != null ? tr.intent : tr.affinityIntent);
4983 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004984
Dianne Hackbornd2835932010-12-13 16:28:46 -08004985 if (canReadFb) {
4986 if (resumed != null && resumed.task == tr) {
4987 rti.thumbnail = resumed.stack.screenshotActivities(resumed);
4988 } else {
4989 rti.thumbnail = tr.lastThumbnail;
4990 }
4991 }
4992 rti.description = tr.lastDescription;
4993
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004994 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4995 // Check whether this activity is currently available.
4996 try {
4997 if (rti.origActivity != null) {
4998 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4999 continue;
5000 }
5001 } else if (rti.baseIntent != null) {
5002 if (pm.queryIntentActivities(rti.baseIntent,
5003 null, 0) == null) {
5004 continue;
5005 }
5006 }
5007 } catch (RemoteException e) {
5008 // Will never happen.
5009 }
5010 }
5011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005012 res.add(rti);
5013 maxNum--;
5014 }
5015 }
5016 return res;
5017 }
5018 }
5019
5020 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5021 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005022 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 TaskRecord jt = startTask;
5024
5025 // First look backwards
5026 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005027 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005028 if (r.task != jt) {
5029 jt = r.task;
5030 if (affinity.equals(jt.affinity)) {
5031 return j;
5032 }
5033 }
5034 }
5035
5036 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005037 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 jt = startTask;
5039 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005040 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 if (r.task != jt) {
5042 if (affinity.equals(jt.affinity)) {
5043 return j;
5044 }
5045 jt = r.task;
5046 }
5047 }
5048
5049 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005050 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 return N-1;
5052 }
5053
5054 return -1;
5055 }
5056
5057 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005058 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005059 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005060 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005061 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5062 "moveTaskToFront()");
5063
5064 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005065 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5066 Binder.getCallingUid(), "Task to front")) {
5067 return;
5068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 final long origId = Binder.clearCallingIdentity();
5070 try {
5071 int N = mRecentTasks.size();
5072 for (int i=0; i<N; i++) {
5073 TaskRecord tr = mRecentTasks.get(i);
5074 if (tr.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005075 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5076 // Caller wants the home activity moved with it. To accomplish this,
5077 // we'll just move the home task to the top first.
5078 mMainStack.moveHomeToFrontLocked();
5079 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005080 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005081 return;
5082 }
5083 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005084 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5085 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005086 if (hr.task.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005087 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5088 // Caller wants the home activity moved with it. To accomplish this,
5089 // we'll just move the home task to the top first.
5090 mMainStack.moveHomeToFrontLocked();
5091 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005092 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 return;
5094 }
5095 }
5096 } finally {
5097 Binder.restoreCallingIdentity(origId);
5098 }
5099 }
5100 }
5101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 public void moveTaskToBack(int task) {
5103 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5104 "moveTaskToBack()");
5105
5106 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005107 if (mMainStack.mResumedActivity != null
5108 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005109 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5110 Binder.getCallingUid(), "Task to back")) {
5111 return;
5112 }
5113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005115 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116 Binder.restoreCallingIdentity(origId);
5117 }
5118 }
5119
5120 /**
5121 * Moves an activity, and all of the other activities within the same task, to the bottom
5122 * of the history stack. The activity's order within the task is unchanged.
5123 *
5124 * @param token A reference to the activity we wish to move
5125 * @param nonRoot If false then this only works if the activity is the root
5126 * of a task; if true it will work for any activity in a task.
5127 * @return Returns true if the move completed, false if not.
5128 */
5129 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5130 synchronized(this) {
5131 final long origId = Binder.clearCallingIdentity();
5132 int taskId = getTaskForActivityLocked(token, !nonRoot);
5133 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005134 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135 }
5136 Binder.restoreCallingIdentity(origId);
5137 }
5138 return false;
5139 }
5140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005141 public void moveTaskBackwards(int task) {
5142 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5143 "moveTaskBackwards()");
5144
5145 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005146 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5147 Binder.getCallingUid(), "Task backwards")) {
5148 return;
5149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005150 final long origId = Binder.clearCallingIdentity();
5151 moveTaskBackwardsLocked(task);
5152 Binder.restoreCallingIdentity(origId);
5153 }
5154 }
5155
5156 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005157 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005158 }
5159
5160 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5161 synchronized(this) {
5162 return getTaskForActivityLocked(token, onlyRoot);
5163 }
5164 }
5165
5166 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005167 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 TaskRecord lastTask = null;
5169 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005170 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005171 if (r == token) {
5172 if (!onlyRoot || lastTask != r.task) {
5173 return r.task.taskId;
5174 }
5175 return -1;
5176 }
5177 lastTask = r.task;
5178 }
5179
5180 return -1;
5181 }
5182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005183 public void finishOtherInstances(IBinder token, ComponentName className) {
5184 synchronized(this) {
5185 final long origId = Binder.clearCallingIdentity();
5186
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005187 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005188 TaskRecord lastTask = null;
5189 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005190 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 if (r.realActivity.equals(className)
5192 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005193 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 null, "others")) {
5195 i--;
5196 N--;
5197 }
5198 }
5199 lastTask = r.task;
5200 }
5201
5202 Binder.restoreCallingIdentity(origId);
5203 }
5204 }
5205
5206 // =========================================================
5207 // THUMBNAILS
5208 // =========================================================
5209
5210 public void reportThumbnail(IBinder token,
5211 Bitmap thumbnail, CharSequence description) {
5212 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5213 final long origId = Binder.clearCallingIdentity();
5214 sendPendingThumbnail(null, token, thumbnail, description, true);
5215 Binder.restoreCallingIdentity(origId);
5216 }
5217
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005218 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005219 Bitmap thumbnail, CharSequence description, boolean always) {
5220 TaskRecord task = null;
5221 ArrayList receivers = null;
5222
5223 //System.out.println("Send pending thumbnail: " + r);
5224
5225 synchronized(this) {
5226 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005227 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 if (index < 0) {
5229 return;
5230 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005231 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 }
5233 if (thumbnail == null) {
5234 thumbnail = r.thumbnail;
5235 description = r.description;
5236 }
5237 if (thumbnail == null && !always) {
5238 // If there is no thumbnail, and this entry is not actually
5239 // going away, then abort for now and pick up the next
5240 // thumbnail we get.
5241 return;
5242 }
5243 task = r.task;
5244
5245 int N = mPendingThumbnails.size();
5246 int i=0;
5247 while (i<N) {
5248 PendingThumbnailsRecord pr =
5249 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5250 //System.out.println("Looking in " + pr.pendingRecords);
5251 if (pr.pendingRecords.remove(r)) {
5252 if (receivers == null) {
5253 receivers = new ArrayList();
5254 }
5255 receivers.add(pr);
5256 if (pr.pendingRecords.size() == 0) {
5257 pr.finished = true;
5258 mPendingThumbnails.remove(i);
5259 N--;
5260 continue;
5261 }
5262 }
5263 i++;
5264 }
5265 }
5266
5267 if (receivers != null) {
5268 final int N = receivers.size();
5269 for (int i=0; i<N; i++) {
5270 try {
5271 PendingThumbnailsRecord pr =
5272 (PendingThumbnailsRecord)receivers.get(i);
5273 pr.receiver.newThumbnail(
5274 task != null ? task.taskId : -1, thumbnail, description);
5275 if (pr.finished) {
5276 pr.receiver.finished();
5277 }
5278 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005279 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 }
5281 }
5282 }
5283 }
5284
5285 // =========================================================
5286 // CONTENT PROVIDERS
5287 // =========================================================
5288
5289 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5290 List providers = null;
5291 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005292 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005294 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 } catch (RemoteException ex) {
5296 }
5297 if (providers != null) {
5298 final int N = providers.size();
5299 for (int i=0; i<N; i++) {
5300 ProviderInfo cpi =
5301 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005302 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 if (cpr == null) {
5304 cpr = new ContentProviderRecord(cpi, app.info);
5305 mProvidersByClass.put(cpi.name, cpr);
5306 }
5307 app.pubProviders.put(cpi.name, cpr);
5308 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005309 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 }
5311 }
5312 return providers;
5313 }
5314
5315 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005316 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5318 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5319 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5320 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005321 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 return null;
5323 }
5324 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5325 cpi.exported ? -1 : cpi.applicationInfo.uid)
5326 == PackageManager.PERMISSION_GRANTED) {
5327 return null;
5328 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005329
5330 PathPermission[] pps = cpi.pathPermissions;
5331 if (pps != null) {
5332 int i = pps.length;
5333 while (i > 0) {
5334 i--;
5335 PathPermission pp = pps[i];
5336 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5337 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005338 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005339 return null;
5340 }
5341 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5342 cpi.exported ? -1 : cpi.applicationInfo.uid)
5343 == PackageManager.PERMISSION_GRANTED) {
5344 return null;
5345 }
5346 }
5347 }
5348
Dianne Hackbornb424b632010-08-18 15:59:05 -07005349 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5350 if (perms != null) {
5351 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5352 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5353 return null;
5354 }
5355 }
5356 }
5357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 String msg = "Permission Denial: opening provider " + cpi.name
5359 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5360 + ", uid=" + callingUid + ") requires "
5361 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005362 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 return msg;
5364 }
5365
5366 private final ContentProviderHolder getContentProviderImpl(
5367 IApplicationThread caller, String name) {
5368 ContentProviderRecord cpr;
5369 ProviderInfo cpi = null;
5370
5371 synchronized(this) {
5372 ProcessRecord r = null;
5373 if (caller != null) {
5374 r = getRecordForAppLocked(caller);
5375 if (r == null) {
5376 throw new SecurityException(
5377 "Unable to find app for caller " + caller
5378 + " (pid=" + Binder.getCallingPid()
5379 + ") when getting content provider " + name);
5380 }
5381 }
5382
5383 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005384 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 if (cpr != null) {
5386 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005387 String msg;
5388 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5389 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 }
5391
5392 if (r != null && cpr.canRunHere(r)) {
5393 // This provider has been published or is in the process
5394 // of being published... but it is also allowed to run
5395 // in the caller's process, so don't make a connection
5396 // and just let the caller instantiate its own instance.
5397 if (cpr.provider != null) {
5398 // don't give caller the provider object, it needs
5399 // to make its own.
5400 cpr = new ContentProviderRecord(cpr);
5401 }
5402 return cpr;
5403 }
5404
5405 final long origId = Binder.clearCallingIdentity();
5406
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005407 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 // return it right away.
5409 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005410 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005411 "Adding provider requested by "
5412 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005413 + cpr.info.processName);
5414 Integer cnt = r.conProviders.get(cpr);
5415 if (cnt == null) {
5416 r.conProviders.put(cpr, new Integer(1));
5417 } else {
5418 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005421 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5422 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005423 // make sure to count it as being accessed and thus
5424 // back up on the LRU list. This is good because
5425 // content providers are often expensive to start.
5426 updateLruProcessLocked(cpr.app, false, true);
5427 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005428 } else {
5429 cpr.externals++;
5430 }
5431
5432 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005433 updateOomAdjLocked(cpr.app);
5434 }
5435
5436 Binder.restoreCallingIdentity(origId);
5437
5438 } else {
5439 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005440 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005441 resolveContentProvider(name,
5442 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005443 } catch (RemoteException ex) {
5444 }
5445 if (cpi == null) {
5446 return null;
5447 }
5448
Dianne Hackbornb424b632010-08-18 15:59:05 -07005449 String msg;
5450 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5451 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005452 }
5453
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005454 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005455 && !cpi.processName.equals("system")) {
5456 // If this content provider does not run in the system
5457 // process, and the system is not yet ready to run other
5458 // processes, then fail fast instead of hanging.
5459 throw new IllegalArgumentException(
5460 "Attempt to launch content provider before system ready");
5461 }
5462
Dianne Hackborn860755f2010-06-03 18:47:52 -07005463 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005464 final boolean firstClass = cpr == null;
5465 if (firstClass) {
5466 try {
5467 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005468 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 getApplicationInfo(
5470 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005471 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005473 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 + cpi.name);
5475 return null;
5476 }
5477 cpr = new ContentProviderRecord(cpi, ai);
5478 } catch (RemoteException ex) {
5479 // pm is in same process, this will never happen.
5480 }
5481 }
5482
5483 if (r != null && cpr.canRunHere(r)) {
5484 // If this is a multiprocess provider, then just return its
5485 // info and allow the caller to instantiate it. Only do
5486 // this if the provider is the same user as the caller's
5487 // process, or can run as root (so can be in any process).
5488 return cpr;
5489 }
5490
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005491 if (DEBUG_PROVIDER) {
5492 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005493 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005494 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005495 }
5496
5497 // This is single process, and our app is now connecting to it.
5498 // See if we are already in the process of launching this
5499 // provider.
5500 final int N = mLaunchingProviders.size();
5501 int i;
5502 for (i=0; i<N; i++) {
5503 if (mLaunchingProviders.get(i) == cpr) {
5504 break;
5505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005506 }
5507
5508 // If the provider is not already being launched, then get it
5509 // started.
5510 if (i >= N) {
5511 final long origId = Binder.clearCallingIdentity();
5512 ProcessRecord proc = startProcessLocked(cpi.processName,
5513 cpr.appInfo, false, 0, "content provider",
5514 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005515 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005516 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005517 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 + cpi.applicationInfo.packageName + "/"
5519 + cpi.applicationInfo.uid + " for provider "
5520 + name + ": process is bad");
5521 return null;
5522 }
5523 cpr.launchingApp = proc;
5524 mLaunchingProviders.add(cpr);
5525 Binder.restoreCallingIdentity(origId);
5526 }
5527
5528 // Make sure the provider is published (the same provider class
5529 // may be published under multiple names).
5530 if (firstClass) {
5531 mProvidersByClass.put(cpi.name, cpr);
5532 }
5533 mProvidersByName.put(name, cpr);
5534
5535 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005536 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005537 "Adding provider requested by "
5538 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005539 + cpr.info.processName);
5540 Integer cnt = r.conProviders.get(cpr);
5541 if (cnt == null) {
5542 r.conProviders.put(cpr, new Integer(1));
5543 } else {
5544 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005546 cpr.clients.add(r);
5547 } else {
5548 cpr.externals++;
5549 }
5550 }
5551 }
5552
5553 // Wait for the provider to be published...
5554 synchronized (cpr) {
5555 while (cpr.provider == null) {
5556 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005557 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 + cpi.applicationInfo.packageName + "/"
5559 + cpi.applicationInfo.uid + " for provider "
5560 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005561 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005562 cpi.applicationInfo.packageName,
5563 cpi.applicationInfo.uid, name);
5564 return null;
5565 }
5566 try {
5567 cpr.wait();
5568 } catch (InterruptedException ex) {
5569 }
5570 }
5571 }
5572 return cpr;
5573 }
5574
5575 public final ContentProviderHolder getContentProvider(
5576 IApplicationThread caller, String name) {
5577 if (caller == null) {
5578 String msg = "null IApplicationThread when getting content provider "
5579 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005580 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 throw new SecurityException(msg);
5582 }
5583
5584 return getContentProviderImpl(caller, name);
5585 }
5586
5587 private ContentProviderHolder getContentProviderExternal(String name) {
5588 return getContentProviderImpl(null, name);
5589 }
5590
5591 /**
5592 * Drop a content provider from a ProcessRecord's bookkeeping
5593 * @param cpr
5594 */
5595 public void removeContentProvider(IApplicationThread caller, String name) {
5596 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005597 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005598 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005599 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005600 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005601 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005602 return;
5603 }
5604 final ProcessRecord r = getRecordForAppLocked(caller);
5605 if (r == null) {
5606 throw new SecurityException(
5607 "Unable to find app for caller " + caller +
5608 " when removing content provider " + name);
5609 }
5610 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005611 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005612 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005613 + r.info.processName + " from process "
5614 + localCpr.appInfo.processName);
5615 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005617 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005618 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005619 return;
5620 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005621 Integer cnt = r.conProviders.get(localCpr);
5622 if (cnt == null || cnt.intValue() <= 1) {
5623 localCpr.clients.remove(r);
5624 r.conProviders.remove(localCpr);
5625 } else {
5626 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628 }
5629 updateOomAdjLocked();
5630 }
5631 }
5632
5633 private void removeContentProviderExternal(String name) {
5634 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005635 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 if(cpr == null) {
5637 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005638 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005639 return;
5640 }
5641
5642 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005643 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005644 localCpr.externals--;
5645 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005646 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 }
5648 updateOomAdjLocked();
5649 }
5650 }
5651
5652 public final void publishContentProviders(IApplicationThread caller,
5653 List<ContentProviderHolder> providers) {
5654 if (providers == null) {
5655 return;
5656 }
5657
5658 synchronized(this) {
5659 final ProcessRecord r = getRecordForAppLocked(caller);
5660 if (r == null) {
5661 throw new SecurityException(
5662 "Unable to find app for caller " + caller
5663 + " (pid=" + Binder.getCallingPid()
5664 + ") when publishing content providers");
5665 }
5666
5667 final long origId = Binder.clearCallingIdentity();
5668
5669 final int N = providers.size();
5670 for (int i=0; i<N; i++) {
5671 ContentProviderHolder src = providers.get(i);
5672 if (src == null || src.info == null || src.provider == null) {
5673 continue;
5674 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005675 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 if (dst != null) {
5677 mProvidersByClass.put(dst.info.name, dst);
5678 String names[] = dst.info.authority.split(";");
5679 for (int j = 0; j < names.length; j++) {
5680 mProvidersByName.put(names[j], dst);
5681 }
5682
5683 int NL = mLaunchingProviders.size();
5684 int j;
5685 for (j=0; j<NL; j++) {
5686 if (mLaunchingProviders.get(j) == dst) {
5687 mLaunchingProviders.remove(j);
5688 j--;
5689 NL--;
5690 }
5691 }
5692 synchronized (dst) {
5693 dst.provider = src.provider;
5694 dst.app = r;
5695 dst.notifyAll();
5696 }
5697 updateOomAdjLocked(r);
5698 }
5699 }
5700
5701 Binder.restoreCallingIdentity(origId);
5702 }
5703 }
5704
5705 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005706 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005707 synchronized (mSelf) {
5708 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5709 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005710 if (providers != null) {
5711 for (int i=providers.size()-1; i>=0; i--) {
5712 ProviderInfo pi = (ProviderInfo)providers.get(i);
5713 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5714 Slog.w(TAG, "Not installing system proc provider " + pi.name
5715 + ": not system .apk");
5716 providers.remove(i);
5717 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005718 }
5719 }
5720 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005721 if (providers != null) {
5722 mSystemThread.installSystemProviders(providers);
5723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 }
5725
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005726 /**
5727 * Allows app to retrieve the MIME type of a URI without having permission
5728 * to access its content provider.
5729 *
5730 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5731 *
5732 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5733 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5734 */
5735 public String getProviderMimeType(Uri uri) {
5736 final String name = uri.getAuthority();
5737 final long ident = Binder.clearCallingIdentity();
5738 ContentProviderHolder holder = null;
5739
5740 try {
5741 holder = getContentProviderExternal(name);
5742 if (holder != null) {
5743 return holder.provider.getType(uri);
5744 }
5745 } catch (RemoteException e) {
5746 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5747 return null;
5748 } finally {
5749 if (holder != null) {
5750 removeContentProviderExternal(name);
5751 }
5752 Binder.restoreCallingIdentity(ident);
5753 }
5754
5755 return null;
5756 }
5757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 // =========================================================
5759 // GLOBAL MANAGEMENT
5760 // =========================================================
5761
5762 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5763 ApplicationInfo info, String customProcess) {
5764 String proc = customProcess != null ? customProcess : info.processName;
5765 BatteryStatsImpl.Uid.Proc ps = null;
5766 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5767 synchronized (stats) {
5768 ps = stats.getProcessStatsLocked(info.uid, proc);
5769 }
5770 return new ProcessRecord(ps, thread, info, proc);
5771 }
5772
5773 final ProcessRecord addAppLocked(ApplicationInfo info) {
5774 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5775
5776 if (app == null) {
5777 app = newProcessRecordLocked(null, info, null);
5778 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005779 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780 }
5781
5782 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5783 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5784 app.persistent = true;
5785 app.maxAdj = CORE_SERVER_ADJ;
5786 }
5787 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5788 mPersistentStartingProcesses.add(app);
5789 startProcessLocked(app, "added application", app.processName);
5790 }
5791
5792 return app;
5793 }
5794
5795 public void unhandledBack() {
5796 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5797 "unhandledBack()");
5798
5799 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005800 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005801 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802 TAG, "Performing unhandledBack(): stack size = " + count);
5803 if (count > 1) {
5804 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005805 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5807 Binder.restoreCallingIdentity(origId);
5808 }
5809 }
5810 }
5811
5812 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5813 String name = uri.getAuthority();
5814 ContentProviderHolder cph = getContentProviderExternal(name);
5815 ParcelFileDescriptor pfd = null;
5816 if (cph != null) {
5817 // We record the binder invoker's uid in thread-local storage before
5818 // going to the content provider to open the file. Later, in the code
5819 // that handles all permissions checks, we look for this uid and use
5820 // that rather than the Activity Manager's own uid. The effect is that
5821 // we do the check against the caller's permissions even though it looks
5822 // to the content provider like the Activity Manager itself is making
5823 // the request.
5824 sCallerIdentity.set(new Identity(
5825 Binder.getCallingPid(), Binder.getCallingUid()));
5826 try {
5827 pfd = cph.provider.openFile(uri, "r");
5828 } catch (FileNotFoundException e) {
5829 // do nothing; pfd will be returned null
5830 } finally {
5831 // Ensure that whatever happens, we clean up the identity state
5832 sCallerIdentity.remove();
5833 }
5834
5835 // We've got the fd now, so we're done with the provider.
5836 removeContentProviderExternal(name);
5837 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005838 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005839 }
5840 return pfd;
5841 }
5842
5843 public void goingToSleep() {
5844 synchronized(this) {
5845 mSleeping = true;
5846 mWindowManager.setEventDispatching(false);
5847
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005848 if (mMainStack.mResumedActivity != null) {
5849 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005850 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005851 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005853
5854 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005855 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005856 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5857 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005858 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005859 }
5860 }
5861
Dianne Hackborn55280a92009-05-07 15:53:46 -07005862 public boolean shutdown(int timeout) {
5863 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5864 != PackageManager.PERMISSION_GRANTED) {
5865 throw new SecurityException("Requires permission "
5866 + android.Manifest.permission.SHUTDOWN);
5867 }
5868
5869 boolean timedout = false;
5870
5871 synchronized(this) {
5872 mShuttingDown = true;
5873 mWindowManager.setEventDispatching(false);
5874
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005875 if (mMainStack.mResumedActivity != null) {
5876 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005877 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005878 while (mMainStack.mResumedActivity != null
5879 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005880 long delay = endTime - System.currentTimeMillis();
5881 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005882 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005883 timedout = true;
5884 break;
5885 }
5886 try {
5887 this.wait();
5888 } catch (InterruptedException e) {
5889 }
5890 }
5891 }
5892 }
5893
5894 mUsageStatsService.shutdown();
5895 mBatteryStatsService.shutdown();
5896
5897 return timedout;
5898 }
5899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005900 public void wakingUp() {
5901 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005902 if (mMainStack.mGoingToSleep.isHeld()) {
5903 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 }
5905 mWindowManager.setEventDispatching(true);
5906 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005907 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005908 }
5909 }
5910
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005911 public void stopAppSwitches() {
5912 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5913 != PackageManager.PERMISSION_GRANTED) {
5914 throw new SecurityException("Requires permission "
5915 + android.Manifest.permission.STOP_APP_SWITCHES);
5916 }
5917
5918 synchronized(this) {
5919 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5920 + APP_SWITCH_DELAY_TIME;
5921 mDidAppSwitch = false;
5922 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5923 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5924 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5925 }
5926 }
5927
5928 public void resumeAppSwitches() {
5929 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5930 != PackageManager.PERMISSION_GRANTED) {
5931 throw new SecurityException("Requires permission "
5932 + android.Manifest.permission.STOP_APP_SWITCHES);
5933 }
5934
5935 synchronized(this) {
5936 // Note that we don't execute any pending app switches... we will
5937 // let those wait until either the timeout, or the next start
5938 // activity request.
5939 mAppSwitchesAllowedTime = 0;
5940 }
5941 }
5942
5943 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5944 String name) {
5945 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5946 return true;
5947 }
5948
5949 final int perm = checkComponentPermission(
5950 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5951 callingUid, -1);
5952 if (perm == PackageManager.PERMISSION_GRANTED) {
5953 return true;
5954 }
5955
Joe Onorato8a9b2202010-02-26 18:56:32 -08005956 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005957 return false;
5958 }
5959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 public void setDebugApp(String packageName, boolean waitForDebugger,
5961 boolean persistent) {
5962 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5963 "setDebugApp()");
5964
5965 // Note that this is not really thread safe if there are multiple
5966 // callers into it at the same time, but that's not a situation we
5967 // care about.
5968 if (persistent) {
5969 final ContentResolver resolver = mContext.getContentResolver();
5970 Settings.System.putString(
5971 resolver, Settings.System.DEBUG_APP,
5972 packageName);
5973 Settings.System.putInt(
5974 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5975 waitForDebugger ? 1 : 0);
5976 }
5977
5978 synchronized (this) {
5979 if (!persistent) {
5980 mOrigDebugApp = mDebugApp;
5981 mOrigWaitForDebugger = mWaitForDebugger;
5982 }
5983 mDebugApp = packageName;
5984 mWaitForDebugger = waitForDebugger;
5985 mDebugTransient = !persistent;
5986 if (packageName != null) {
5987 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005988 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 Binder.restoreCallingIdentity(origId);
5990 }
5991 }
5992 }
5993
5994 public void setAlwaysFinish(boolean enabled) {
5995 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5996 "setAlwaysFinish()");
5997
5998 Settings.System.putInt(
5999 mContext.getContentResolver(),
6000 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6001
6002 synchronized (this) {
6003 mAlwaysFinishActivities = enabled;
6004 }
6005 }
6006
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006007 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006008 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006009 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006010 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006011 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 }
6013 }
6014
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006015 public boolean isUserAMonkey() {
6016 // For now the fact that there is a controller implies
6017 // we have a monkey.
6018 synchronized (this) {
6019 return mController != null;
6020 }
6021 }
6022
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006023 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006024 synchronized (this) {
6025 mWatchers.register(watcher);
6026 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006027 }
6028
6029 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006030 synchronized (this) {
6031 mWatchers.unregister(watcher);
6032 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006033 }
6034
Daniel Sandler69a48172010-06-23 16:29:36 -04006035 public void setImmersive(IBinder token, boolean immersive) {
6036 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006037 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006038 if (index < 0) {
6039 throw new IllegalArgumentException();
6040 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006041 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006042 r.immersive = immersive;
6043 }
6044 }
6045
6046 public boolean isImmersive(IBinder token) {
6047 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006048 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006049 if (index < 0) {
6050 throw new IllegalArgumentException();
6051 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006052 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006053 return r.immersive;
6054 }
6055 }
6056
6057 public boolean isTopActivityImmersive() {
6058 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006059 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006060 return (r != null) ? r.immersive : false;
6061 }
6062 }
6063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006064 public final void enterSafeMode() {
6065 synchronized(this) {
6066 // It only makes sense to do this before the system is ready
6067 // and started launching other packages.
6068 if (!mSystemReady) {
6069 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006070 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006071 } catch (RemoteException e) {
6072 }
6073
6074 View v = LayoutInflater.from(mContext).inflate(
6075 com.android.internal.R.layout.safe_mode, null);
6076 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Jeff Brown3b2b3542010-10-15 00:54:27 -07006077 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006078 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6079 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6080 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6081 lp.format = v.getBackground().getOpacity();
6082 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6083 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6084 ((WindowManager)mContext.getSystemService(
6085 Context.WINDOW_SERVICE)).addView(v, lp);
6086 }
6087 }
6088 }
6089
6090 public void noteWakeupAlarm(IIntentSender sender) {
6091 if (!(sender instanceof PendingIntentRecord)) {
6092 return;
6093 }
6094 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6095 synchronized (stats) {
6096 if (mBatteryStatsService.isOnBattery()) {
6097 mBatteryStatsService.enforceCallingPermission();
6098 PendingIntentRecord rec = (PendingIntentRecord)sender;
6099 int MY_UID = Binder.getCallingUid();
6100 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6101 BatteryStatsImpl.Uid.Pkg pkg =
6102 stats.getPackageStatsLocked(uid, rec.key.packageName);
6103 pkg.incWakeupsLocked();
6104 }
6105 }
6106 }
6107
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006108 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006109 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006110 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006111 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006112 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006113 // XXX Note: don't acquire main activity lock here, because the window
6114 // manager calls in with its locks held.
6115
6116 boolean killed = false;
6117 synchronized (mPidsSelfLocked) {
6118 int[] types = new int[pids.length];
6119 int worstType = 0;
6120 for (int i=0; i<pids.length; i++) {
6121 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6122 if (proc != null) {
6123 int type = proc.setAdj;
6124 types[i] = type;
6125 if (type > worstType) {
6126 worstType = type;
6127 }
6128 }
6129 }
6130
6131 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6132 // then constrain it so we will kill all hidden procs.
6133 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6134 worstType = HIDDEN_APP_MIN_ADJ;
6135 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006136 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006137 for (int i=0; i<pids.length; i++) {
6138 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6139 if (proc == null) {
6140 continue;
6141 }
6142 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006143 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006144 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006145 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6146 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006147 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006148 proc.killedBackground = true;
6149 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006150 }
6151 }
6152 }
6153 return killed;
6154 }
6155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006156 public final void startRunning(String pkg, String cls, String action,
6157 String data) {
6158 synchronized(this) {
6159 if (mStartRunning) {
6160 return;
6161 }
6162 mStartRunning = true;
6163 mTopComponent = pkg != null && cls != null
6164 ? new ComponentName(pkg, cls) : null;
6165 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6166 mTopData = data;
6167 if (!mSystemReady) {
6168 return;
6169 }
6170 }
6171
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006172 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006173 }
6174
6175 private void retrieveSettings() {
6176 final ContentResolver resolver = mContext.getContentResolver();
6177 String debugApp = Settings.System.getString(
6178 resolver, Settings.System.DEBUG_APP);
6179 boolean waitForDebugger = Settings.System.getInt(
6180 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6181 boolean alwaysFinishActivities = Settings.System.getInt(
6182 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6183
6184 Configuration configuration = new Configuration();
6185 Settings.System.getConfiguration(resolver, configuration);
6186
6187 synchronized (this) {
6188 mDebugApp = mOrigDebugApp = debugApp;
6189 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6190 mAlwaysFinishActivities = alwaysFinishActivities;
6191 // This happens before any activities are started, so we can
6192 // change mConfiguration in-place.
6193 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006194 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006195 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006196 }
6197 }
6198
6199 public boolean testIsSystemReady() {
6200 // no need to synchronize(this) just to read & return the value
6201 return mSystemReady;
6202 }
6203
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006204 private static File getCalledPreBootReceiversFile() {
6205 File dataDir = Environment.getDataDirectory();
6206 File systemDir = new File(dataDir, "system");
6207 File fname = new File(systemDir, "called_pre_boots.dat");
6208 return fname;
6209 }
6210
6211 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6212 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6213 File file = getCalledPreBootReceiversFile();
6214 FileInputStream fis = null;
6215 try {
6216 fis = new FileInputStream(file);
6217 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6218 int vers = dis.readInt();
6219 String codename = dis.readUTF();
6220 if (vers == android.os.Build.VERSION.SDK_INT
6221 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6222 int num = dis.readInt();
6223 while (num > 0) {
6224 num--;
6225 String pkg = dis.readUTF();
6226 String cls = dis.readUTF();
6227 lastDoneReceivers.add(new ComponentName(pkg, cls));
6228 }
6229 }
6230 } catch (FileNotFoundException e) {
6231 } catch (IOException e) {
6232 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6233 } finally {
6234 if (fis != null) {
6235 try {
6236 fis.close();
6237 } catch (IOException e) {
6238 }
6239 }
6240 }
6241 return lastDoneReceivers;
6242 }
6243
6244 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6245 File file = getCalledPreBootReceiversFile();
6246 FileOutputStream fos = null;
6247 DataOutputStream dos = null;
6248 try {
6249 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6250 fos = new FileOutputStream(file);
6251 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6252 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6253 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6254 dos.writeInt(list.size());
6255 for (int i=0; i<list.size(); i++) {
6256 dos.writeUTF(list.get(i).getPackageName());
6257 dos.writeUTF(list.get(i).getClassName());
6258 }
6259 } catch (IOException e) {
6260 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6261 file.delete();
6262 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006263 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006264 if (dos != null) {
6265 try {
6266 dos.close();
6267 } catch (IOException e) {
6268 // TODO Auto-generated catch block
6269 e.printStackTrace();
6270 }
6271 }
6272 }
6273 }
6274
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006275 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006276 // In the simulator, startRunning will never have been called, which
6277 // normally sets a few crucial variables. Do it here instead.
6278 if (!Process.supportsProcesses()) {
6279 mStartRunning = true;
6280 mTopAction = Intent.ACTION_MAIN;
6281 }
6282
6283 synchronized(this) {
6284 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006285 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006286 return;
6287 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006288
6289 // Check to see if there are any update receivers to run.
6290 if (!mDidUpdate) {
6291 if (mWaitingUpdate) {
6292 return;
6293 }
6294 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6295 List<ResolveInfo> ris = null;
6296 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006297 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006298 intent, null, 0);
6299 } catch (RemoteException e) {
6300 }
6301 if (ris != null) {
6302 for (int i=ris.size()-1; i>=0; i--) {
6303 if ((ris.get(i).activityInfo.applicationInfo.flags
6304 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6305 ris.remove(i);
6306 }
6307 }
6308 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006309
6310 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6311
6312 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006313 for (int i=0; i<ris.size(); i++) {
6314 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006315 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6316 if (lastDoneReceivers.contains(comp)) {
6317 ris.remove(i);
6318 i--;
6319 }
6320 }
6321
6322 for (int i=0; i<ris.size(); i++) {
6323 ActivityInfo ai = ris.get(i).activityInfo;
6324 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6325 doneReceivers.add(comp);
6326 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006327 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006328 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006329 finisher = new IIntentReceiver.Stub() {
6330 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006331 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006332 boolean sticky) {
6333 // The raw IIntentReceiver interface is called
6334 // with the AM lock held, so redispatch to
6335 // execute our code without the lock.
6336 mHandler.post(new Runnable() {
6337 public void run() {
6338 synchronized (ActivityManagerService.this) {
6339 mDidUpdate = true;
6340 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006341 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006342 systemReady(goingCallback);
6343 }
6344 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006345 }
6346 };
6347 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006348 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006349 broadcastIntentLocked(null, null, intent, null, finisher,
6350 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006351 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006352 mWaitingUpdate = true;
6353 }
6354 }
6355 }
6356 if (mWaitingUpdate) {
6357 return;
6358 }
6359 mDidUpdate = true;
6360 }
6361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006362 mSystemReady = true;
6363 if (!mStartRunning) {
6364 return;
6365 }
6366 }
6367
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006368 ArrayList<ProcessRecord> procsToKill = null;
6369 synchronized(mPidsSelfLocked) {
6370 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6371 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6372 if (!isAllowedWhileBooting(proc.info)){
6373 if (procsToKill == null) {
6374 procsToKill = new ArrayList<ProcessRecord>();
6375 }
6376 procsToKill.add(proc);
6377 }
6378 }
6379 }
6380
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006381 synchronized(this) {
6382 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006383 for (int i=procsToKill.size()-1; i>=0; i--) {
6384 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006385 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006386 removeProcessLocked(proc, true);
6387 }
6388 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006389
6390 // Now that we have cleaned up any update processes, we
6391 // are ready to start launching real processes and know that
6392 // we won't trample on them any more.
6393 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006394 }
6395
Joe Onorato8a9b2202010-02-26 18:56:32 -08006396 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006397 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006398 SystemClock.uptimeMillis());
6399
6400 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006401 // Make sure we have no pre-ready processes sitting around.
6402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6404 ResolveInfo ri = mContext.getPackageManager()
6405 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006406 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006407 CharSequence errorMsg = null;
6408 if (ri != null) {
6409 ActivityInfo ai = ri.activityInfo;
6410 ApplicationInfo app = ai.applicationInfo;
6411 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6412 mTopAction = Intent.ACTION_FACTORY_TEST;
6413 mTopData = null;
6414 mTopComponent = new ComponentName(app.packageName,
6415 ai.name);
6416 } else {
6417 errorMsg = mContext.getResources().getText(
6418 com.android.internal.R.string.factorytest_not_system);
6419 }
6420 } else {
6421 errorMsg = mContext.getResources().getText(
6422 com.android.internal.R.string.factorytest_no_action);
6423 }
6424 if (errorMsg != null) {
6425 mTopAction = null;
6426 mTopData = null;
6427 mTopComponent = null;
6428 Message msg = Message.obtain();
6429 msg.what = SHOW_FACTORY_ERROR_MSG;
6430 msg.getData().putCharSequence("msg", errorMsg);
6431 mHandler.sendMessage(msg);
6432 }
6433 }
6434 }
6435
6436 retrieveSettings();
6437
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006438 if (goingCallback != null) goingCallback.run();
6439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 synchronized (this) {
6441 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6442 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006443 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006444 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 if (apps != null) {
6446 int N = apps.size();
6447 int i;
6448 for (i=0; i<N; i++) {
6449 ApplicationInfo info
6450 = (ApplicationInfo)apps.get(i);
6451 if (info != null &&
6452 !info.packageName.equals("android")) {
6453 addAppLocked(info);
6454 }
6455 }
6456 }
6457 } catch (RemoteException ex) {
6458 // pm is in same process, this will never happen.
6459 }
6460 }
6461
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006462 // Start up initial activity.
6463 mBooting = true;
6464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006466 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 Message msg = Message.obtain();
6468 msg.what = SHOW_UID_ERROR_MSG;
6469 mHandler.sendMessage(msg);
6470 }
6471 } catch (RemoteException e) {
6472 }
6473
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006474 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006475 }
6476 }
6477
Dan Egnorb7f03672009-12-09 16:22:32 -08006478 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006479 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006481 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006482 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006483 startAppProblemLocked(app);
6484 app.stopFreezingAllLocked();
6485 return handleAppCrashLocked(app);
6486 }
6487
Dan Egnorb7f03672009-12-09 16:22:32 -08006488 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006489 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006491 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006492 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6493 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006494 startAppProblemLocked(app);
6495 app.stopFreezingAllLocked();
6496 }
6497
6498 /**
6499 * Generate a process error record, suitable for attachment to a ProcessRecord.
6500 *
6501 * @param app The ProcessRecord in which the error occurred.
6502 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6503 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006504 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 * @param shortMsg Short message describing the crash.
6506 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006507 * @param stackTrace Full crash stack trace, may be null.
6508 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006509 * @return Returns a fully-formed AppErrorStateInfo record.
6510 */
6511 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006512 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006513 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 report.condition = condition;
6516 report.processName = app.processName;
6517 report.pid = app.pid;
6518 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006519 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006520 report.shortMsg = shortMsg;
6521 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006522 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523
6524 return report;
6525 }
6526
Dan Egnor42471dd2010-01-07 17:25:22 -08006527 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006528 synchronized (this) {
6529 app.crashing = false;
6530 app.crashingReport = null;
6531 app.notResponding = false;
6532 app.notRespondingReport = null;
6533 if (app.anrDialog == fromDialog) {
6534 app.anrDialog = null;
6535 }
6536 if (app.waitDialog == fromDialog) {
6537 app.waitDialog = null;
6538 }
6539 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006540 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006541 Slog.i(ActivityManagerService.TAG, "Killing "
6542 + app.processName + " (pid=" + app.pid + "): user's request");
6543 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6544 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006545 Process.killProcess(app.pid);
6546 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006547 }
6548 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006549
Dan Egnorb7f03672009-12-09 16:22:32 -08006550 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006551 long now = SystemClock.uptimeMillis();
6552
6553 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6554 app.info.uid);
6555 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6556 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006557 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006559 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006560 app.info.processName, app.info.uid);
6561 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006562 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6563 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006565 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006567 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 }
6569 }
6570 if (!app.persistent) {
6571 // We don't want to start this process again until the user
6572 // explicitly does so... but for persistent process, we really
6573 // need to keep it running. If a persistent process is actually
6574 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006575 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006576 app.info.processName);
6577 mBadProcesses.put(app.info.processName, app.info.uid, now);
6578 app.bad = true;
6579 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6580 app.removed = true;
6581 removeProcessLocked(app, false);
6582 return false;
6583 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006584 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006585 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006586 if (r.app == app) {
6587 // If the top running activity is from this crashing
6588 // process, then terminate it to avoid getting in a loop.
6589 Slog.w(TAG, " Force finishing activity "
6590 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006591 int index = mMainStack.indexOfTokenLocked(r);
6592 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006593 Activity.RESULT_CANCELED, null, "crashed");
6594 // Also terminate an activities below it that aren't yet
6595 // stopped, to avoid a situation where one will get
6596 // re-start our crashing activity once it gets resumed again.
6597 index--;
6598 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006599 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006600 if (r.state == ActivityState.RESUMED
6601 || r.state == ActivityState.PAUSING
6602 || r.state == ActivityState.PAUSED) {
6603 if (!r.isHomeActivity) {
6604 Slog.w(TAG, " Force finishing activity "
6605 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006606 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006607 Activity.RESULT_CANCELED, null, "crashed");
6608 }
6609 }
6610 }
6611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006612 }
6613
6614 // Bump up the crash count of any services currently running in the proc.
6615 if (app.services.size() != 0) {
6616 // Any services running in the application need to be placed
6617 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006618 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006620 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006621 sr.crashCount++;
6622 }
6623 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006624
6625 // If the crashing process is what we consider to be the "home process" and it has been
6626 // replaced by a third-party app, clear the package preferred activities from packages
6627 // with a home activity running in the process to prevent a repeatedly crashing app
6628 // from blocking the user to manually clear the list.
6629 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6630 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6631 Iterator it = mHomeProcess.activities.iterator();
6632 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006633 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006634 if (r.isHomeActivity) {
6635 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6636 try {
6637 ActivityThread.getPackageManager()
6638 .clearPackagePreferredActivities(r.packageName);
6639 } catch (RemoteException c) {
6640 // pm is in same process, this will never happen.
6641 }
6642 }
6643 }
6644 }
6645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006646 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6647 return true;
6648 }
6649
6650 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006651 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6652 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006653 skipCurrentReceiverLocked(app);
6654 }
6655
6656 void skipCurrentReceiverLocked(ProcessRecord app) {
6657 boolean reschedule = false;
6658 BroadcastRecord r = app.curReceiver;
6659 if (r != null) {
6660 // The current broadcast is waiting for this app's receiver
6661 // to be finished. Looks like that's not going to happen, so
6662 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006663 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006664 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6665 r.resultExtras, r.resultAbort, true);
6666 reschedule = true;
6667 }
6668 r = mPendingBroadcast;
6669 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006670 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006671 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006672 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006673 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6674 r.resultExtras, r.resultAbort, true);
6675 reschedule = true;
6676 }
6677 if (reschedule) {
6678 scheduleBroadcastsLocked();
6679 }
6680 }
6681
Dan Egnor60d87622009-12-16 16:32:58 -08006682 /**
6683 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6684 * The application process will exit immediately after this call returns.
6685 * @param app object of the crashing app, null for the system server
6686 * @param crashInfo describing the exception
6687 */
6688 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6689 ProcessRecord r = findAppProcess(app);
6690
6691 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6692 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006693 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006694 crashInfo.exceptionClassName,
6695 crashInfo.exceptionMessage,
6696 crashInfo.throwFileName,
6697 crashInfo.throwLineNumber);
6698
Dan Egnor42471dd2010-01-07 17:25:22 -08006699 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006700
6701 crashApplication(r, crashInfo);
6702 }
6703
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006704 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006705 IBinder app,
6706 int violationMask,
6707 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006708 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006709
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006710 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006711 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006712 boolean logIt = true;
6713 synchronized (mAlreadyLoggedViolatedStacks) {
6714 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6715 logIt = false;
6716 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006717 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006718 // the relative pain numbers, without logging all
6719 // the stack traces repeatedly. We'd want to do
6720 // likewise in the client code, which also does
6721 // dup suppression, before the Binder call.
6722 } else {
6723 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6724 mAlreadyLoggedViolatedStacks.clear();
6725 }
6726 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6727 }
6728 }
6729 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006730 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006731 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006732 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006733
6734 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6735 AppErrorResult result = new AppErrorResult();
6736 synchronized (this) {
6737 final long origId = Binder.clearCallingIdentity();
6738
6739 Message msg = Message.obtain();
6740 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6741 HashMap<String, Object> data = new HashMap<String, Object>();
6742 data.put("result", result);
6743 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006744 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006745 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006746 msg.obj = data;
6747 mHandler.sendMessage(msg);
6748
6749 Binder.restoreCallingIdentity(origId);
6750 }
6751 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006752 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006753 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006754 }
6755
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006756 // Depending on the policy in effect, there could be a bunch of
6757 // these in quick succession so we try to batch these together to
6758 // minimize disk writes, number of dropbox entries, and maximize
6759 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006760 private void logStrictModeViolationToDropBox(
6761 ProcessRecord process,
6762 StrictMode.ViolationInfo info) {
6763 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006764 return;
6765 }
6766 final boolean isSystemApp = process == null ||
6767 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6768 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6769 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6770 final DropBoxManager dbox = (DropBoxManager)
6771 mContext.getSystemService(Context.DROPBOX_SERVICE);
6772
6773 // Exit early if the dropbox isn't configured to accept this report type.
6774 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6775
6776 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006777 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006778 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6779 synchronized (sb) {
6780 bufferWasEmpty = sb.length() == 0;
6781 appendDropBoxProcessHeaders(process, sb);
6782 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6783 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006784 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6785 if (info.violationNumThisLoop != 0) {
6786 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6787 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006788 if (info.numAnimationsRunning != 0) {
6789 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6790 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006791 if (info.broadcastIntentAction != null) {
6792 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6793 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006794 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006795 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006796 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006797 if (info.tags != null) {
6798 for (String tag : info.tags) {
6799 sb.append("Span-Tag: ").append(tag).append("\n");
6800 }
6801 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006802 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006803 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6804 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006805 }
6806 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006807
6808 // Only buffer up to ~64k. Various logging bits truncate
6809 // things at 128k.
6810 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006811 }
6812
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006813 // Flush immediately if the buffer's grown too large, or this
6814 // is a non-system app. Non-system apps are isolated with a
6815 // different tag & policy and not batched.
6816 //
6817 // Batching is useful during internal testing with
6818 // StrictMode settings turned up high. Without batching,
6819 // thousands of separate files could be created on boot.
6820 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006821 new Thread("Error dump: " + dropboxTag) {
6822 @Override
6823 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006824 String report;
6825 synchronized (sb) {
6826 report = sb.toString();
6827 sb.delete(0, sb.length());
6828 sb.trimToSize();
6829 }
6830 if (report.length() != 0) {
6831 dbox.addText(dropboxTag, report);
6832 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006833 }
6834 }.start();
6835 return;
6836 }
6837
6838 // System app batching:
6839 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006840 // An existing dropbox-writing thread is outstanding, so
6841 // we don't need to start it up. The existing thread will
6842 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006843 return;
6844 }
6845
6846 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6847 // (After this point, we shouldn't access AMS internal data structures.)
6848 new Thread("Error dump: " + dropboxTag) {
6849 @Override
6850 public void run() {
6851 // 5 second sleep to let stacks arrive and be batched together
6852 try {
6853 Thread.sleep(5000); // 5 seconds
6854 } catch (InterruptedException e) {}
6855
6856 String errorReport;
6857 synchronized (mStrictModeBuffer) {
6858 errorReport = mStrictModeBuffer.toString();
6859 if (errorReport.length() == 0) {
6860 return;
6861 }
6862 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6863 mStrictModeBuffer.trimToSize();
6864 }
6865 dbox.addText(dropboxTag, errorReport);
6866 }
6867 }.start();
6868 }
6869
Dan Egnor60d87622009-12-16 16:32:58 -08006870 /**
6871 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6872 * @param app object of the crashing app, null for the system server
6873 * @param tag reported by the caller
6874 * @param crashInfo describing the context of the error
6875 * @return true if the process should exit immediately (WTF is fatal)
6876 */
6877 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006878 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006879 ProcessRecord r = findAppProcess(app);
6880
6881 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6882 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006883 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006884 tag, crashInfo.exceptionMessage);
6885
Dan Egnor42471dd2010-01-07 17:25:22 -08006886 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006887
Doug Zongker43866e02010-01-07 12:09:54 -08006888 if (Settings.Secure.getInt(mContext.getContentResolver(),
6889 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006890 crashApplication(r, crashInfo);
6891 return true;
6892 } else {
6893 return false;
6894 }
6895 }
6896
6897 /**
6898 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6899 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6900 */
6901 private ProcessRecord findAppProcess(IBinder app) {
6902 if (app == null) {
6903 return null;
6904 }
6905
6906 synchronized (this) {
6907 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6908 final int NA = apps.size();
6909 for (int ia=0; ia<NA; ia++) {
6910 ProcessRecord p = apps.valueAt(ia);
6911 if (p.thread != null && p.thread.asBinder() == app) {
6912 return p;
6913 }
6914 }
6915 }
6916
Joe Onorato8a9b2202010-02-26 18:56:32 -08006917 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006918 return null;
6919 }
6920 }
6921
6922 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006923 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6924 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006925 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006926 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6927 // Note: ProcessRecord 'process' is guarded by the service
6928 // instance. (notably process.pkgList, which could otherwise change
6929 // concurrently during execution of this method)
6930 synchronized (this) {
6931 if (process == null || process.pid == MY_PID) {
6932 sb.append("Process: system_server\n");
6933 } else {
6934 sb.append("Process: ").append(process.processName).append("\n");
6935 }
6936 if (process == null) {
6937 return;
6938 }
Dan Egnora455d192010-03-12 08:52:28 -08006939 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006940 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006941 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6942 for (String pkg : process.pkgList) {
6943 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006944 try {
Dan Egnora455d192010-03-12 08:52:28 -08006945 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6946 if (pi != null) {
6947 sb.append(" v").append(pi.versionCode);
6948 if (pi.versionName != null) {
6949 sb.append(" (").append(pi.versionName).append(")");
6950 }
6951 }
6952 } catch (RemoteException e) {
6953 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006954 }
Dan Egnora455d192010-03-12 08:52:28 -08006955 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006956 }
Dan Egnora455d192010-03-12 08:52:28 -08006957 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006958 }
6959
6960 private static String processClass(ProcessRecord process) {
6961 if (process == null || process.pid == MY_PID) {
6962 return "system_server";
6963 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6964 return "system_app";
6965 } else {
6966 return "data_app";
6967 }
6968 }
6969
6970 /**
6971 * Write a description of an error (crash, WTF, ANR) to the drop box.
6972 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6973 * @param process which caused the error, null means the system server
6974 * @param activity which triggered the error, null if unknown
6975 * @param parent activity related to the error, null if unknown
6976 * @param subject line related to the error, null if absent
6977 * @param report in long form describing the error, null if absent
6978 * @param logFile to include in the report, null if none
6979 * @param crashInfo giving an application stack trace, null if absent
6980 */
6981 public void addErrorToDropBox(String eventType,
6982 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6983 final String report, final File logFile,
6984 final ApplicationErrorReport.CrashInfo crashInfo) {
6985 // NOTE -- this must never acquire the ActivityManagerService lock,
6986 // otherwise the watchdog may be prevented from resetting the system.
6987
6988 final String dropboxTag = processClass(process) + "_" + eventType;
6989 final DropBoxManager dbox = (DropBoxManager)
6990 mContext.getSystemService(Context.DROPBOX_SERVICE);
6991
6992 // Exit early if the dropbox isn't configured to accept this report type.
6993 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6994
6995 final StringBuilder sb = new StringBuilder(1024);
6996 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006997 if (activity != null) {
6998 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6999 }
7000 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7001 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7002 }
7003 if (parent != null && parent != activity) {
7004 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7005 }
7006 if (subject != null) {
7007 sb.append("Subject: ").append(subject).append("\n");
7008 }
7009 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007010 if (Debug.isDebuggerConnected()) {
7011 sb.append("Debugger: Connected\n");
7012 }
Dan Egnora455d192010-03-12 08:52:28 -08007013 sb.append("\n");
7014
7015 // Do the rest in a worker thread to avoid blocking the caller on I/O
7016 // (After this point, we shouldn't access AMS internal data structures.)
7017 Thread worker = new Thread("Error dump: " + dropboxTag) {
7018 @Override
7019 public void run() {
7020 if (report != null) {
7021 sb.append(report);
7022 }
7023 if (logFile != null) {
7024 try {
7025 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7026 } catch (IOException e) {
7027 Slog.e(TAG, "Error reading " + logFile, e);
7028 }
7029 }
7030 if (crashInfo != null && crashInfo.stackTrace != null) {
7031 sb.append(crashInfo.stackTrace);
7032 }
7033
7034 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7035 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7036 if (lines > 0) {
7037 sb.append("\n");
7038
7039 // Merge several logcat streams, and take the last N lines
7040 InputStreamReader input = null;
7041 try {
7042 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7043 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7044 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7045
7046 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7047 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7048 input = new InputStreamReader(logcat.getInputStream());
7049
7050 int num;
7051 char[] buf = new char[8192];
7052 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7053 } catch (IOException e) {
7054 Slog.e(TAG, "Error running logcat", e);
7055 } finally {
7056 if (input != null) try { input.close(); } catch (IOException e) {}
7057 }
7058 }
7059
7060 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007061 }
Dan Egnora455d192010-03-12 08:52:28 -08007062 };
7063
7064 if (process == null || process.pid == MY_PID) {
7065 worker.run(); // We may be about to die -- need to run this synchronously
7066 } else {
7067 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007068 }
7069 }
7070
7071 /**
7072 * Bring up the "unexpected error" dialog box for a crashing app.
7073 * Deal with edge cases (intercepts from instrumented applications,
7074 * ActivityController, error intent receivers, that sort of thing).
7075 * @param r the application crashing
7076 * @param crashInfo describing the failure
7077 */
7078 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007079 long timeMillis = System.currentTimeMillis();
7080 String shortMsg = crashInfo.exceptionClassName;
7081 String longMsg = crashInfo.exceptionMessage;
7082 String stackTrace = crashInfo.stackTrace;
7083 if (shortMsg != null && longMsg != null) {
7084 longMsg = shortMsg + ": " + longMsg;
7085 } else if (shortMsg != null) {
7086 longMsg = shortMsg;
7087 }
7088
Dan Egnor60d87622009-12-16 16:32:58 -08007089 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007090 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007091 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 try {
7093 String name = r != null ? r.processName : null;
7094 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007095 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007096 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007097 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007098 + " at watcher's request");
7099 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007100 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007101 }
7102 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007103 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007104 }
7105 }
7106
7107 final long origId = Binder.clearCallingIdentity();
7108
7109 // If this process is running instrumentation, finish it.
7110 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007111 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007112 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007113 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7114 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007115 Bundle info = new Bundle();
7116 info.putString("shortMsg", shortMsg);
7117 info.putString("longMsg", longMsg);
7118 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7119 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007120 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007121 }
7122
Dan Egnor60d87622009-12-16 16:32:58 -08007123 // If we can't identify the process or it's already exceeded its crash quota,
7124 // quit right away without showing a crash dialog.
7125 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007126 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007127 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007128 }
7129
7130 Message msg = Message.obtain();
7131 msg.what = SHOW_ERROR_MSG;
7132 HashMap data = new HashMap();
7133 data.put("result", result);
7134 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007135 msg.obj = data;
7136 mHandler.sendMessage(msg);
7137
7138 Binder.restoreCallingIdentity(origId);
7139 }
7140
7141 int res = result.get();
7142
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007143 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007144 synchronized (this) {
7145 if (r != null) {
7146 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7147 SystemClock.uptimeMillis());
7148 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007149 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007150 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007151 }
7152 }
7153
7154 if (appErrorIntent != null) {
7155 try {
7156 mContext.startActivity(appErrorIntent);
7157 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007158 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007162
7163 Intent createAppErrorIntentLocked(ProcessRecord r,
7164 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7165 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007166 if (report == null) {
7167 return null;
7168 }
7169 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7170 result.setComponent(r.errorReportReceiver);
7171 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7172 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7173 return result;
7174 }
7175
Dan Egnorb7f03672009-12-09 16:22:32 -08007176 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7177 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007178 if (r.errorReportReceiver == null) {
7179 return null;
7180 }
7181
7182 if (!r.crashing && !r.notResponding) {
7183 return null;
7184 }
7185
Dan Egnorb7f03672009-12-09 16:22:32 -08007186 ApplicationErrorReport report = new ApplicationErrorReport();
7187 report.packageName = r.info.packageName;
7188 report.installerPackageName = r.errorReportReceiver.getPackageName();
7189 report.processName = r.processName;
7190 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007191 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007192
Dan Egnorb7f03672009-12-09 16:22:32 -08007193 if (r.crashing) {
7194 report.type = ApplicationErrorReport.TYPE_CRASH;
7195 report.crashInfo = crashInfo;
7196 } else if (r.notResponding) {
7197 report.type = ApplicationErrorReport.TYPE_ANR;
7198 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007199
Dan Egnorb7f03672009-12-09 16:22:32 -08007200 report.anrInfo.activity = r.notRespondingReport.tag;
7201 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7202 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007203 }
7204
Dan Egnorb7f03672009-12-09 16:22:32 -08007205 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007206 }
7207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007208 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7209 // assume our apps are happy - lazy create the list
7210 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7211
7212 synchronized (this) {
7213
7214 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007215 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7216 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7218 // This one's in trouble, so we'll generate a report for it
7219 // crashes are higher priority (in case there's a crash *and* an anr)
7220 ActivityManager.ProcessErrorStateInfo report = null;
7221 if (app.crashing) {
7222 report = app.crashingReport;
7223 } else if (app.notResponding) {
7224 report = app.notRespondingReport;
7225 }
7226
7227 if (report != null) {
7228 if (errList == null) {
7229 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7230 }
7231 errList.add(report);
7232 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007233 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007234 " crashing = " + app.crashing +
7235 " notResponding = " + app.notResponding);
7236 }
7237 }
7238 }
7239 }
7240
7241 return errList;
7242 }
7243
7244 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7245 // Lazy instantiation of list
7246 List<ActivityManager.RunningAppProcessInfo> runList = null;
7247 synchronized (this) {
7248 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007249 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7250 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7252 // Generate process state info for running application
7253 ActivityManager.RunningAppProcessInfo currApp =
7254 new ActivityManager.RunningAppProcessInfo(app.processName,
7255 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007256 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007257 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007258 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007259 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007260 if (app.persistent) {
7261 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007263 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007264 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007265 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7266 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7267 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007268 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7269 } else if (adj >= HOME_APP_ADJ) {
7270 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7271 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 } else if (adj >= SECONDARY_SERVER_ADJ) {
7273 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007274 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007275 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007276 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7277 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007278 } else if (adj >= VISIBLE_APP_ADJ) {
7279 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7280 } else {
7281 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7282 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007283 currApp.importanceReasonCode = app.adjTypeCode;
7284 if (app.adjSource instanceof ProcessRecord) {
7285 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007286 } else if (app.adjSource instanceof ActivityRecord) {
7287 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007288 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7289 }
7290 if (app.adjTarget instanceof ComponentName) {
7291 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7292 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007293 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007294 // + " lru=" + currApp.lru);
7295 if (runList == null) {
7296 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7297 }
7298 runList.add(currApp);
7299 }
7300 }
7301 }
7302 return runList;
7303 }
7304
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007305 public List<ApplicationInfo> getRunningExternalApplications() {
7306 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7307 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7308 if (runningApps != null && runningApps.size() > 0) {
7309 Set<String> extList = new HashSet<String>();
7310 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7311 if (app.pkgList != null) {
7312 for (String pkg : app.pkgList) {
7313 extList.add(pkg);
7314 }
7315 }
7316 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007317 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007318 for (String pkg : extList) {
7319 try {
7320 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7321 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7322 retList.add(info);
7323 }
7324 } catch (RemoteException e) {
7325 }
7326 }
7327 }
7328 return retList;
7329 }
7330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007331 @Override
7332 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007333 if (checkCallingPermission(android.Manifest.permission.DUMP)
7334 != PackageManager.PERMISSION_GRANTED) {
7335 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7336 + Binder.getCallingPid()
7337 + ", uid=" + Binder.getCallingUid()
7338 + " without permission "
7339 + android.Manifest.permission.DUMP);
7340 return;
7341 }
7342
7343 boolean dumpAll = false;
7344
7345 int opti = 0;
7346 while (opti < args.length) {
7347 String opt = args[opti];
7348 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7349 break;
7350 }
7351 opti++;
7352 if ("-a".equals(opt)) {
7353 dumpAll = true;
7354 } else if ("-h".equals(opt)) {
7355 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007356 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007357 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007358 pw.println(" a[ctivities]: activity stack state");
7359 pw.println(" b[roadcasts]: broadcast state");
7360 pw.println(" i[ntents]: pending intent state");
7361 pw.println(" p[rocesses]: process state");
7362 pw.println(" o[om]: out of memory management");
7363 pw.println(" prov[iders]: content provider state");
7364 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007365 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007366 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7367 pw.println(" a partial substring in a component name, or an");
7368 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007370 } else {
7371 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007373 }
7374
7375 // Is the caller requesting to dump a particular piece of data?
7376 if (opti < args.length) {
7377 String cmd = args[opti];
7378 opti++;
7379 if ("activities".equals(cmd) || "a".equals(cmd)) {
7380 synchronized (this) {
7381 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007383 return;
7384 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7385 synchronized (this) {
7386 dumpBroadcastsLocked(fd, pw, args, opti, true);
7387 }
7388 return;
7389 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7390 synchronized (this) {
7391 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7392 }
7393 return;
7394 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7395 synchronized (this) {
7396 dumpProcessesLocked(fd, pw, args, opti, true);
7397 }
7398 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007399 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7400 synchronized (this) {
7401 dumpOomLocked(fd, pw, args, opti, true);
7402 }
7403 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007404 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7405 synchronized (this) {
7406 dumpProvidersLocked(fd, pw, args, opti, true);
7407 }
7408 return;
7409 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007410 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007411 return;
7412 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7413 synchronized (this) {
7414 dumpServicesLocked(fd, pw, args, opti, true);
7415 }
7416 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007417 } else {
7418 // Dumping a single activity?
7419 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7420 return;
7421 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007422 pw.println("Bad activity command, or no activities match: " + cmd);
7423 pw.println("Use -h for help.");
7424 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007425 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007426 }
7427
7428 // No piece of data specified, dump everything.
7429 synchronized (this) {
7430 boolean needSep;
7431 if (dumpAll) {
7432 pw.println("Providers in Current Activity Manager State:");
7433 }
7434 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7435 if (needSep) {
7436 pw.println(" ");
7437 }
7438 if (dumpAll) {
7439 pw.println("-------------------------------------------------------------------------------");
7440 pw.println("Broadcasts in Current Activity Manager State:");
7441 }
7442 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7443 if (needSep) {
7444 pw.println(" ");
7445 }
7446 if (dumpAll) {
7447 pw.println("-------------------------------------------------------------------------------");
7448 pw.println("Services in Current Activity Manager State:");
7449 }
7450 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7451 if (needSep) {
7452 pw.println(" ");
7453 }
7454 if (dumpAll) {
7455 pw.println("-------------------------------------------------------------------------------");
7456 pw.println("PendingIntents in Current Activity Manager State:");
7457 }
7458 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7459 if (needSep) {
7460 pw.println(" ");
7461 }
7462 if (dumpAll) {
7463 pw.println("-------------------------------------------------------------------------------");
7464 pw.println("Activities in Current Activity Manager State:");
7465 }
7466 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7467 if (needSep) {
7468 pw.println(" ");
7469 }
7470 if (dumpAll) {
7471 pw.println("-------------------------------------------------------------------------------");
7472 pw.println("Processes in Current Activity Manager State:");
7473 }
7474 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7475 }
7476 }
7477
7478 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7479 int opti, boolean dumpAll, boolean needHeader) {
7480 if (needHeader) {
7481 pw.println(" Activity stack:");
7482 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007483 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007484 pw.println(" ");
7485 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007486 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7487 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007488 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007489 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007490 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007491 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007492 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007493 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007494 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007495 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007496 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007497 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007498 pw.println(" ");
7499 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007500 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007503 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007504 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7505 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007506 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007507 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007508
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007509 if (dumpAll && mRecentTasks.size() > 0) {
7510 pw.println(" ");
7511 pw.println("Recent tasks in Current Activity Manager State:");
7512
7513 final int N = mRecentTasks.size();
7514 for (int i=0; i<N; i++) {
7515 TaskRecord tr = mRecentTasks.get(i);
7516 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7517 pw.println(tr);
7518 mRecentTasks.get(i).dump(pw, " ");
7519 }
7520 }
7521
7522 pw.println(" ");
7523 pw.println(" mCurTask: " + mCurTask);
7524
7525 return true;
7526 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007527
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007528 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7529 int opti, boolean dumpAll) {
7530 boolean needSep = false;
7531 int numPers = 0;
7532
7533 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7535 final int NA = procs.size();
7536 for (int ia=0; ia<NA; ia++) {
7537 if (!needSep) {
7538 pw.println(" All known processes:");
7539 needSep = true;
7540 }
7541 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007542 pw.print(r.persistent ? " *PERS*" : " *APP*");
7543 pw.print(" UID "); pw.print(procs.keyAt(ia));
7544 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 r.dump(pw, " ");
7546 if (r.persistent) {
7547 numPers++;
7548 }
7549 }
7550 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007551 }
7552
7553 if (mLruProcesses.size() > 0) {
7554 if (needSep) pw.println(" ");
7555 needSep = true;
7556 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007557 dumpProcessOomList(pw, this, mLruProcesses, " ",
7558 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007559 needSep = true;
7560 }
7561
7562 synchronized (mPidsSelfLocked) {
7563 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007564 if (needSep) pw.println(" ");
7565 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007566 pw.println(" PID mappings:");
7567 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7568 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7569 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 }
7571 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007572 }
7573
7574 if (mForegroundProcesses.size() > 0) {
7575 if (needSep) pw.println(" ");
7576 needSep = true;
7577 pw.println(" Foreground Processes:");
7578 for (int i=0; i<mForegroundProcesses.size(); i++) {
7579 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7580 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007582 }
7583
7584 if (mPersistentStartingProcesses.size() > 0) {
7585 if (needSep) pw.println(" ");
7586 needSep = true;
7587 pw.println(" Persisent processes that are starting:");
7588 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007589 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007592 if (mStartingProcesses.size() > 0) {
7593 if (needSep) pw.println(" ");
7594 needSep = true;
7595 pw.println(" Processes that are starting:");
7596 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007597 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007600 if (mRemovedProcesses.size() > 0) {
7601 if (needSep) pw.println(" ");
7602 needSep = true;
7603 pw.println(" Processes that are being removed:");
7604 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007605 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007606 }
7607
7608 if (mProcessesOnHold.size() > 0) {
7609 if (needSep) pw.println(" ");
7610 needSep = true;
7611 pw.println(" Processes that are on old until the system is ready:");
7612 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007613 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615
Dianne Hackborn287952c2010-09-22 22:34:31 -07007616 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007617
7618 if (mProcessCrashTimes.getMap().size() > 0) {
7619 if (needSep) pw.println(" ");
7620 needSep = true;
7621 pw.println(" Time since processes crashed:");
7622 long now = SystemClock.uptimeMillis();
7623 for (Map.Entry<String, SparseArray<Long>> procs
7624 : mProcessCrashTimes.getMap().entrySet()) {
7625 SparseArray<Long> uids = procs.getValue();
7626 final int N = uids.size();
7627 for (int i=0; i<N; i++) {
7628 pw.print(" Process "); pw.print(procs.getKey());
7629 pw.print(" uid "); pw.print(uids.keyAt(i));
7630 pw.print(": last crashed ");
7631 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007632 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007633 }
7634 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007637 if (mBadProcesses.getMap().size() > 0) {
7638 if (needSep) pw.println(" ");
7639 needSep = true;
7640 pw.println(" Bad processes:");
7641 for (Map.Entry<String, SparseArray<Long>> procs
7642 : mBadProcesses.getMap().entrySet()) {
7643 SparseArray<Long> uids = procs.getValue();
7644 final int N = uids.size();
7645 for (int i=0; i<N; i++) {
7646 pw.print(" Bad process "); pw.print(procs.getKey());
7647 pw.print(" uid "); pw.print(uids.keyAt(i));
7648 pw.print(": crashed at time ");
7649 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 }
7651 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007654 pw.println(" ");
7655 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007656 if (mHeavyWeightProcess != null) {
7657 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7658 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007659 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007660 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007661 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7662 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7663 || mOrigWaitForDebugger) {
7664 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7665 + " mDebugTransient=" + mDebugTransient
7666 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7667 }
7668 if (mAlwaysFinishActivities || mController != null) {
7669 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7670 + " mController=" + mController);
7671 }
7672 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007674 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007675 + " mProcessesReady=" + mProcessesReady
7676 + " mSystemReady=" + mSystemReady);
7677 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 + " mBooted=" + mBooted
7679 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007680 pw.print(" mLastPowerCheckRealtime=");
7681 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7682 pw.println("");
7683 pw.print(" mLastPowerCheckUptime=");
7684 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7685 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007686 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7687 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007688 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007690
7691 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692 }
7693
Dianne Hackborn287952c2010-09-22 22:34:31 -07007694 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7695 int opti, boolean needSep, boolean dumpAll) {
7696 if (mProcessesToGc.size() > 0) {
7697 if (needSep) pw.println(" ");
7698 needSep = true;
7699 pw.println(" Processes that are waiting to GC:");
7700 long now = SystemClock.uptimeMillis();
7701 for (int i=0; i<mProcessesToGc.size(); i++) {
7702 ProcessRecord proc = mProcessesToGc.get(i);
7703 pw.print(" Process "); pw.println(proc);
7704 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7705 pw.print(", last gced=");
7706 pw.print(now-proc.lastRequestedGc);
7707 pw.print(" ms ago, last lowMem=");
7708 pw.print(now-proc.lastLowMemory);
7709 pw.println(" ms ago");
7710
7711 }
7712 }
7713 return needSep;
7714 }
7715
7716 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7717 int opti, boolean dumpAll) {
7718 boolean needSep = false;
7719
7720 if (mLruProcesses.size() > 0) {
7721 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7722
7723 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7724 @Override
7725 public int compare(ProcessRecord object1, ProcessRecord object2) {
7726 if (object1.setAdj != object2.setAdj) {
7727 return object1.setAdj > object2.setAdj ? -1 : 1;
7728 }
7729 if (object1.setSchedGroup != object2.setSchedGroup) {
7730 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7731 }
7732 if (object1.keeping != object2.keeping) {
7733 return object1.keeping ? -1 : 1;
7734 }
7735 if (object1.pid != object2.pid) {
7736 return object1.pid > object2.pid ? -1 : 1;
7737 }
7738 return 0;
7739 }
7740 };
7741
7742 Collections.sort(procs, comparator);
7743
7744 if (needSep) pw.println(" ");
7745 needSep = true;
7746 pw.println(" Process OOM control:");
7747 dumpProcessOomList(pw, this, procs, " ",
7748 "Proc", "PERS", true);
7749 needSep = true;
7750 }
7751
7752 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7753
7754 pw.println(" ");
7755 pw.println(" mHomeProcess: " + mHomeProcess);
7756 if (mHeavyWeightProcess != null) {
7757 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7758 }
7759
7760 return true;
7761 }
7762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007763 /**
7764 * There are three ways to call this:
7765 * - no service specified: dump all the services
7766 * - a flattened component name that matched an existing service was specified as the
7767 * first arg: dump that one service
7768 * - the first arg isn't the flattened component name of an existing service:
7769 * dump all services whose component contains the first arg as a substring
7770 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007771 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007772 String[] newArgs;
7773 String componentNameString;
7774 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007775 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007776 componentNameString = null;
7777 newArgs = EMPTY_STRING_ARRAY;
7778 r = null;
7779 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007780 componentNameString = args[opti];
7781 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007783 synchronized (this) {
7784 r = componentName != null ? mServices.get(componentName) : null;
7785 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007786 newArgs = new String[args.length - opti];
7787 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007788 }
7789
7790 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007791 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007793 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7794 synchronized (this) {
7795 for (ServiceRecord r1 : mServices.values()) {
7796 if (componentNameString == null
7797 || r1.name.flattenToString().contains(componentNameString)) {
7798 services.add(r1);
7799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 }
7801 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007802 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007803 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007805 }
7806 }
7807
7808 /**
7809 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7810 * there is a thread associated with the service.
7811 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007812 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7813 pw.println("------------------------------------------------------------"
7814 + "-------------------");
7815 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816 if (r.app != null && r.app.thread != null) {
7817 try {
7818 // flush anything that is already in the PrintWriter since the thread is going
7819 // to write to the file descriptor directly
7820 pw.flush();
7821 r.app.thread.dumpService(fd, r, args);
7822 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007823 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007824 } catch (RemoteException e) {
7825 pw.println("got a RemoteException while dumping the service");
7826 }
7827 }
7828 }
7829
Dianne Hackborn625ac272010-09-17 18:29:22 -07007830 /**
7831 * There are three things that cmd can be:
7832 * - a flattened component name that matched an existing activity
7833 * - the cmd arg isn't the flattened component name of an existing activity:
7834 * dump all activity whose component contains the cmd as a substring
7835 * - A hex number of the ActivityRecord object instance.
7836 */
7837 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7838 int opti, boolean dumpAll) {
7839 String[] newArgs;
7840 ComponentName componentName = ComponentName.unflattenFromString(name);
7841 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007842 if (componentName == null) {
7843 // Not a '/' separated full component name; maybe an object ID?
7844 try {
7845 objectId = Integer.parseInt(name, 16);
7846 name = null;
7847 componentName = null;
7848 } catch (RuntimeException e) {
7849 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007850 }
7851 newArgs = new String[args.length - opti];
7852 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7853
7854 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7855 synchronized (this) {
7856 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7857 if (componentName != null) {
7858 if (r1.intent.getComponent().equals(componentName)) {
7859 activities.add(r1);
7860 }
7861 } else if (name != null) {
7862 if (r1.intent.getComponent().flattenToString().contains(name)) {
7863 activities.add(r1);
7864 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007865 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007866 activities.add(r1);
7867 }
7868 }
7869 }
7870
7871 if (activities.size() <= 0) {
7872 return false;
7873 }
7874
Dianne Hackborn30d71892010-12-11 10:37:55 -08007875 TaskRecord lastTask = null;
7876 for (int i=activities.size()-1; i>=0; i--) {
7877 ActivityRecord r = (ActivityRecord)activities.get(i);
7878 if (lastTask != r.task) {
7879 lastTask = r.task;
7880 pw.print("* Task "); pw.print(lastTask.affinity);
7881 pw.print(" id="); pw.println(lastTask.taskId);
7882 if (dumpAll) {
7883 lastTask.dump(pw, " ");
7884 }
7885 }
7886 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007887 }
7888 return true;
7889 }
7890
7891 /**
7892 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7893 * there is a thread associated with the activity.
7894 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08007895 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
7896 ActivityRecord r, String[] args, boolean dumpAll) {
7897 synchronized (this) {
7898 pw.print(prefix); pw.print("* Activity ");
7899 pw.print(Integer.toHexString(System.identityHashCode(r)));
7900 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
7901 if (r.app != null) pw.println(r.app.pid);
7902 else pw.println("(not running)");
7903 if (dumpAll) {
7904 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007905 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007906 }
7907 if (r.app != null && r.app.thread != null) {
7908 try {
7909 // flush anything that is already in the PrintWriter since the thread is going
7910 // to write to the file descriptor directly
7911 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08007912 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007913 pw.flush();
7914 } catch (RemoteException e) {
7915 pw.println("got a RemoteException while dumping the activity");
7916 }
7917 }
7918 }
7919
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007920 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7921 int opti, boolean dumpAll) {
7922 boolean needSep = false;
7923
7924 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007925 if (mRegisteredReceivers.size() > 0) {
7926 pw.println(" ");
7927 pw.println(" Registered Receivers:");
7928 Iterator it = mRegisteredReceivers.values().iterator();
7929 while (it.hasNext()) {
7930 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007931 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 r.dump(pw, " ");
7933 }
7934 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 pw.println(" ");
7937 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007938 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007939 needSep = true;
7940 }
7941
7942 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7943 || mPendingBroadcast != null) {
7944 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007946 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007948 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7949 pw.println(" Broadcast #" + i + ":");
7950 mParallelBroadcasts.get(i).dump(pw, " ");
7951 }
7952 if (mOrderedBroadcasts.size() > 0) {
7953 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007954 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007955 }
7956 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7957 pw.println(" Serialized Broadcast #" + i + ":");
7958 mOrderedBroadcasts.get(i).dump(pw, " ");
7959 }
7960 pw.println(" ");
7961 pw.println(" Pending broadcast:");
7962 if (mPendingBroadcast != null) {
7963 mPendingBroadcast.dump(pw, " ");
7964 } else {
7965 pw.println(" (null)");
7966 }
7967 needSep = true;
7968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007969
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007970 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007971 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007972 pw.println(" Historical broadcasts:");
7973 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7974 BroadcastRecord r = mBroadcastHistory[i];
7975 if (r == null) {
7976 break;
7977 }
7978 pw.println(" Historical Broadcast #" + i + ":");
7979 r.dump(pw, " ");
7980 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007981 needSep = true;
7982 }
7983
7984 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007985 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007986 pw.println(" Sticky broadcasts:");
7987 StringBuilder sb = new StringBuilder(128);
7988 for (Map.Entry<String, ArrayList<Intent>> ent
7989 : mStickyBroadcasts.entrySet()) {
7990 pw.print(" * Sticky action "); pw.print(ent.getKey());
7991 pw.println(":");
7992 ArrayList<Intent> intents = ent.getValue();
7993 final int N = intents.size();
7994 for (int i=0; i<N; i++) {
7995 sb.setLength(0);
7996 sb.append(" Intent: ");
7997 intents.get(i).toShortString(sb, true, false);
7998 pw.println(sb.toString());
7999 Bundle bundle = intents.get(i).getExtras();
8000 if (bundle != null) {
8001 pw.print(" ");
8002 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008003 }
8004 }
8005 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008006 needSep = true;
8007 }
8008
8009 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008010 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008011 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008012 pw.println(" mHandler:");
8013 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008014 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008016
8017 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008018 }
8019
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008020 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8021 int opti, boolean dumpAll) {
8022 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008023
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008024 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008025 if (mServices.size() > 0) {
8026 pw.println(" Active services:");
8027 Iterator<ServiceRecord> it = mServices.values().iterator();
8028 while (it.hasNext()) {
8029 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008030 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008031 r.dump(pw, " ");
8032 }
8033 needSep = true;
8034 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008036
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008037 if (mPendingServices.size() > 0) {
8038 if (needSep) pw.println(" ");
8039 pw.println(" Pending services:");
8040 for (int i=0; i<mPendingServices.size(); i++) {
8041 ServiceRecord r = mPendingServices.get(i);
8042 pw.print(" * Pending "); pw.println(r);
8043 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008045 needSep = true;
8046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008047
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008048 if (mRestartingServices.size() > 0) {
8049 if (needSep) pw.println(" ");
8050 pw.println(" Restarting services:");
8051 for (int i=0; i<mRestartingServices.size(); i++) {
8052 ServiceRecord r = mRestartingServices.get(i);
8053 pw.print(" * Restarting "); pw.println(r);
8054 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008055 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008056 needSep = true;
8057 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008058
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008059 if (mStoppingServices.size() > 0) {
8060 if (needSep) pw.println(" ");
8061 pw.println(" Stopping services:");
8062 for (int i=0; i<mStoppingServices.size(); i++) {
8063 ServiceRecord r = mStoppingServices.get(i);
8064 pw.print(" * Stopping "); pw.println(r);
8065 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008067 needSep = true;
8068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008070 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008071 if (mServiceConnections.size() > 0) {
8072 if (needSep) pw.println(" ");
8073 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008074 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008075 = mServiceConnections.values().iterator();
8076 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008077 ArrayList<ConnectionRecord> r = it.next();
8078 for (int i=0; i<r.size(); i++) {
8079 pw.print(" * "); pw.println(r.get(i));
8080 r.get(i).dump(pw, " ");
8081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008082 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008083 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008084 }
8085 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008086
8087 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008088 }
8089
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008090 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8091 int opti, boolean dumpAll) {
8092 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008093
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008094 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008095 if (mProvidersByClass.size() > 0) {
8096 if (needSep) pw.println(" ");
8097 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008098 Iterator<Map.Entry<String, ContentProviderRecord>> it
8099 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008100 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008101 Map.Entry<String, ContentProviderRecord> e = it.next();
8102 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008103 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008104 r.dump(pw, " ");
8105 }
8106 needSep = true;
8107 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008108
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008109 if (mProvidersByName.size() > 0) {
8110 pw.println(" ");
8111 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008112 Iterator<Map.Entry<String, ContentProviderRecord>> it
8113 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008114 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008115 Map.Entry<String, ContentProviderRecord> e = it.next();
8116 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008117 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8118 pw.println(r);
8119 }
8120 needSep = true;
8121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008122 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008123
8124 if (mLaunchingProviders.size() > 0) {
8125 if (needSep) pw.println(" ");
8126 pw.println(" Launching content providers:");
8127 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8128 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8129 pw.println(mLaunchingProviders.get(i));
8130 }
8131 needSep = true;
8132 }
8133
8134 if (mGrantedUriPermissions.size() > 0) {
8135 pw.println();
8136 pw.println("Granted Uri Permissions:");
8137 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8138 int uid = mGrantedUriPermissions.keyAt(i);
8139 HashMap<Uri, UriPermission> perms
8140 = mGrantedUriPermissions.valueAt(i);
8141 pw.print(" * UID "); pw.print(uid);
8142 pw.println(" holds:");
8143 for (UriPermission perm : perms.values()) {
8144 pw.print(" "); pw.println(perm);
8145 perm.dump(pw, " ");
8146 }
8147 }
8148 needSep = true;
8149 }
8150
8151 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008152 }
8153
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008154 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8155 int opti, boolean dumpAll) {
8156 boolean needSep = false;
8157
8158 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159 if (this.mIntentSenderRecords.size() > 0) {
8160 Iterator<WeakReference<PendingIntentRecord>> it
8161 = mIntentSenderRecords.values().iterator();
8162 while (it.hasNext()) {
8163 WeakReference<PendingIntentRecord> ref = it.next();
8164 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008165 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008166 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008167 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008168 rec.dump(pw, " ");
8169 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008170 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008171 }
8172 }
8173 }
8174 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008175
8176 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008177 }
8178
8179 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008180 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008181 TaskRecord lastTask = null;
8182 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008183 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008184 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 if (lastTask != r.task) {
8186 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008187 pw.print(prefix);
8188 pw.print(full ? "* " : " ");
8189 pw.println(lastTask);
8190 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008191 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008193 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008194 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8195 pw.print(" #"); pw.print(i); pw.print(": ");
8196 pw.println(r);
8197 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008198 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008200 }
8201 }
8202
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008203 private static String buildOomTag(String prefix, String space, int val, int base) {
8204 if (val == base) {
8205 if (space == null) return prefix;
8206 return prefix + " ";
8207 }
8208 return prefix + "+" + Integer.toString(val-base);
8209 }
8210
8211 private static final int dumpProcessList(PrintWriter pw,
8212 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008213 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008214 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008215 final int N = list.size()-1;
8216 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008218 pw.println(String.format("%s%s #%2d: %s",
8219 prefix, (r.persistent ? persistentLabel : normalLabel),
8220 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008221 if (r.persistent) {
8222 numPers++;
8223 }
8224 }
8225 return numPers;
8226 }
8227
Dianne Hackborn287952c2010-09-22 22:34:31 -07008228 private static final void dumpProcessOomList(PrintWriter pw,
8229 ActivityManagerService service, List<ProcessRecord> list,
8230 String prefix, String normalLabel, String persistentLabel,
8231 boolean inclDetails) {
8232
8233 final long curRealtime = SystemClock.elapsedRealtime();
8234 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8235 final long curUptime = SystemClock.uptimeMillis();
8236 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8237
8238 final int N = list.size()-1;
8239 for (int i=N; i>=0; i--) {
8240 ProcessRecord r = list.get(i);
8241 String oomAdj;
8242 if (r.setAdj >= EMPTY_APP_ADJ) {
8243 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8244 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8245 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8246 } else if (r.setAdj >= HOME_APP_ADJ) {
8247 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8248 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8249 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8250 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8251 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8252 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8253 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8254 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8255 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8256 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8257 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8258 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8259 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8260 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8261 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8262 } else if (r.setAdj >= SYSTEM_ADJ) {
8263 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8264 } else {
8265 oomAdj = Integer.toString(r.setAdj);
8266 }
8267 String schedGroup;
8268 switch (r.setSchedGroup) {
8269 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8270 schedGroup = "B";
8271 break;
8272 case Process.THREAD_GROUP_DEFAULT:
8273 schedGroup = "F";
8274 break;
8275 default:
8276 schedGroup = Integer.toString(r.setSchedGroup);
8277 break;
8278 }
8279 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8280 prefix, (r.persistent ? persistentLabel : normalLabel),
8281 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8282 if (r.adjSource != null || r.adjTarget != null) {
8283 pw.print(prefix);
8284 pw.print(" ");
8285 if (r.adjTarget instanceof ComponentName) {
8286 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8287 } else if (r.adjTarget != null) {
8288 pw.print(r.adjTarget.toString());
8289 } else {
8290 pw.print("{null}");
8291 }
8292 pw.print("<=");
8293 if (r.adjSource instanceof ProcessRecord) {
8294 pw.print("Proc{");
8295 pw.print(((ProcessRecord)r.adjSource).toShortString());
8296 pw.println("}");
8297 } else if (r.adjSource != null) {
8298 pw.println(r.adjSource.toString());
8299 } else {
8300 pw.println("{null}");
8301 }
8302 }
8303 if (inclDetails) {
8304 pw.print(prefix);
8305 pw.print(" ");
8306 pw.print("oom: max="); pw.print(r.maxAdj);
8307 pw.print(" hidden="); pw.print(r.hiddenAdj);
8308 pw.print(" curRaw="); pw.print(r.curRawAdj);
8309 pw.print(" setRaw="); pw.print(r.setRawAdj);
8310 pw.print(" cur="); pw.print(r.curAdj);
8311 pw.print(" set="); pw.println(r.setAdj);
8312 pw.print(prefix);
8313 pw.print(" ");
8314 pw.print("keeping="); pw.print(r.keeping);
8315 pw.print(" hidden="); pw.print(r.hidden);
8316 pw.print(" empty="); pw.println(r.empty);
8317
8318 if (!r.keeping) {
8319 if (r.lastWakeTime != 0) {
8320 long wtime;
8321 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8322 synchronized (stats) {
8323 wtime = stats.getProcessWakeTime(r.info.uid,
8324 r.pid, curRealtime);
8325 }
8326 long timeUsed = wtime - r.lastWakeTime;
8327 pw.print(prefix);
8328 pw.print(" ");
8329 pw.print("keep awake over ");
8330 TimeUtils.formatDuration(realtimeSince, pw);
8331 pw.print(" used ");
8332 TimeUtils.formatDuration(timeUsed, pw);
8333 pw.print(" (");
8334 pw.print((timeUsed*100)/realtimeSince);
8335 pw.println("%)");
8336 }
8337 if (r.lastCpuTime != 0) {
8338 long timeUsed = r.curCpuTime - r.lastCpuTime;
8339 pw.print(prefix);
8340 pw.print(" ");
8341 pw.print("run cpu over ");
8342 TimeUtils.formatDuration(uptimeSince, pw);
8343 pw.print(" used ");
8344 TimeUtils.formatDuration(timeUsed, pw);
8345 pw.print(" (");
8346 pw.print((timeUsed*100)/uptimeSince);
8347 pw.println("%)");
8348 }
8349 }
8350 }
8351 }
8352 }
8353
Dianne Hackborn472ad872010-04-07 17:31:48 -07008354 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008355 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008356 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357 long uptime = SystemClock.uptimeMillis();
8358 long realtime = SystemClock.elapsedRealtime();
8359
8360 if (isCheckinRequest) {
8361 // short checkin version
8362 pw.println(uptime + "," + realtime);
8363 pw.flush();
8364 } else {
8365 pw.println("Applications Memory Usage (kB):");
8366 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8367 }
8368 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8369 ProcessRecord r = (ProcessRecord)list.get(i);
8370 if (r.thread != null) {
8371 if (!isCheckinRequest) {
8372 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8373 pw.flush();
8374 }
8375 try {
8376 r.thread.asBinder().dump(fd, args);
8377 } catch (RemoteException e) {
8378 if (!isCheckinRequest) {
8379 pw.println("Got RemoteException!");
8380 pw.flush();
8381 }
8382 }
8383 }
8384 }
8385 }
8386
8387 /**
8388 * Searches array of arguments for the specified string
8389 * @param args array of argument strings
8390 * @param value value to search for
8391 * @return true if the value is contained in the array
8392 */
8393 private static boolean scanArgs(String[] args, String value) {
8394 if (args != null) {
8395 for (String arg : args) {
8396 if (value.equals(arg)) {
8397 return true;
8398 }
8399 }
8400 }
8401 return false;
8402 }
8403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008404 private final void killServicesLocked(ProcessRecord app,
8405 boolean allowRestart) {
8406 // Report disconnected services.
8407 if (false) {
8408 // XXX we are letting the client link to the service for
8409 // death notifications.
8410 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008411 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008412 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008413 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008414 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008415 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008416 = r.connections.values().iterator();
8417 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008418 ArrayList<ConnectionRecord> cl = jt.next();
8419 for (int i=0; i<cl.size(); i++) {
8420 ConnectionRecord c = cl.get(i);
8421 if (c.binding.client != app) {
8422 try {
8423 //c.conn.connected(r.className, null);
8424 } catch (Exception e) {
8425 // todo: this should be asynchronous!
8426 Slog.w(TAG, "Exception thrown disconnected servce "
8427 + r.shortName
8428 + " from app " + app.processName, e);
8429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008430 }
8431 }
8432 }
8433 }
8434 }
8435 }
8436 }
8437
8438 // Clean up any connections this application has to other services.
8439 if (app.connections.size() > 0) {
8440 Iterator<ConnectionRecord> it = app.connections.iterator();
8441 while (it.hasNext()) {
8442 ConnectionRecord r = it.next();
8443 removeConnectionLocked(r, app, null);
8444 }
8445 }
8446 app.connections.clear();
8447
8448 if (app.services.size() != 0) {
8449 // Any services running in the application need to be placed
8450 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008451 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008453 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008454 synchronized (sr.stats.getBatteryStats()) {
8455 sr.stats.stopLaunchedLocked();
8456 }
8457 sr.app = null;
8458 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008459 if (mStoppingServices.remove(sr)) {
8460 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8461 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008462
8463 boolean hasClients = sr.bindings.size() > 0;
8464 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008465 Iterator<IntentBindRecord> bindings
8466 = sr.bindings.values().iterator();
8467 while (bindings.hasNext()) {
8468 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008469 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008470 + ": shouldUnbind=" + b.hasBound);
8471 b.binder = null;
8472 b.requested = b.received = b.hasBound = false;
8473 }
8474 }
8475
8476 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008477 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008478 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008479 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008480 sr.crashCount, sr.shortName, app.pid);
8481 bringDownServiceLocked(sr, true);
8482 } else if (!allowRestart) {
8483 bringDownServiceLocked(sr, true);
8484 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008485 boolean canceled = scheduleServiceRestartLocked(sr, true);
8486
8487 // Should the service remain running? Note that in the
8488 // extreme case of so many attempts to deliver a command
8489 // that it failed, that we also will stop it here.
8490 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8491 if (sr.pendingStarts.size() == 0) {
8492 sr.startRequested = false;
8493 if (!hasClients) {
8494 // Whoops, no reason to restart!
8495 bringDownServiceLocked(sr, true);
8496 }
8497 }
8498 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008499 }
8500 }
8501
8502 if (!allowRestart) {
8503 app.services.clear();
8504 }
8505 }
8506
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008507 // Make sure we have no more records on the stopping list.
8508 int i = mStoppingServices.size();
8509 while (i > 0) {
8510 i--;
8511 ServiceRecord sr = mStoppingServices.get(i);
8512 if (sr.app == app) {
8513 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008514 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008515 }
8516 }
8517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 app.executingServices.clear();
8519 }
8520
8521 private final void removeDyingProviderLocked(ProcessRecord proc,
8522 ContentProviderRecord cpr) {
8523 synchronized (cpr) {
8524 cpr.launchingApp = null;
8525 cpr.notifyAll();
8526 }
8527
8528 mProvidersByClass.remove(cpr.info.name);
8529 String names[] = cpr.info.authority.split(";");
8530 for (int j = 0; j < names.length; j++) {
8531 mProvidersByName.remove(names[j]);
8532 }
8533
8534 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8535 while (cit.hasNext()) {
8536 ProcessRecord capp = cit.next();
8537 if (!capp.persistent && capp.thread != null
8538 && capp.pid != 0
8539 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008540 Slog.i(TAG, "Kill " + capp.processName
8541 + " (pid " + capp.pid + "): provider " + cpr.info.name
8542 + " in dying process " + proc.processName);
8543 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8544 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008545 Process.killProcess(capp.pid);
8546 }
8547 }
8548
8549 mLaunchingProviders.remove(cpr);
8550 }
8551
8552 /**
8553 * Main code for cleaning up a process when it has gone away. This is
8554 * called both as a result of the process dying, or directly when stopping
8555 * a process when running in single process mode.
8556 */
8557 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8558 boolean restarting, int index) {
8559 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008560 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008561 }
8562
Dianne Hackborn36124872009-10-08 16:22:03 -07008563 mProcessesToGc.remove(app);
8564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008565 // Dismiss any open dialogs.
8566 if (app.crashDialog != null) {
8567 app.crashDialog.dismiss();
8568 app.crashDialog = null;
8569 }
8570 if (app.anrDialog != null) {
8571 app.anrDialog.dismiss();
8572 app.anrDialog = null;
8573 }
8574 if (app.waitDialog != null) {
8575 app.waitDialog.dismiss();
8576 app.waitDialog = null;
8577 }
8578
8579 app.crashing = false;
8580 app.notResponding = false;
8581
8582 app.resetPackageList();
8583 app.thread = null;
8584 app.forcingToForeground = null;
8585 app.foregroundServices = false;
8586
8587 killServicesLocked(app, true);
8588
8589 boolean restart = false;
8590
8591 int NL = mLaunchingProviders.size();
8592
8593 // Remove published content providers.
8594 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008595 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008596 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008597 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008598 cpr.provider = null;
8599 cpr.app = null;
8600
8601 // See if someone is waiting for this provider... in which
8602 // case we don't remove it, but just let it restart.
8603 int i = 0;
8604 if (!app.bad) {
8605 for (; i<NL; i++) {
8606 if (mLaunchingProviders.get(i) == cpr) {
8607 restart = true;
8608 break;
8609 }
8610 }
8611 } else {
8612 i = NL;
8613 }
8614
8615 if (i >= NL) {
8616 removeDyingProviderLocked(app, cpr);
8617 NL = mLaunchingProviders.size();
8618 }
8619 }
8620 app.pubProviders.clear();
8621 }
8622
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008623 // Take care of any launching providers waiting for this process.
8624 if (checkAppInLaunchingProvidersLocked(app, false)) {
8625 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008626 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008628 // Unregister from connected content providers.
8629 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008630 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008631 while (it.hasNext()) {
8632 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8633 cpr.clients.remove(app);
8634 }
8635 app.conProviders.clear();
8636 }
8637
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008638 // At this point there may be remaining entries in mLaunchingProviders
8639 // where we were the only one waiting, so they are no longer of use.
8640 // Look for these and clean up if found.
8641 // XXX Commented out for now. Trying to figure out a way to reproduce
8642 // the actual situation to identify what is actually going on.
8643 if (false) {
8644 for (int i=0; i<NL; i++) {
8645 ContentProviderRecord cpr = (ContentProviderRecord)
8646 mLaunchingProviders.get(i);
8647 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8648 synchronized (cpr) {
8649 cpr.launchingApp = null;
8650 cpr.notifyAll();
8651 }
8652 }
8653 }
8654 }
8655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 skipCurrentReceiverLocked(app);
8657
8658 // Unregister any receivers.
8659 if (app.receivers.size() > 0) {
8660 Iterator<ReceiverList> it = app.receivers.iterator();
8661 while (it.hasNext()) {
8662 removeReceiverLocked(it.next());
8663 }
8664 app.receivers.clear();
8665 }
8666
Christopher Tate181fafa2009-05-14 11:12:14 -07008667 // If the app is undergoing backup, tell the backup manager about it
8668 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008669 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008670 try {
8671 IBackupManager bm = IBackupManager.Stub.asInterface(
8672 ServiceManager.getService(Context.BACKUP_SERVICE));
8673 bm.agentDisconnected(app.info.packageName);
8674 } catch (RemoteException e) {
8675 // can't happen; backup manager is local
8676 }
8677 }
8678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008679 // If the caller is restarting this app, then leave it in its
8680 // current lists and let the caller take care of it.
8681 if (restarting) {
8682 return;
8683 }
8684
8685 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008686 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008687 "Removing non-persistent process during cleanup: " + app);
8688 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008689 if (mHeavyWeightProcess == app) {
8690 mHeavyWeightProcess = null;
8691 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8692 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008693 } else if (!app.removed) {
8694 // This app is persistent, so we need to keep its record around.
8695 // If it is not already on the pending app list, add it there
8696 // and start a new process for it.
8697 app.thread = null;
8698 app.forcingToForeground = null;
8699 app.foregroundServices = false;
8700 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8701 mPersistentStartingProcesses.add(app);
8702 restart = true;
8703 }
8704 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008705 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8706 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008707 mProcessesOnHold.remove(app);
8708
The Android Open Source Project4df24232009-03-05 14:34:35 -08008709 if (app == mHomeProcess) {
8710 mHomeProcess = null;
8711 }
8712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008713 if (restart) {
8714 // We have components that still need to be running in the
8715 // process, so re-launch it.
8716 mProcessNames.put(app.processName, app.info.uid, app);
8717 startProcessLocked(app, "restart", app.processName);
8718 } else if (app.pid > 0 && app.pid != MY_PID) {
8719 // Goodbye!
8720 synchronized (mPidsSelfLocked) {
8721 mPidsSelfLocked.remove(app.pid);
8722 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8723 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008724 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 }
8726 }
8727
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008728 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8729 // Look through the content providers we are waiting to have launched,
8730 // and if any run in this process then either schedule a restart of
8731 // the process or kill the client waiting for it if this process has
8732 // gone bad.
8733 int NL = mLaunchingProviders.size();
8734 boolean restart = false;
8735 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008736 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008737 if (cpr.launchingApp == app) {
8738 if (!alwaysBad && !app.bad) {
8739 restart = true;
8740 } else {
8741 removeDyingProviderLocked(app, cpr);
8742 NL = mLaunchingProviders.size();
8743 }
8744 }
8745 }
8746 return restart;
8747 }
8748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 // =========================================================
8750 // SERVICES
8751 // =========================================================
8752
8753 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8754 ActivityManager.RunningServiceInfo info =
8755 new ActivityManager.RunningServiceInfo();
8756 info.service = r.name;
8757 if (r.app != null) {
8758 info.pid = r.app.pid;
8759 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008760 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008761 info.process = r.processName;
8762 info.foreground = r.isForeground;
8763 info.activeSince = r.createTime;
8764 info.started = r.startRequested;
8765 info.clientCount = r.connections.size();
8766 info.crashCount = r.crashCount;
8767 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008768 if (r.isForeground) {
8769 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8770 }
8771 if (r.startRequested) {
8772 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8773 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008774 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008775 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8776 }
8777 if (r.app != null && r.app.persistent) {
8778 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8779 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008780
8781 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8782 for (int i=0; i<connl.size(); i++) {
8783 ConnectionRecord conn = connl.get(i);
8784 if (conn.clientLabel != 0) {
8785 info.clientPackage = conn.binding.client.info.packageName;
8786 info.clientLabel = conn.clientLabel;
8787 return info;
8788 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008789 }
8790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008791 return info;
8792 }
8793
8794 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8795 int flags) {
8796 synchronized (this) {
8797 ArrayList<ActivityManager.RunningServiceInfo> res
8798 = new ArrayList<ActivityManager.RunningServiceInfo>();
8799
8800 if (mServices.size() > 0) {
8801 Iterator<ServiceRecord> it = mServices.values().iterator();
8802 while (it.hasNext() && res.size() < maxNum) {
8803 res.add(makeRunningServiceInfoLocked(it.next()));
8804 }
8805 }
8806
8807 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8808 ServiceRecord r = mRestartingServices.get(i);
8809 ActivityManager.RunningServiceInfo info =
8810 makeRunningServiceInfoLocked(r);
8811 info.restarting = r.nextRestartTime;
8812 res.add(info);
8813 }
8814
8815 return res;
8816 }
8817 }
8818
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008819 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8820 synchronized (this) {
8821 ServiceRecord r = mServices.get(name);
8822 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008823 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8824 for (int i=0; i<conn.size(); i++) {
8825 if (conn.get(i).clientIntent != null) {
8826 return conn.get(i).clientIntent;
8827 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008828 }
8829 }
8830 }
8831 }
8832 return null;
8833 }
8834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008835 private final ServiceRecord findServiceLocked(ComponentName name,
8836 IBinder token) {
8837 ServiceRecord r = mServices.get(name);
8838 return r == token ? r : null;
8839 }
8840
8841 private final class ServiceLookupResult {
8842 final ServiceRecord record;
8843 final String permission;
8844
8845 ServiceLookupResult(ServiceRecord _record, String _permission) {
8846 record = _record;
8847 permission = _permission;
8848 }
8849 };
8850
8851 private ServiceLookupResult findServiceLocked(Intent service,
8852 String resolvedType) {
8853 ServiceRecord r = null;
8854 if (service.getComponent() != null) {
8855 r = mServices.get(service.getComponent());
8856 }
8857 if (r == null) {
8858 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8859 r = mServicesByIntent.get(filter);
8860 }
8861
8862 if (r == null) {
8863 try {
8864 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008865 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008866 service, resolvedType, 0);
8867 ServiceInfo sInfo =
8868 rInfo != null ? rInfo.serviceInfo : null;
8869 if (sInfo == null) {
8870 return null;
8871 }
8872
8873 ComponentName name = new ComponentName(
8874 sInfo.applicationInfo.packageName, sInfo.name);
8875 r = mServices.get(name);
8876 } catch (RemoteException ex) {
8877 // pm is in same process, this will never happen.
8878 }
8879 }
8880 if (r != null) {
8881 int callingPid = Binder.getCallingPid();
8882 int callingUid = Binder.getCallingUid();
8883 if (checkComponentPermission(r.permission,
8884 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8885 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008886 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 + " from pid=" + callingPid
8888 + ", uid=" + callingUid
8889 + " requires " + r.permission);
8890 return new ServiceLookupResult(null, r.permission);
8891 }
8892 return new ServiceLookupResult(r, null);
8893 }
8894 return null;
8895 }
8896
8897 private class ServiceRestarter implements Runnable {
8898 private ServiceRecord mService;
8899
8900 void setService(ServiceRecord service) {
8901 mService = service;
8902 }
8903
8904 public void run() {
8905 synchronized(ActivityManagerService.this) {
8906 performServiceRestartLocked(mService);
8907 }
8908 }
8909 }
8910
8911 private ServiceLookupResult retrieveServiceLocked(Intent service,
8912 String resolvedType, int callingPid, int callingUid) {
8913 ServiceRecord r = null;
8914 if (service.getComponent() != null) {
8915 r = mServices.get(service.getComponent());
8916 }
8917 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8918 r = mServicesByIntent.get(filter);
8919 if (r == null) {
8920 try {
8921 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008922 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008923 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008924 ServiceInfo sInfo =
8925 rInfo != null ? rInfo.serviceInfo : null;
8926 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008927 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 ": not found");
8929 return null;
8930 }
8931
8932 ComponentName name = new ComponentName(
8933 sInfo.applicationInfo.packageName, sInfo.name);
8934 r = mServices.get(name);
8935 if (r == null) {
8936 filter = new Intent.FilterComparison(service.cloneFilter());
8937 ServiceRestarter res = new ServiceRestarter();
8938 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8939 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8940 synchronized (stats) {
8941 ss = stats.getServiceStatsLocked(
8942 sInfo.applicationInfo.uid, sInfo.packageName,
8943 sInfo.name);
8944 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008945 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008946 res.setService(r);
8947 mServices.put(name, r);
8948 mServicesByIntent.put(filter, r);
8949
8950 // Make sure this component isn't in the pending list.
8951 int N = mPendingServices.size();
8952 for (int i=0; i<N; i++) {
8953 ServiceRecord pr = mPendingServices.get(i);
8954 if (pr.name.equals(name)) {
8955 mPendingServices.remove(i);
8956 i--;
8957 N--;
8958 }
8959 }
8960 }
8961 } catch (RemoteException ex) {
8962 // pm is in same process, this will never happen.
8963 }
8964 }
8965 if (r != null) {
8966 if (checkComponentPermission(r.permission,
8967 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8968 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008969 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 + " from pid=" + Binder.getCallingPid()
8971 + ", uid=" + Binder.getCallingUid()
8972 + " requires " + r.permission);
8973 return new ServiceLookupResult(null, r.permission);
8974 }
8975 return new ServiceLookupResult(r, null);
8976 }
8977 return null;
8978 }
8979
Dianne Hackborn287952c2010-09-22 22:34:31 -07008980 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8981 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8982 + why + " of " + r + " in app " + r.app);
8983 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8984 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008985 long now = SystemClock.uptimeMillis();
8986 if (r.executeNesting == 0 && r.app != null) {
8987 if (r.app.executingServices.size() == 0) {
8988 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8989 msg.obj = r.app;
8990 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8991 }
8992 r.app.executingServices.add(r);
8993 }
8994 r.executeNesting++;
8995 r.executingStart = now;
8996 }
8997
8998 private final void sendServiceArgsLocked(ServiceRecord r,
8999 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009000 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009001 if (N == 0) {
9002 return;
9003 }
9004
Dianne Hackborn39792d22010-08-19 18:01:52 -07009005 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009006 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009007 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009008 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9009 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009010 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009011 // If somehow we got a dummy start at the front, then
9012 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009013 continue;
9014 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009015 si.deliveredTime = SystemClock.uptimeMillis();
9016 r.deliveredStarts.add(si);
9017 si.deliveryCount++;
9018 if (si.targetPermissionUid >= 0) {
9019 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009020 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009021 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009022 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009023 if (!oomAdjusted) {
9024 oomAdjusted = true;
9025 updateOomAdjLocked(r.app);
9026 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009027 int flags = 0;
9028 if (si.deliveryCount > 0) {
9029 flags |= Service.START_FLAG_RETRY;
9030 }
9031 if (si.doneExecutingCount > 0) {
9032 flags |= Service.START_FLAG_REDELIVERY;
9033 }
9034 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009035 } catch (RemoteException e) {
9036 // Remote process gone... we'll let the normal cleanup take
9037 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009038 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009039 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009040 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009041 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009042 break;
9043 }
9044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 }
9046
9047 private final boolean requestServiceBindingLocked(ServiceRecord r,
9048 IntentBindRecord i, boolean rebind) {
9049 if (r.app == null || r.app.thread == null) {
9050 // If service is not currently running, can't yet bind.
9051 return false;
9052 }
9053 if ((!i.requested || rebind) && i.apps.size() > 0) {
9054 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009055 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009056 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9057 if (!rebind) {
9058 i.requested = true;
9059 }
9060 i.hasBound = true;
9061 i.doRebind = false;
9062 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009063 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009064 return false;
9065 }
9066 }
9067 return true;
9068 }
9069
9070 private final void requestServiceBindingsLocked(ServiceRecord r) {
9071 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9072 while (bindings.hasNext()) {
9073 IntentBindRecord i = bindings.next();
9074 if (!requestServiceBindingLocked(r, i, false)) {
9075 break;
9076 }
9077 }
9078 }
9079
9080 private final void realStartServiceLocked(ServiceRecord r,
9081 ProcessRecord app) throws RemoteException {
9082 if (app.thread == null) {
9083 throw new RemoteException();
9084 }
9085
9086 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009087 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088
9089 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009090 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009091 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092
9093 boolean created = false;
9094 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009095 mStringBuilder.setLength(0);
9096 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009097 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009099 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009100 synchronized (r.stats.getBatteryStats()) {
9101 r.stats.startLaunchedLocked();
9102 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009103 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009105 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009106 created = true;
9107 } finally {
9108 if (!created) {
9109 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009110 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009111 }
9112 }
9113
9114 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009115
9116 // If the service is in the started state, and there are no
9117 // pending arguments, then fake up one so its onStartCommand() will
9118 // be called.
9119 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9120 r.lastStartId++;
9121 if (r.lastStartId < 1) {
9122 r.lastStartId = 1;
9123 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009124 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009125 }
9126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009127 sendServiceArgsLocked(r, true);
9128 }
9129
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009130 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9131 boolean allowCancel) {
9132 boolean canceled = false;
9133
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009134 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009135 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009136 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009137
9138 // Any delivered but not yet finished starts should be put back
9139 // on the pending list.
9140 final int N = r.deliveredStarts.size();
9141 if (N > 0) {
9142 for (int i=N-1; i>=0; i--) {
9143 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009144 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009145 if (si.intent == null) {
9146 // We'll generate this again if needed.
9147 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9148 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9149 r.pendingStarts.add(0, si);
9150 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9151 dur *= 2;
9152 if (minDuration < dur) minDuration = dur;
9153 if (resetTime < dur) resetTime = dur;
9154 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009155 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009156 + r.name);
9157 canceled = true;
9158 }
9159 }
9160 r.deliveredStarts.clear();
9161 }
9162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 r.totalRestartCount++;
9164 if (r.restartDelay == 0) {
9165 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009166 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009167 } else {
9168 // If it has been a "reasonably long time" since the service
9169 // was started, then reset our restart duration back to
9170 // the beginning, so we don't infinitely increase the duration
9171 // on a service that just occasionally gets killed (which is
9172 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009173 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009174 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009175 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009176 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009177 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009178 if (r.restartDelay < minDuration) {
9179 r.restartDelay = minDuration;
9180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 }
9182 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009183
9184 r.nextRestartTime = now + r.restartDelay;
9185
9186 // Make sure that we don't end up restarting a bunch of services
9187 // all at the same time.
9188 boolean repeat;
9189 do {
9190 repeat = false;
9191 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9192 ServiceRecord r2 = mRestartingServices.get(i);
9193 if (r2 != r && r.nextRestartTime
9194 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9195 && r.nextRestartTime
9196 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9197 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9198 r.restartDelay = r.nextRestartTime - now;
9199 repeat = true;
9200 break;
9201 }
9202 }
9203 } while (repeat);
9204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009205 if (!mRestartingServices.contains(r)) {
9206 mRestartingServices.add(r);
9207 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009208
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009209 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009211 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009212 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009213 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009214 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009216 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217 r.shortName, r.restartDelay);
9218
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009219 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 }
9221
9222 final void performServiceRestartLocked(ServiceRecord r) {
9223 if (!mRestartingServices.contains(r)) {
9224 return;
9225 }
9226 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9227 }
9228
9229 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9230 if (r.restartDelay == 0) {
9231 return false;
9232 }
9233 r.resetRestartCounter();
9234 mRestartingServices.remove(r);
9235 mHandler.removeCallbacks(r.restarter);
9236 return true;
9237 }
9238
9239 private final boolean bringUpServiceLocked(ServiceRecord r,
9240 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009241 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009242 //r.dump(" ");
9243
Dianne Hackborn36124872009-10-08 16:22:03 -07009244 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009245 sendServiceArgsLocked(r, false);
9246 return true;
9247 }
9248
9249 if (!whileRestarting && r.restartDelay > 0) {
9250 // If waiting for a restart, then do nothing.
9251 return true;
9252 }
9253
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009254 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009255
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009256 // We are now bringing the service up, so no longer in the
9257 // restarting state.
9258 mRestartingServices.remove(r);
9259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009260 final String appName = r.processName;
9261 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9262 if (app != null && app.thread != null) {
9263 try {
9264 realStartServiceLocked(r, app);
9265 return true;
9266 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009267 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009268 }
9269
9270 // If a dead object exception was thrown -- fall through to
9271 // restart the application.
9272 }
9273
Dianne Hackborn36124872009-10-08 16:22:03 -07009274 // Not running -- get it started, and enqueue this service record
9275 // to be executed when the app comes up.
9276 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9277 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009278 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009279 + r.appInfo.packageName + "/"
9280 + r.appInfo.uid + " for service "
9281 + r.intent.getIntent() + ": process is bad");
9282 bringDownServiceLocked(r, true);
9283 return false;
9284 }
9285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 mPendingServices.add(r);
9288 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290 return true;
9291 }
9292
9293 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009294 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 //r.dump(" ");
9296
9297 // Does it still need to run?
9298 if (!force && r.startRequested) {
9299 return;
9300 }
9301 if (r.connections.size() > 0) {
9302 if (!force) {
9303 // XXX should probably keep a count of the number of auto-create
9304 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009305 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009307 ArrayList<ConnectionRecord> cr = it.next();
9308 for (int i=0; i<cr.size(); i++) {
9309 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9310 return;
9311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 }
9313 }
9314 }
9315
9316 // Report to all of the connections that the service is no longer
9317 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009318 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009319 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009320 ArrayList<ConnectionRecord> c = it.next();
9321 for (int i=0; i<c.size(); i++) {
9322 try {
9323 c.get(i).conn.connected(r.name, null);
9324 } catch (Exception e) {
9325 Slog.w(TAG, "Failure disconnecting service " + r.name +
9326 " to connection " + c.get(i).conn.asBinder() +
9327 " (in " + c.get(i).binding.client.processName + ")", e);
9328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009329 }
9330 }
9331 }
9332
9333 // Tell the service that it has been unbound.
9334 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9335 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9336 while (it.hasNext()) {
9337 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009338 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009339 + ": hasBound=" + ibr.hasBound);
9340 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9341 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009342 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009343 updateOomAdjLocked(r.app);
9344 ibr.hasBound = false;
9345 r.app.thread.scheduleUnbindService(r,
9346 ibr.intent.getIntent());
9347 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009348 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349 + r.shortName, e);
9350 serviceDoneExecutingLocked(r, true);
9351 }
9352 }
9353 }
9354 }
9355
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009356 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009357 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009358 System.identityHashCode(r), r.shortName,
9359 (r.app != null) ? r.app.pid : -1);
9360
9361 mServices.remove(r.name);
9362 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009363 r.totalRestartCount = 0;
9364 unscheduleServiceRestartLocked(r);
9365
9366 // Also make sure it is not on the pending list.
9367 int N = mPendingServices.size();
9368 for (int i=0; i<N; i++) {
9369 if (mPendingServices.get(i) == r) {
9370 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009371 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009372 i--;
9373 N--;
9374 }
9375 }
9376
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009377 r.cancelNotification();
9378 r.isForeground = false;
9379 r.foregroundId = 0;
9380 r.foregroundNoti = null;
9381
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009382 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009383 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009384 r.pendingStarts.clear();
9385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009386 if (r.app != null) {
9387 synchronized (r.stats.getBatteryStats()) {
9388 r.stats.stopLaunchedLocked();
9389 }
9390 r.app.services.remove(r);
9391 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009392 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009393 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 mStoppingServices.add(r);
9395 updateOomAdjLocked(r.app);
9396 r.app.thread.scheduleStopService(r);
9397 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009398 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009399 + r.shortName, e);
9400 serviceDoneExecutingLocked(r, true);
9401 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009402 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009403 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009404 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009405 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009406 }
9407 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009408 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009409 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009410 }
9411 }
9412
9413 ComponentName startServiceLocked(IApplicationThread caller,
9414 Intent service, String resolvedType,
9415 int callingPid, int callingUid) {
9416 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009417 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009418 + " type=" + resolvedType + " args=" + service.getExtras());
9419
9420 if (caller != null) {
9421 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9422 if (callerApp == null) {
9423 throw new SecurityException(
9424 "Unable to find app for caller " + caller
9425 + " (pid=" + Binder.getCallingPid()
9426 + ") when starting service " + service);
9427 }
9428 }
9429
9430 ServiceLookupResult res =
9431 retrieveServiceLocked(service, resolvedType,
9432 callingPid, callingUid);
9433 if (res == null) {
9434 return null;
9435 }
9436 if (res.record == null) {
9437 return new ComponentName("!", res.permission != null
9438 ? res.permission : "private to package");
9439 }
9440 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009441 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9442 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009443 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009444 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009445 }
9446 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009447 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009448 r.lastStartId++;
9449 if (r.lastStartId < 1) {
9450 r.lastStartId = 1;
9451 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009452 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9453 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 r.lastActivity = SystemClock.uptimeMillis();
9455 synchronized (r.stats.getBatteryStats()) {
9456 r.stats.startRunningLocked();
9457 }
9458 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9459 return new ComponentName("!", "Service process is bad");
9460 }
9461 return r.name;
9462 }
9463 }
9464
9465 public ComponentName startService(IApplicationThread caller, Intent service,
9466 String resolvedType) {
9467 // Refuse possible leaked file descriptors
9468 if (service != null && service.hasFileDescriptors() == true) {
9469 throw new IllegalArgumentException("File descriptors passed in Intent");
9470 }
9471
9472 synchronized(this) {
9473 final int callingPid = Binder.getCallingPid();
9474 final int callingUid = Binder.getCallingUid();
9475 final long origId = Binder.clearCallingIdentity();
9476 ComponentName res = startServiceLocked(caller, service,
9477 resolvedType, callingPid, callingUid);
9478 Binder.restoreCallingIdentity(origId);
9479 return res;
9480 }
9481 }
9482
9483 ComponentName startServiceInPackage(int uid,
9484 Intent service, String resolvedType) {
9485 synchronized(this) {
9486 final long origId = Binder.clearCallingIdentity();
9487 ComponentName res = startServiceLocked(null, service,
9488 resolvedType, -1, uid);
9489 Binder.restoreCallingIdentity(origId);
9490 return res;
9491 }
9492 }
9493
9494 public int stopService(IApplicationThread caller, Intent service,
9495 String resolvedType) {
9496 // Refuse possible leaked file descriptors
9497 if (service != null && service.hasFileDescriptors() == true) {
9498 throw new IllegalArgumentException("File descriptors passed in Intent");
9499 }
9500
9501 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009502 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009503 + " type=" + resolvedType);
9504
9505 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9506 if (caller != null && callerApp == null) {
9507 throw new SecurityException(
9508 "Unable to find app for caller " + caller
9509 + " (pid=" + Binder.getCallingPid()
9510 + ") when stopping service " + service);
9511 }
9512
9513 // If this service is active, make sure it is stopped.
9514 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9515 if (r != null) {
9516 if (r.record != null) {
9517 synchronized (r.record.stats.getBatteryStats()) {
9518 r.record.stats.stopRunningLocked();
9519 }
9520 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009521 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009522 final long origId = Binder.clearCallingIdentity();
9523 bringDownServiceLocked(r.record, false);
9524 Binder.restoreCallingIdentity(origId);
9525 return 1;
9526 }
9527 return -1;
9528 }
9529 }
9530
9531 return 0;
9532 }
9533
9534 public IBinder peekService(Intent service, String resolvedType) {
9535 // Refuse possible leaked file descriptors
9536 if (service != null && service.hasFileDescriptors() == true) {
9537 throw new IllegalArgumentException("File descriptors passed in Intent");
9538 }
9539
9540 IBinder ret = null;
9541
9542 synchronized(this) {
9543 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9544
9545 if (r != null) {
9546 // r.record is null if findServiceLocked() failed the caller permission check
9547 if (r.record == null) {
9548 throw new SecurityException(
9549 "Permission Denial: Accessing service " + r.record.name
9550 + " from pid=" + Binder.getCallingPid()
9551 + ", uid=" + Binder.getCallingUid()
9552 + " requires " + r.permission);
9553 }
9554 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9555 if (ib != null) {
9556 ret = ib.binder;
9557 }
9558 }
9559 }
9560
9561 return ret;
9562 }
9563
9564 public boolean stopServiceToken(ComponentName className, IBinder token,
9565 int startId) {
9566 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009567 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009568 + " " + token + " startId=" + startId);
9569 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009570 if (r != null) {
9571 if (startId >= 0) {
9572 // Asked to only stop if done with all work. Note that
9573 // to avoid leaks, we will take this as dropping all
9574 // start items up to and including this one.
9575 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9576 if (si != null) {
9577 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009578 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9579 cur.removeUriPermissionsLocked();
9580 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009581 break;
9582 }
9583 }
9584 }
9585
9586 if (r.lastStartId != startId) {
9587 return false;
9588 }
9589
9590 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009591 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009592 + " is last, but have " + r.deliveredStarts.size()
9593 + " remaining args");
9594 }
9595 }
9596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009597 synchronized (r.stats.getBatteryStats()) {
9598 r.stats.stopRunningLocked();
9599 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009600 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009601 }
9602 final long origId = Binder.clearCallingIdentity();
9603 bringDownServiceLocked(r, false);
9604 Binder.restoreCallingIdentity(origId);
9605 return true;
9606 }
9607 }
9608 return false;
9609 }
9610
9611 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009612 int id, Notification notification, boolean removeNotification) {
9613 final long origId = Binder.clearCallingIdentity();
9614 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 synchronized(this) {
9616 ServiceRecord r = findServiceLocked(className, token);
9617 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009618 if (id != 0) {
9619 if (notification == null) {
9620 throw new IllegalArgumentException("null notification");
9621 }
9622 if (r.foregroundId != id) {
9623 r.cancelNotification();
9624 r.foregroundId = id;
9625 }
9626 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9627 r.foregroundNoti = notification;
9628 r.isForeground = true;
9629 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009630 if (r.app != null) {
9631 updateServiceForegroundLocked(r.app, true);
9632 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009633 } else {
9634 if (r.isForeground) {
9635 r.isForeground = false;
9636 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009637 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009638 updateServiceForegroundLocked(r.app, true);
9639 }
9640 }
9641 if (removeNotification) {
9642 r.cancelNotification();
9643 r.foregroundId = 0;
9644 r.foregroundNoti = null;
9645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009646 }
9647 }
9648 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009649 } finally {
9650 Binder.restoreCallingIdentity(origId);
9651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 }
9653
9654 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9655 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009656 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009657 if (sr.isForeground) {
9658 anyForeground = true;
9659 break;
9660 }
9661 }
9662 if (anyForeground != proc.foregroundServices) {
9663 proc.foregroundServices = anyForeground;
9664 if (oomAdj) {
9665 updateOomAdjLocked();
9666 }
9667 }
9668 }
9669
9670 public int bindService(IApplicationThread caller, IBinder token,
9671 Intent service, String resolvedType,
9672 IServiceConnection connection, int flags) {
9673 // Refuse possible leaked file descriptors
9674 if (service != null && service.hasFileDescriptors() == true) {
9675 throw new IllegalArgumentException("File descriptors passed in Intent");
9676 }
9677
9678 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009679 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009680 + " type=" + resolvedType + " conn=" + connection.asBinder()
9681 + " flags=0x" + Integer.toHexString(flags));
9682 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9683 if (callerApp == null) {
9684 throw new SecurityException(
9685 "Unable to find app for caller " + caller
9686 + " (pid=" + Binder.getCallingPid()
9687 + ") when binding service " + service);
9688 }
9689
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009690 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009692 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009693 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009694 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009695 return 0;
9696 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009697 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 }
9699
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009700 int clientLabel = 0;
9701 PendingIntent clientIntent = null;
9702
9703 if (callerApp.info.uid == Process.SYSTEM_UID) {
9704 // Hacky kind of thing -- allow system stuff to tell us
9705 // what they are, so we can report this elsewhere for
9706 // others to know why certain services are running.
9707 try {
9708 clientIntent = (PendingIntent)service.getParcelableExtra(
9709 Intent.EXTRA_CLIENT_INTENT);
9710 } catch (RuntimeException e) {
9711 }
9712 if (clientIntent != null) {
9713 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9714 if (clientLabel != 0) {
9715 // There are no useful extras in the intent, trash them.
9716 // System code calling with this stuff just needs to know
9717 // this will happen.
9718 service = service.cloneFilter();
9719 }
9720 }
9721 }
9722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009723 ServiceLookupResult res =
9724 retrieveServiceLocked(service, resolvedType,
9725 Binder.getCallingPid(), Binder.getCallingUid());
9726 if (res == null) {
9727 return 0;
9728 }
9729 if (res.record == null) {
9730 return -1;
9731 }
9732 ServiceRecord s = res.record;
9733
9734 final long origId = Binder.clearCallingIdentity();
9735
9736 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009737 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009738 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009739 }
9740
9741 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9742 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009743 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009744
9745 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009746 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9747 if (clist == null) {
9748 clist = new ArrayList<ConnectionRecord>();
9749 s.connections.put(binder, clist);
9750 }
9751 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752 b.connections.add(c);
9753 if (activity != null) {
9754 if (activity.connections == null) {
9755 activity.connections = new HashSet<ConnectionRecord>();
9756 }
9757 activity.connections.add(c);
9758 }
9759 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009760 clist = mServiceConnections.get(binder);
9761 if (clist == null) {
9762 clist = new ArrayList<ConnectionRecord>();
9763 mServiceConnections.put(binder, clist);
9764 }
9765 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766
9767 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9768 s.lastActivity = SystemClock.uptimeMillis();
9769 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9770 return 0;
9771 }
9772 }
9773
9774 if (s.app != null) {
9775 // This could have made the service more important.
9776 updateOomAdjLocked(s.app);
9777 }
9778
Joe Onorato8a9b2202010-02-26 18:56:32 -08009779 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 + ": received=" + b.intent.received
9781 + " apps=" + b.intent.apps.size()
9782 + " doRebind=" + b.intent.doRebind);
9783
9784 if (s.app != null && b.intent.received) {
9785 // Service is already running, so we can immediately
9786 // publish the connection.
9787 try {
9788 c.conn.connected(s.name, b.intent.binder);
9789 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009790 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 + " to connection " + c.conn.asBinder()
9792 + " (in " + c.binding.client.processName + ")", e);
9793 }
9794
9795 // If this is the first app connected back to this binding,
9796 // and the service had previously asked to be told when
9797 // rebound, then do so.
9798 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9799 requestServiceBindingLocked(s, b.intent, true);
9800 }
9801 } else if (!b.intent.requested) {
9802 requestServiceBindingLocked(s, b.intent, false);
9803 }
9804
9805 Binder.restoreCallingIdentity(origId);
9806 }
9807
9808 return 1;
9809 }
9810
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009811 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009812 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 IBinder binder = c.conn.asBinder();
9814 AppBindRecord b = c.binding;
9815 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009816 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9817 if (clist != null) {
9818 clist.remove(c);
9819 if (clist.size() == 0) {
9820 s.connections.remove(binder);
9821 }
9822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009823 b.connections.remove(c);
9824 if (c.activity != null && c.activity != skipAct) {
9825 if (c.activity.connections != null) {
9826 c.activity.connections.remove(c);
9827 }
9828 }
9829 if (b.client != skipApp) {
9830 b.client.connections.remove(c);
9831 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009832 clist = mServiceConnections.get(binder);
9833 if (clist != null) {
9834 clist.remove(c);
9835 if (clist.size() == 0) {
9836 mServiceConnections.remove(binder);
9837 }
9838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839
9840 if (b.connections.size() == 0) {
9841 b.intent.apps.remove(b.client);
9842 }
9843
Joe Onorato8a9b2202010-02-26 18:56:32 -08009844 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009845 + ": shouldUnbind=" + b.intent.hasBound);
9846 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9847 && b.intent.hasBound) {
9848 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009849 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009850 updateOomAdjLocked(s.app);
9851 b.intent.hasBound = false;
9852 // Assume the client doesn't want to know about a rebind;
9853 // we will deal with that later if it asks for one.
9854 b.intent.doRebind = false;
9855 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9856 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009857 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009858 serviceDoneExecutingLocked(s, true);
9859 }
9860 }
9861
9862 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9863 bringDownServiceLocked(s, false);
9864 }
9865 }
9866
9867 public boolean unbindService(IServiceConnection connection) {
9868 synchronized (this) {
9869 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009870 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009871 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9872 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009873 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009874 + connection.asBinder());
9875 return false;
9876 }
9877
9878 final long origId = Binder.clearCallingIdentity();
9879
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009880 while (clist.size() > 0) {
9881 ConnectionRecord r = clist.get(0);
9882 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009884 if (r.binding.service.app != null) {
9885 // This could have made the service less important.
9886 updateOomAdjLocked(r.binding.service.app);
9887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009888 }
9889
9890 Binder.restoreCallingIdentity(origId);
9891 }
9892
9893 return true;
9894 }
9895
9896 public void publishService(IBinder token, Intent intent, IBinder service) {
9897 // Refuse possible leaked file descriptors
9898 if (intent != null && intent.hasFileDescriptors() == true) {
9899 throw new IllegalArgumentException("File descriptors passed in Intent");
9900 }
9901
9902 synchronized(this) {
9903 if (!(token instanceof ServiceRecord)) {
9904 throw new IllegalArgumentException("Invalid service token");
9905 }
9906 ServiceRecord r = (ServiceRecord)token;
9907
9908 final long origId = Binder.clearCallingIdentity();
9909
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009910 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009911 + " " + intent + ": " + service);
9912 if (r != null) {
9913 Intent.FilterComparison filter
9914 = new Intent.FilterComparison(intent);
9915 IntentBindRecord b = r.bindings.get(filter);
9916 if (b != null && !b.received) {
9917 b.binder = service;
9918 b.requested = true;
9919 b.received = true;
9920 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009921 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 = r.connections.values().iterator();
9923 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009924 ArrayList<ConnectionRecord> clist = it.next();
9925 for (int i=0; i<clist.size(); i++) {
9926 ConnectionRecord c = clist.get(i);
9927 if (!filter.equals(c.binding.intent.intent)) {
9928 if (DEBUG_SERVICE) Slog.v(
9929 TAG, "Not publishing to: " + c);
9930 if (DEBUG_SERVICE) Slog.v(
9931 TAG, "Bound intent: " + c.binding.intent.intent);
9932 if (DEBUG_SERVICE) Slog.v(
9933 TAG, "Published intent: " + intent);
9934 continue;
9935 }
9936 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9937 try {
9938 c.conn.connected(r.name, service);
9939 } catch (Exception e) {
9940 Slog.w(TAG, "Failure sending service " + r.name +
9941 " to connection " + c.conn.asBinder() +
9942 " (in " + c.binding.client.processName + ")", e);
9943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009944 }
9945 }
9946 }
9947 }
9948
9949 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9950
9951 Binder.restoreCallingIdentity(origId);
9952 }
9953 }
9954 }
9955
9956 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9957 // Refuse possible leaked file descriptors
9958 if (intent != null && intent.hasFileDescriptors() == true) {
9959 throw new IllegalArgumentException("File descriptors passed in Intent");
9960 }
9961
9962 synchronized(this) {
9963 if (!(token instanceof ServiceRecord)) {
9964 throw new IllegalArgumentException("Invalid service token");
9965 }
9966 ServiceRecord r = (ServiceRecord)token;
9967
9968 final long origId = Binder.clearCallingIdentity();
9969
9970 if (r != null) {
9971 Intent.FilterComparison filter
9972 = new Intent.FilterComparison(intent);
9973 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009974 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009975 + " at " + b + ": apps="
9976 + (b != null ? b.apps.size() : 0));
9977 if (b != null) {
9978 if (b.apps.size() > 0) {
9979 // Applications have already bound since the last
9980 // unbind, so just rebind right here.
9981 requestServiceBindingLocked(r, b, true);
9982 } else {
9983 // Note to tell the service the next time there is
9984 // a new client.
9985 b.doRebind = true;
9986 }
9987 }
9988
9989 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9990
9991 Binder.restoreCallingIdentity(origId);
9992 }
9993 }
9994 }
9995
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009996 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009997 synchronized(this) {
9998 if (!(token instanceof ServiceRecord)) {
9999 throw new IllegalArgumentException("Invalid service token");
10000 }
10001 ServiceRecord r = (ServiceRecord)token;
10002 boolean inStopping = mStoppingServices.contains(token);
10003 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010004 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010005 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 + " with incorrect token: given " + token
10007 + ", expected " + r);
10008 return;
10009 }
10010
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010011 if (type == 1) {
10012 // This is a call from a service start... take care of
10013 // book-keeping.
10014 r.callStart = true;
10015 switch (res) {
10016 case Service.START_STICKY_COMPATIBILITY:
10017 case Service.START_STICKY: {
10018 // We are done with the associated start arguments.
10019 r.findDeliveredStart(startId, true);
10020 // Don't stop if killed.
10021 r.stopIfKilled = false;
10022 break;
10023 }
10024 case Service.START_NOT_STICKY: {
10025 // We are done with the associated start arguments.
10026 r.findDeliveredStart(startId, true);
10027 if (r.lastStartId == startId) {
10028 // There is no more work, and this service
10029 // doesn't want to hang around if killed.
10030 r.stopIfKilled = true;
10031 }
10032 break;
10033 }
10034 case Service.START_REDELIVER_INTENT: {
10035 // We'll keep this item until they explicitly
10036 // call stop for it, but keep track of the fact
10037 // that it was delivered.
10038 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10039 if (si != null) {
10040 si.deliveryCount = 0;
10041 si.doneExecutingCount++;
10042 // Don't stop if killed.
10043 r.stopIfKilled = true;
10044 }
10045 break;
10046 }
10047 default:
10048 throw new IllegalArgumentException(
10049 "Unknown service start result: " + res);
10050 }
10051 if (res == Service.START_STICKY_COMPATIBILITY) {
10052 r.callStart = false;
10053 }
10054 }
10055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056 final long origId = Binder.clearCallingIdentity();
10057 serviceDoneExecutingLocked(r, inStopping);
10058 Binder.restoreCallingIdentity(origId);
10059 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010060 Slog.w(TAG, "Done executing unknown service from pid "
10061 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010062 }
10063 }
10064 }
10065
10066 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010067 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10068 + ": nesting=" + r.executeNesting
10069 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010070 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010071 r.executeNesting--;
10072 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010073 if (DEBUG_SERVICE) Slog.v(TAG,
10074 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 r.app.executingServices.remove(r);
10076 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010077 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10078 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010079 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10080 }
10081 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010082 if (DEBUG_SERVICE) Slog.v(TAG,
10083 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010084 mStoppingServices.remove(r);
10085 }
10086 updateOomAdjLocked(r.app);
10087 }
10088 }
10089
10090 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010091 String anrMessage = null;
10092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010093 synchronized(this) {
10094 if (proc.executingServices.size() == 0 || proc.thread == null) {
10095 return;
10096 }
10097 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10098 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10099 ServiceRecord timeout = null;
10100 long nextTime = 0;
10101 while (it.hasNext()) {
10102 ServiceRecord sr = it.next();
10103 if (sr.executingStart < maxTime) {
10104 timeout = sr;
10105 break;
10106 }
10107 if (sr.executingStart > nextTime) {
10108 nextTime = sr.executingStart;
10109 }
10110 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010111 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010112 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010113 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 } else {
10115 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10116 msg.obj = proc;
10117 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10118 }
10119 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010120
10121 if (anrMessage != null) {
10122 appNotResponding(proc, null, null, anrMessage);
10123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010124 }
10125
10126 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010127 // BACKUP AND RESTORE
10128 // =========================================================
10129
10130 // Cause the target app to be launched if necessary and its backup agent
10131 // instantiated. The backup agent will invoke backupAgentCreated() on the
10132 // activity manager to announce its creation.
10133 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010134 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010135 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10136
10137 synchronized(this) {
10138 // !!! TODO: currently no check here that we're already bound
10139 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10140 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10141 synchronized (stats) {
10142 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10143 }
10144
10145 BackupRecord r = new BackupRecord(ss, app, backupMode);
10146 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10147 // startProcessLocked() returns existing proc's record if it's already running
10148 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010149 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010150 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010151 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010152 return false;
10153 }
10154
10155 r.app = proc;
10156 mBackupTarget = r;
10157 mBackupAppName = app.packageName;
10158
Christopher Tate6fa95972009-06-05 18:43:55 -070010159 // Try not to kill the process during backup
10160 updateOomAdjLocked(proc);
10161
Christopher Tate181fafa2009-05-14 11:12:14 -070010162 // If the process is already attached, schedule the creation of the backup agent now.
10163 // If it is not yet live, this will be done when it attaches to the framework.
10164 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010165 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010166 try {
10167 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10168 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010169 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010170 }
10171 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010172 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010173 }
10174 // Invariants: at this point, the target app process exists and the application
10175 // is either already running or in the process of coming up. mBackupTarget and
10176 // mBackupAppName describe the app, so that when it binds back to the AM we
10177 // know that it's scheduled for a backup-agent operation.
10178 }
10179
10180 return true;
10181 }
10182
10183 // A backup agent has just come up
10184 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010185 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010186 + " = " + agent);
10187
10188 synchronized(this) {
10189 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010190 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010191 return;
10192 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010193 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010194
Dianne Hackborn06740692010-09-22 22:46:21 -070010195 long oldIdent = Binder.clearCallingIdentity();
10196 try {
10197 IBackupManager bm = IBackupManager.Stub.asInterface(
10198 ServiceManager.getService(Context.BACKUP_SERVICE));
10199 bm.agentConnected(agentPackageName, agent);
10200 } catch (RemoteException e) {
10201 // can't happen; the backup manager service is local
10202 } catch (Exception e) {
10203 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10204 e.printStackTrace();
10205 } finally {
10206 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010207 }
10208 }
10209
10210 // done with this agent
10211 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010212 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010213 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010214 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010215 return;
10216 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010217
10218 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010219 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010220 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010221 return;
10222 }
10223
Christopher Tate181fafa2009-05-14 11:12:14 -070010224 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010225 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010226 return;
10227 }
10228
Christopher Tate6fa95972009-06-05 18:43:55 -070010229 ProcessRecord proc = mBackupTarget.app;
10230 mBackupTarget = null;
10231 mBackupAppName = null;
10232
10233 // Not backing this app up any more; reset its OOM adjustment
10234 updateOomAdjLocked(proc);
10235
Christopher Tatec7b31e32009-06-10 15:49:30 -070010236 // If the app crashed during backup, 'thread' will be null here
10237 if (proc.thread != null) {
10238 try {
10239 proc.thread.scheduleDestroyBackupAgent(appInfo);
10240 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010241 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010242 e.printStackTrace();
10243 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010244 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010245 }
10246 }
10247 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010248 // BROADCASTS
10249 // =========================================================
10250
Josh Bartel7f208742010-02-25 11:01:44 -060010251 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010252 List cur) {
10253 final ContentResolver resolver = mContext.getContentResolver();
10254 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10255 if (list == null) {
10256 return cur;
10257 }
10258 int N = list.size();
10259 for (int i=0; i<N; i++) {
10260 Intent intent = list.get(i);
10261 if (filter.match(resolver, intent, true, TAG) >= 0) {
10262 if (cur == null) {
10263 cur = new ArrayList<Intent>();
10264 }
10265 cur.add(intent);
10266 }
10267 }
10268 return cur;
10269 }
10270
10271 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010272 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010273 + mBroadcastsScheduled);
10274
10275 if (mBroadcastsScheduled) {
10276 return;
10277 }
10278 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10279 mBroadcastsScheduled = true;
10280 }
10281
10282 public Intent registerReceiver(IApplicationThread caller,
10283 IIntentReceiver receiver, IntentFilter filter, String permission) {
10284 synchronized(this) {
10285 ProcessRecord callerApp = null;
10286 if (caller != null) {
10287 callerApp = getRecordForAppLocked(caller);
10288 if (callerApp == null) {
10289 throw new SecurityException(
10290 "Unable to find app for caller " + caller
10291 + " (pid=" + Binder.getCallingPid()
10292 + ") when registering receiver " + receiver);
10293 }
10294 }
10295
10296 List allSticky = null;
10297
10298 // Look for any matching sticky broadcasts...
10299 Iterator actions = filter.actionsIterator();
10300 if (actions != null) {
10301 while (actions.hasNext()) {
10302 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010303 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 }
10305 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010306 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010307 }
10308
10309 // The first sticky in the list is returned directly back to
10310 // the client.
10311 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10312
Joe Onorato8a9b2202010-02-26 18:56:32 -080010313 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 + ": " + sticky);
10315
10316 if (receiver == null) {
10317 return sticky;
10318 }
10319
10320 ReceiverList rl
10321 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10322 if (rl == null) {
10323 rl = new ReceiverList(this, callerApp,
10324 Binder.getCallingPid(),
10325 Binder.getCallingUid(), receiver);
10326 if (rl.app != null) {
10327 rl.app.receivers.add(rl);
10328 } else {
10329 try {
10330 receiver.asBinder().linkToDeath(rl, 0);
10331 } catch (RemoteException e) {
10332 return sticky;
10333 }
10334 rl.linkedToDeath = true;
10335 }
10336 mRegisteredReceivers.put(receiver.asBinder(), rl);
10337 }
10338 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10339 rl.add(bf);
10340 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010341 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010342 }
10343 mReceiverResolver.addFilter(bf);
10344
10345 // Enqueue broadcasts for all existing stickies that match
10346 // this filter.
10347 if (allSticky != null) {
10348 ArrayList receivers = new ArrayList();
10349 receivers.add(bf);
10350
10351 int N = allSticky.size();
10352 for (int i=0; i<N; i++) {
10353 Intent intent = (Intent)allSticky.get(i);
10354 BroadcastRecord r = new BroadcastRecord(intent, null,
10355 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010356 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 if (mParallelBroadcasts.size() == 0) {
10358 scheduleBroadcastsLocked();
10359 }
10360 mParallelBroadcasts.add(r);
10361 }
10362 }
10363
10364 return sticky;
10365 }
10366 }
10367
10368 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010369 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370
10371 boolean doNext = false;
10372
10373 synchronized(this) {
10374 ReceiverList rl
10375 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10376 if (rl != null) {
10377 if (rl.curBroadcast != null) {
10378 BroadcastRecord r = rl.curBroadcast;
10379 doNext = finishReceiverLocked(
10380 receiver.asBinder(), r.resultCode, r.resultData,
10381 r.resultExtras, r.resultAbort, true);
10382 }
10383
10384 if (rl.app != null) {
10385 rl.app.receivers.remove(rl);
10386 }
10387 removeReceiverLocked(rl);
10388 if (rl.linkedToDeath) {
10389 rl.linkedToDeath = false;
10390 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10391 }
10392 }
10393 }
10394
10395 if (!doNext) {
10396 return;
10397 }
10398
10399 final long origId = Binder.clearCallingIdentity();
10400 processNextBroadcast(false);
10401 trimApplications();
10402 Binder.restoreCallingIdentity(origId);
10403 }
10404
10405 void removeReceiverLocked(ReceiverList rl) {
10406 mRegisteredReceivers.remove(rl.receiver.asBinder());
10407 int N = rl.size();
10408 for (int i=0; i<N; i++) {
10409 mReceiverResolver.removeFilter(rl.get(i));
10410 }
10411 }
10412
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010413 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10414 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10415 ProcessRecord r = mLruProcesses.get(i);
10416 if (r.thread != null) {
10417 try {
10418 r.thread.dispatchPackageBroadcast(cmd, packages);
10419 } catch (RemoteException ex) {
10420 }
10421 }
10422 }
10423 }
10424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 private final int broadcastIntentLocked(ProcessRecord callerApp,
10426 String callerPackage, Intent intent, String resolvedType,
10427 IIntentReceiver resultTo, int resultCode, String resultData,
10428 Bundle map, String requiredPermission,
10429 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10430 intent = new Intent(intent);
10431
Joe Onorato8a9b2202010-02-26 18:56:32 -080010432 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010433 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10434 + " ordered=" + ordered);
10435 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010436 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010437 }
10438
10439 // Handle special intents: if this broadcast is from the package
10440 // manager about a package being removed, we need to remove all of
10441 // its activities from the history stack.
10442 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10443 intent.getAction());
10444 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10445 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010446 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010447 || uidRemoved) {
10448 if (checkComponentPermission(
10449 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10450 callingPid, callingUid, -1)
10451 == PackageManager.PERMISSION_GRANTED) {
10452 if (uidRemoved) {
10453 final Bundle intentExtras = intent.getExtras();
10454 final int uid = intentExtras != null
10455 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10456 if (uid >= 0) {
10457 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10458 synchronized (bs) {
10459 bs.removeUidStatsLocked(uid);
10460 }
10461 }
10462 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010463 // If resources are unvailble just force stop all
10464 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010465 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010466 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10467 if (list != null && (list.length > 0)) {
10468 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010469 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010470 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010471 sendPackageBroadcastLocked(
10472 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010473 }
10474 } else {
10475 Uri data = intent.getData();
10476 String ssp;
10477 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10478 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10479 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010480 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010481 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010482 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10483 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10484 new String[] {ssp});
10485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010486 }
10487 }
10488 }
10489 } else {
10490 String msg = "Permission Denial: " + intent.getAction()
10491 + " broadcast from " + callerPackage + " (pid=" + callingPid
10492 + ", uid=" + callingUid + ")"
10493 + " requires "
10494 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010495 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010496 throw new SecurityException(msg);
10497 }
10498 }
10499
10500 /*
10501 * If this is the time zone changed action, queue up a message that will reset the timezone
10502 * of all currently running processes. This message will get queued up before the broadcast
10503 * happens.
10504 */
10505 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10506 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10507 }
10508
Robert Greenwalt03595d02010-11-02 14:08:23 -070010509 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10510 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10511 }
10512
Robert Greenwalt434203a2010-10-11 16:00:27 -070010513 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10514 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10515 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10516 }
10517
Dianne Hackborn854060af2009-07-09 18:14:31 -070010518 /*
10519 * Prevent non-system code (defined here to be non-persistent
10520 * processes) from sending protected broadcasts.
10521 */
10522 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10523 || callingUid == Process.SHELL_UID || callingUid == 0) {
10524 // Always okay.
10525 } else if (callerApp == null || !callerApp.persistent) {
10526 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010527 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010528 intent.getAction())) {
10529 String msg = "Permission Denial: not allowed to send broadcast "
10530 + intent.getAction() + " from pid="
10531 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010532 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010533 throw new SecurityException(msg);
10534 }
10535 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010536 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010537 return BROADCAST_SUCCESS;
10538 }
10539 }
10540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010541 // Add to the sticky list if requested.
10542 if (sticky) {
10543 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10544 callingPid, callingUid)
10545 != PackageManager.PERMISSION_GRANTED) {
10546 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10547 + callingPid + ", uid=" + callingUid
10548 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010549 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010550 throw new SecurityException(msg);
10551 }
10552 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010553 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010554 + " and enforce permission " + requiredPermission);
10555 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10556 }
10557 if (intent.getComponent() != null) {
10558 throw new SecurityException(
10559 "Sticky broadcasts can't target a specific component");
10560 }
10561 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10562 if (list == null) {
10563 list = new ArrayList<Intent>();
10564 mStickyBroadcasts.put(intent.getAction(), list);
10565 }
10566 int N = list.size();
10567 int i;
10568 for (i=0; i<N; i++) {
10569 if (intent.filterEquals(list.get(i))) {
10570 // This sticky already exists, replace it.
10571 list.set(i, new Intent(intent));
10572 break;
10573 }
10574 }
10575 if (i >= N) {
10576 list.add(new Intent(intent));
10577 }
10578 }
10579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010580 // Figure out who all will receive this broadcast.
10581 List receivers = null;
10582 List<BroadcastFilter> registeredReceivers = null;
10583 try {
10584 if (intent.getComponent() != null) {
10585 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010586 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010587 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588 if (ai != null) {
10589 receivers = new ArrayList();
10590 ResolveInfo ri = new ResolveInfo();
10591 ri.activityInfo = ai;
10592 receivers.add(ri);
10593 }
10594 } else {
10595 // Need to resolve the intent to interested receivers...
10596 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10597 == 0) {
10598 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010599 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010600 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010601 }
Mihai Preda074edef2009-05-18 17:13:31 +020010602 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010603 }
10604 } catch (RemoteException ex) {
10605 // pm is in same process, this will never happen.
10606 }
10607
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010608 final boolean replacePending =
10609 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10610
Joe Onorato8a9b2202010-02-26 18:56:32 -080010611 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010612 + " replacePending=" + replacePending);
10613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10615 if (!ordered && NR > 0) {
10616 // If we are not serializing this broadcast, then send the
10617 // registered receivers separately so they don't wait for the
10618 // components to be launched.
10619 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10620 callerPackage, callingPid, callingUid, requiredPermission,
10621 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010622 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010623 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010624 TAG, "Enqueueing parallel broadcast " + r
10625 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010626 boolean replaced = false;
10627 if (replacePending) {
10628 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10629 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010630 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010631 "***** DROPPING PARALLEL: " + intent);
10632 mParallelBroadcasts.set(i, r);
10633 replaced = true;
10634 break;
10635 }
10636 }
10637 }
10638 if (!replaced) {
10639 mParallelBroadcasts.add(r);
10640 scheduleBroadcastsLocked();
10641 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010642 registeredReceivers = null;
10643 NR = 0;
10644 }
10645
10646 // Merge into one list.
10647 int ir = 0;
10648 if (receivers != null) {
10649 // A special case for PACKAGE_ADDED: do not allow the package
10650 // being added to see this broadcast. This prevents them from
10651 // using this as a back door to get run as soon as they are
10652 // installed. Maybe in the future we want to have a special install
10653 // broadcast or such for apps, but we'd like to deliberately make
10654 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010655 String skipPackages[] = null;
10656 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10657 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10658 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10659 Uri data = intent.getData();
10660 if (data != null) {
10661 String pkgName = data.getSchemeSpecificPart();
10662 if (pkgName != null) {
10663 skipPackages = new String[] { pkgName };
10664 }
10665 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010666 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010667 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010668 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010669 if (skipPackages != null && (skipPackages.length > 0)) {
10670 for (String skipPackage : skipPackages) {
10671 if (skipPackage != null) {
10672 int NT = receivers.size();
10673 for (int it=0; it<NT; it++) {
10674 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10675 if (curt.activityInfo.packageName.equals(skipPackage)) {
10676 receivers.remove(it);
10677 it--;
10678 NT--;
10679 }
10680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010681 }
10682 }
10683 }
10684
10685 int NT = receivers != null ? receivers.size() : 0;
10686 int it = 0;
10687 ResolveInfo curt = null;
10688 BroadcastFilter curr = null;
10689 while (it < NT && ir < NR) {
10690 if (curt == null) {
10691 curt = (ResolveInfo)receivers.get(it);
10692 }
10693 if (curr == null) {
10694 curr = registeredReceivers.get(ir);
10695 }
10696 if (curr.getPriority() >= curt.priority) {
10697 // Insert this broadcast record into the final list.
10698 receivers.add(it, curr);
10699 ir++;
10700 curr = null;
10701 it++;
10702 NT++;
10703 } else {
10704 // Skip to the next ResolveInfo in the final list.
10705 it++;
10706 curt = null;
10707 }
10708 }
10709 }
10710 while (ir < NR) {
10711 if (receivers == null) {
10712 receivers = new ArrayList();
10713 }
10714 receivers.add(registeredReceivers.get(ir));
10715 ir++;
10716 }
10717
10718 if ((receivers != null && receivers.size() > 0)
10719 || resultTo != null) {
10720 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10721 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010722 receivers, resultTo, resultCode, resultData, map, ordered,
10723 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010724 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 TAG, "Enqueueing ordered broadcast " + r
10726 + ": prev had " + mOrderedBroadcasts.size());
10727 if (DEBUG_BROADCAST) {
10728 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010729 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010730 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010731 boolean replaced = false;
10732 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010733 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010734 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010735 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010736 "***** DROPPING ORDERED: " + intent);
10737 mOrderedBroadcasts.set(i, r);
10738 replaced = true;
10739 break;
10740 }
10741 }
10742 }
10743 if (!replaced) {
10744 mOrderedBroadcasts.add(r);
10745 scheduleBroadcastsLocked();
10746 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010747 }
10748
10749 return BROADCAST_SUCCESS;
10750 }
10751
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010752 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 // Refuse possible leaked file descriptors
10754 if (intent != null && intent.hasFileDescriptors() == true) {
10755 throw new IllegalArgumentException("File descriptors passed in Intent");
10756 }
10757
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010758 int flags = intent.getFlags();
10759
10760 if (!mProcessesReady) {
10761 // if the caller really truly claims to know what they're doing, go
10762 // ahead and allow the broadcast without launching any receivers
10763 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10764 intent = new Intent(intent);
10765 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10766 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10767 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10768 + " before boot completion");
10769 throw new IllegalStateException("Cannot broadcast before boot completed");
10770 }
10771 }
10772
10773 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10774 throw new IllegalArgumentException(
10775 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10776 }
10777
10778 return intent;
10779 }
10780
10781 public final int broadcastIntent(IApplicationThread caller,
10782 Intent intent, String resolvedType, IIntentReceiver resultTo,
10783 int resultCode, String resultData, Bundle map,
10784 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010786 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010788 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10789 final int callingPid = Binder.getCallingPid();
10790 final int callingUid = Binder.getCallingUid();
10791 final long origId = Binder.clearCallingIdentity();
10792 int res = broadcastIntentLocked(callerApp,
10793 callerApp != null ? callerApp.info.packageName : null,
10794 intent, resolvedType, resultTo,
10795 resultCode, resultData, map, requiredPermission, serialized,
10796 sticky, callingPid, callingUid);
10797 Binder.restoreCallingIdentity(origId);
10798 return res;
10799 }
10800 }
10801
10802 int broadcastIntentInPackage(String packageName, int uid,
10803 Intent intent, String resolvedType, IIntentReceiver resultTo,
10804 int resultCode, String resultData, Bundle map,
10805 String requiredPermission, boolean serialized, boolean sticky) {
10806 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010807 intent = verifyBroadcastLocked(intent);
10808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010809 final long origId = Binder.clearCallingIdentity();
10810 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10811 resultTo, resultCode, resultData, map, requiredPermission,
10812 serialized, sticky, -1, uid);
10813 Binder.restoreCallingIdentity(origId);
10814 return res;
10815 }
10816 }
10817
10818 public final void unbroadcastIntent(IApplicationThread caller,
10819 Intent intent) {
10820 // Refuse possible leaked file descriptors
10821 if (intent != null && intent.hasFileDescriptors() == true) {
10822 throw new IllegalArgumentException("File descriptors passed in Intent");
10823 }
10824
10825 synchronized(this) {
10826 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10827 != PackageManager.PERMISSION_GRANTED) {
10828 String msg = "Permission Denial: unbroadcastIntent() from pid="
10829 + Binder.getCallingPid()
10830 + ", uid=" + Binder.getCallingUid()
10831 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010832 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 throw new SecurityException(msg);
10834 }
10835 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10836 if (list != null) {
10837 int N = list.size();
10838 int i;
10839 for (i=0; i<N; i++) {
10840 if (intent.filterEquals(list.get(i))) {
10841 list.remove(i);
10842 break;
10843 }
10844 }
10845 }
10846 }
10847 }
10848
10849 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10850 String resultData, Bundle resultExtras, boolean resultAbort,
10851 boolean explicit) {
10852 if (mOrderedBroadcasts.size() == 0) {
10853 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010854 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010855 }
10856 return false;
10857 }
10858 BroadcastRecord r = mOrderedBroadcasts.get(0);
10859 if (r.receiver == null) {
10860 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010861 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010862 }
10863 return false;
10864 }
10865 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010866 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010867 return false;
10868 }
10869 int state = r.state;
10870 r.state = r.IDLE;
10871 if (state == r.IDLE) {
10872 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010873 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010874 }
10875 }
10876 r.receiver = null;
10877 r.intent.setComponent(null);
10878 if (r.curApp != null) {
10879 r.curApp.curReceiver = null;
10880 }
10881 if (r.curFilter != null) {
10882 r.curFilter.receiverList.curBroadcast = null;
10883 }
10884 r.curFilter = null;
10885 r.curApp = null;
10886 r.curComponent = null;
10887 r.curReceiver = null;
10888 mPendingBroadcast = null;
10889
10890 r.resultCode = resultCode;
10891 r.resultData = resultData;
10892 r.resultExtras = resultExtras;
10893 r.resultAbort = resultAbort;
10894
10895 // We will process the next receiver right now if this is finishing
10896 // an app receiver (which is always asynchronous) or after we have
10897 // come back from calling a receiver.
10898 return state == BroadcastRecord.APP_RECEIVE
10899 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10900 }
10901
10902 public void finishReceiver(IBinder who, int resultCode, String resultData,
10903 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010904 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010905
10906 // Refuse possible leaked file descriptors
10907 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10908 throw new IllegalArgumentException("File descriptors passed in Bundle");
10909 }
10910
10911 boolean doNext;
10912
10913 final long origId = Binder.clearCallingIdentity();
10914
10915 synchronized(this) {
10916 doNext = finishReceiverLocked(
10917 who, resultCode, resultData, resultExtras, resultAbort, true);
10918 }
10919
10920 if (doNext) {
10921 processNextBroadcast(false);
10922 }
10923 trimApplications();
10924
10925 Binder.restoreCallingIdentity(origId);
10926 }
10927
Jeff Brown4d94a762010-09-23 11:33:28 -070010928 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 if (r.nextReceiver > 0) {
10930 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10931 if (curReceiver instanceof BroadcastFilter) {
10932 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010933 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010934 System.identityHashCode(r),
10935 r.intent.getAction(),
10936 r.nextReceiver - 1,
10937 System.identityHashCode(bf));
10938 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010939 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010940 System.identityHashCode(r),
10941 r.intent.getAction(),
10942 r.nextReceiver - 1,
10943 ((ResolveInfo)curReceiver).toString());
10944 }
10945 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010946 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010947 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010948 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010949 System.identityHashCode(r),
10950 r.intent.getAction(),
10951 r.nextReceiver,
10952 "NONE");
10953 }
10954 }
10955
Jeff Brown4d94a762010-09-23 11:33:28 -070010956 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10957 if (! mPendingBroadcastTimeoutMessage) {
10958 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10959 mHandler.sendMessageAtTime(msg, timeoutTime);
10960 mPendingBroadcastTimeoutMessage = true;
10961 }
10962 }
10963
10964 private final void cancelBroadcastTimeoutLocked() {
10965 if (mPendingBroadcastTimeoutMessage) {
10966 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10967 mPendingBroadcastTimeoutMessage = false;
10968 }
10969 }
10970
10971 private final void broadcastTimeoutLocked(boolean fromMsg) {
10972 if (fromMsg) {
10973 mPendingBroadcastTimeoutMessage = false;
10974 }
10975
10976 if (mOrderedBroadcasts.size() == 0) {
10977 return;
10978 }
10979
10980 long now = SystemClock.uptimeMillis();
10981 BroadcastRecord r = mOrderedBroadcasts.get(0);
10982 if (fromMsg) {
10983 if (mDidDexOpt) {
10984 // Delay timeouts until dexopt finishes.
10985 mDidDexOpt = false;
10986 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10987 setBroadcastTimeoutLocked(timeoutTime);
10988 return;
10989 }
10990 if (! mProcessesReady) {
10991 // Only process broadcast timeouts if the system is ready. That way
10992 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10993 // to do heavy lifting for system up.
10994 return;
10995 }
10996
10997 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10998 if (timeoutTime > now) {
10999 // We can observe premature timeouts because we do not cancel and reset the
11000 // broadcast timeout message after each receiver finishes. Instead, we set up
11001 // an initial timeout then kick it down the road a little further as needed
11002 // when it expires.
11003 if (DEBUG_BROADCAST) Slog.v(TAG,
11004 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11005 + timeoutTime);
11006 setBroadcastTimeoutLocked(timeoutTime);
11007 return;
11008 }
11009 }
11010
11011 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11012 + ", started " + (now - r.receiverTime) + "ms ago");
11013 r.receiverTime = now;
11014 r.anrCount++;
11015
11016 // Current receiver has passed its expiration date.
11017 if (r.nextReceiver <= 0) {
11018 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11019 return;
11020 }
11021
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011022 ProcessRecord app = null;
11023 String anrMessage = null;
11024
Jeff Brown4d94a762010-09-23 11:33:28 -070011025 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11026 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11027 logBroadcastReceiverDiscardLocked(r);
11028 if (curReceiver instanceof BroadcastFilter) {
11029 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11030 if (bf.receiverList.pid != 0
11031 && bf.receiverList.pid != MY_PID) {
11032 synchronized (this.mPidsSelfLocked) {
11033 app = this.mPidsSelfLocked.get(
11034 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011037 } else {
11038 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011039 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011040
Jeff Brown4d94a762010-09-23 11:33:28 -070011041 if (app != null) {
11042 anrMessage = "Broadcast of " + r.intent.toString();
11043 }
11044
11045 if (mPendingBroadcast == r) {
11046 mPendingBroadcast = null;
11047 }
11048
11049 // Move on to the next receiver.
11050 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11051 r.resultExtras, r.resultAbort, true);
11052 scheduleBroadcastsLocked();
11053
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011054 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011055 // Post the ANR to the handler since we do not want to process ANRs while
11056 // potentially holding our lock.
11057 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 }
11060
11061 private final void processCurBroadcastLocked(BroadcastRecord r,
11062 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011063 if (DEBUG_BROADCAST) Slog.v(TAG,
11064 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 if (app.thread == null) {
11066 throw new RemoteException();
11067 }
11068 r.receiver = app.thread.asBinder();
11069 r.curApp = app;
11070 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011071 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072
11073 // Tell the application to launch this receiver.
11074 r.intent.setComponent(r.curComponent);
11075
11076 boolean started = false;
11077 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011078 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 "Delivering to component " + r.curComponent
11080 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011081 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011082 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11083 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011084 if (DEBUG_BROADCAST) Slog.v(TAG,
11085 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011086 started = true;
11087 } finally {
11088 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011089 if (DEBUG_BROADCAST) Slog.v(TAG,
11090 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 r.receiver = null;
11092 r.curApp = null;
11093 app.curReceiver = null;
11094 }
11095 }
11096
11097 }
11098
Jeff Brown4d94a762010-09-23 11:33:28 -070011099 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011100 Intent intent, int resultCode, String data, Bundle extras,
11101 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011102 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011103 if (app != null && app.thread != null) {
11104 // If we have an app thread, do the call through that so it is
11105 // correctly ordered with other one-way calls.
11106 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011107 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011108 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011109 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 }
11111 }
11112
Jeff Brown4d94a762010-09-23 11:33:28 -070011113 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 BroadcastFilter filter, boolean ordered) {
11115 boolean skip = false;
11116 if (filter.requiredPermission != null) {
11117 int perm = checkComponentPermission(filter.requiredPermission,
11118 r.callingPid, r.callingUid, -1);
11119 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011120 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011121 + r.intent.toString()
11122 + " from " + r.callerPackage + " (pid="
11123 + r.callingPid + ", uid=" + r.callingUid + ")"
11124 + " requires " + filter.requiredPermission
11125 + " due to registered receiver " + filter);
11126 skip = true;
11127 }
11128 }
11129 if (r.requiredPermission != null) {
11130 int perm = checkComponentPermission(r.requiredPermission,
11131 filter.receiverList.pid, filter.receiverList.uid, -1);
11132 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011133 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 + r.intent.toString()
11135 + " to " + filter.receiverList.app
11136 + " (pid=" + filter.receiverList.pid
11137 + ", uid=" + filter.receiverList.uid + ")"
11138 + " requires " + r.requiredPermission
11139 + " due to sender " + r.callerPackage
11140 + " (uid " + r.callingUid + ")");
11141 skip = true;
11142 }
11143 }
11144
11145 if (!skip) {
11146 // If this is not being sent as an ordered broadcast, then we
11147 // don't want to touch the fields that keep track of the current
11148 // state of ordered broadcasts.
11149 if (ordered) {
11150 r.receiver = filter.receiverList.receiver.asBinder();
11151 r.curFilter = filter;
11152 filter.receiverList.curBroadcast = r;
11153 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011154 if (filter.receiverList.app != null) {
11155 // Bump hosting application to no longer be in background
11156 // scheduling class. Note that we can't do that if there
11157 // isn't an app... but we can only be in that case for
11158 // things that directly call the IActivityManager API, which
11159 // are already core system stuff so don't matter for this.
11160 r.curApp = filter.receiverList.app;
11161 filter.receiverList.app.curReceiver = r;
11162 updateOomAdjLocked();
11163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 }
11165 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011166 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011167 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011168 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011169 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011171 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011172 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011173 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011174 if (ordered) {
11175 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11176 }
11177 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011178 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011179 if (ordered) {
11180 r.receiver = null;
11181 r.curFilter = null;
11182 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011183 if (filter.receiverList.app != null) {
11184 filter.receiverList.app.curReceiver = null;
11185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 }
11187 }
11188 }
11189 }
11190
Dianne Hackborn12527f92009-11-11 17:39:50 -080011191 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11192 if (r.callingUid < 0) {
11193 // This was from a registerReceiver() call; ignore it.
11194 return;
11195 }
11196 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11197 MAX_BROADCAST_HISTORY-1);
11198 r.finishTime = SystemClock.uptimeMillis();
11199 mBroadcastHistory[0] = r;
11200 }
11201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 private final void processNextBroadcast(boolean fromMsg) {
11203 synchronized(this) {
11204 BroadcastRecord r;
11205
Joe Onorato8a9b2202010-02-26 18:56:32 -080011206 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011207 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011208 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011209
11210 updateCpuStats();
11211
11212 if (fromMsg) {
11213 mBroadcastsScheduled = false;
11214 }
11215
11216 // First, deliver any non-serialized broadcasts right away.
11217 while (mParallelBroadcasts.size() > 0) {
11218 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011219 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011221 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011222 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011223 for (int i=0; i<N; i++) {
11224 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011225 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011226 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011228 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011229 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011230 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011231 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011232 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 }
11234
11235 // Now take care of the next serialized one...
11236
11237 // If we are waiting for a process to come up to handle the next
11238 // broadcast, then do nothing at this point. Just in case, we
11239 // check that the process we're waiting for still exists.
11240 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011241 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011242 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011243 + mPendingBroadcast.curApp);
11244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245
11246 boolean isDead;
11247 synchronized (mPidsSelfLocked) {
11248 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11249 }
11250 if (!isDead) {
11251 // It's still alive, so keep waiting
11252 return;
11253 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011254 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011255 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011256 mPendingBroadcast.state = BroadcastRecord.IDLE;
11257 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 mPendingBroadcast = null;
11259 }
11260 }
11261
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011262 boolean looped = false;
11263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 do {
11265 if (mOrderedBroadcasts.size() == 0) {
11266 // No more broadcasts pending, so all done!
11267 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011268 if (looped) {
11269 // If we had finished the last ordered broadcast, then
11270 // make sure all processes have correct oom and sched
11271 // adjustments.
11272 updateOomAdjLocked();
11273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 return;
11275 }
11276 r = mOrderedBroadcasts.get(0);
11277 boolean forceReceive = false;
11278
11279 // Ensure that even if something goes awry with the timeout
11280 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011281 // and continue to make progress.
11282 //
11283 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011284 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011285 // one time heavy lifting after system upgrades and can take
11286 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011287 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011288 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011289 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011290 if ((numReceivers > 0) &&
11291 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011292 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011293 + " now=" + now
11294 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011295 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011296 + " intent=" + r.intent
11297 + " numReceivers=" + numReceivers
11298 + " nextReceiver=" + r.nextReceiver
11299 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011300 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011301 forceReceive = true;
11302 r.state = BroadcastRecord.IDLE;
11303 }
11304 }
11305
11306 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011307 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011308 "processNextBroadcast() called when not idle (state="
11309 + r.state + ")");
11310 return;
11311 }
11312
11313 if (r.receivers == null || r.nextReceiver >= numReceivers
11314 || r.resultAbort || forceReceive) {
11315 // No more receivers for this broadcast! Send the final
11316 // result if requested...
11317 if (r.resultTo != null) {
11318 try {
11319 if (DEBUG_BROADCAST) {
11320 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011321 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 + " seq=" + seq + " app=" + r.callerApp);
11323 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011324 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011325 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011326 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011327 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011328 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 }
11330 }
11331
Joe Onorato8a9b2202010-02-26 18:56:32 -080011332 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011333 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334
Joe Onorato8a9b2202010-02-26 18:56:32 -080011335 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011336 + r);
11337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011338 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011339 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011340 mOrderedBroadcasts.remove(0);
11341 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011342 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011343 continue;
11344 }
11345 } while (r == null);
11346
11347 // Get the next receiver...
11348 int recIdx = r.nextReceiver++;
11349
11350 // Keep track of when this receiver started, and make sure there
11351 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011352 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011353 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011354 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011355
Joe Onorato8a9b2202010-02-26 18:56:32 -080011356 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011357 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011358 }
11359 if (! mPendingBroadcastTimeoutMessage) {
11360 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011361 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011362 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11363 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 }
11365
11366 Object nextReceiver = r.receivers.get(recIdx);
11367 if (nextReceiver instanceof BroadcastFilter) {
11368 // Simple case: this is a registered receiver who gets
11369 // a direct call.
11370 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011371 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011372 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011373 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011374 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011375 if (r.receiver == null || !r.ordered) {
11376 // The receiver has already finished, so schedule to
11377 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011378 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11379 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011380 r.state = BroadcastRecord.IDLE;
11381 scheduleBroadcastsLocked();
11382 }
11383 return;
11384 }
11385
11386 // Hard case: need to instantiate the receiver, possibly
11387 // starting its application process to host it.
11388
11389 ResolveInfo info =
11390 (ResolveInfo)nextReceiver;
11391
11392 boolean skip = false;
11393 int perm = checkComponentPermission(info.activityInfo.permission,
11394 r.callingPid, r.callingUid,
11395 info.activityInfo.exported
11396 ? -1 : info.activityInfo.applicationInfo.uid);
11397 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011398 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 + r.intent.toString()
11400 + " from " + r.callerPackage + " (pid=" + r.callingPid
11401 + ", uid=" + r.callingUid + ")"
11402 + " requires " + info.activityInfo.permission
11403 + " due to receiver " + info.activityInfo.packageName
11404 + "/" + info.activityInfo.name);
11405 skip = true;
11406 }
11407 if (r.callingUid != Process.SYSTEM_UID &&
11408 r.requiredPermission != null) {
11409 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011410 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011411 checkPermission(r.requiredPermission,
11412 info.activityInfo.applicationInfo.packageName);
11413 } catch (RemoteException e) {
11414 perm = PackageManager.PERMISSION_DENIED;
11415 }
11416 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011417 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 + r.intent + " to "
11419 + info.activityInfo.applicationInfo.packageName
11420 + " requires " + r.requiredPermission
11421 + " due to sender " + r.callerPackage
11422 + " (uid " + r.callingUid + ")");
11423 skip = true;
11424 }
11425 }
11426 if (r.curApp != null && r.curApp.crashing) {
11427 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011428 if (DEBUG_BROADCAST) Slog.v(TAG,
11429 "Skipping deliver ordered " + r + " to " + r.curApp
11430 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011431 skip = true;
11432 }
11433
11434 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011435 if (DEBUG_BROADCAST) Slog.v(TAG,
11436 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011437 r.receiver = null;
11438 r.curFilter = null;
11439 r.state = BroadcastRecord.IDLE;
11440 scheduleBroadcastsLocked();
11441 return;
11442 }
11443
11444 r.state = BroadcastRecord.APP_RECEIVE;
11445 String targetProcess = info.activityInfo.processName;
11446 r.curComponent = new ComponentName(
11447 info.activityInfo.applicationInfo.packageName,
11448 info.activityInfo.name);
11449 r.curReceiver = info.activityInfo;
11450
11451 // Is this receiver's application already running?
11452 ProcessRecord app = getProcessRecordLocked(targetProcess,
11453 info.activityInfo.applicationInfo.uid);
11454 if (app != null && app.thread != null) {
11455 try {
11456 processCurBroadcastLocked(r, app);
11457 return;
11458 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011459 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011460 + r.curComponent, e);
11461 }
11462
11463 // If a dead object exception was thrown -- fall through to
11464 // restart the application.
11465 }
11466
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011467 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011468 if (DEBUG_BROADCAST) Slog.v(TAG,
11469 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 if ((r.curApp=startProcessLocked(targetProcess,
11471 info.activityInfo.applicationInfo, true,
11472 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011473 "broadcast", r.curComponent,
11474 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11475 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011476 // Ah, this recipient is unavailable. Finish it if necessary,
11477 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011478 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011479 + info.activityInfo.applicationInfo.packageName + "/"
11480 + info.activityInfo.applicationInfo.uid + " for broadcast "
11481 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011482 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011483 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11484 r.resultExtras, r.resultAbort, true);
11485 scheduleBroadcastsLocked();
11486 r.state = BroadcastRecord.IDLE;
11487 return;
11488 }
11489
11490 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011491 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011492 }
11493 }
11494
11495 // =========================================================
11496 // INSTRUMENTATION
11497 // =========================================================
11498
11499 public boolean startInstrumentation(ComponentName className,
11500 String profileFile, int flags, Bundle arguments,
11501 IInstrumentationWatcher watcher) {
11502 // Refuse possible leaked file descriptors
11503 if (arguments != null && arguments.hasFileDescriptors()) {
11504 throw new IllegalArgumentException("File descriptors passed in Bundle");
11505 }
11506
11507 synchronized(this) {
11508 InstrumentationInfo ii = null;
11509 ApplicationInfo ai = null;
11510 try {
11511 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011512 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011514 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011515 } catch (PackageManager.NameNotFoundException e) {
11516 }
11517 if (ii == null) {
11518 reportStartInstrumentationFailure(watcher, className,
11519 "Unable to find instrumentation info for: " + className);
11520 return false;
11521 }
11522 if (ai == null) {
11523 reportStartInstrumentationFailure(watcher, className,
11524 "Unable to find instrumentation target package: " + ii.targetPackage);
11525 return false;
11526 }
11527
11528 int match = mContext.getPackageManager().checkSignatures(
11529 ii.targetPackage, ii.packageName);
11530 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11531 String msg = "Permission Denial: starting instrumentation "
11532 + className + " from pid="
11533 + Binder.getCallingPid()
11534 + ", uid=" + Binder.getCallingPid()
11535 + " not allowed because package " + ii.packageName
11536 + " does not have a signature matching the target "
11537 + ii.targetPackage;
11538 reportStartInstrumentationFailure(watcher, className, msg);
11539 throw new SecurityException(msg);
11540 }
11541
11542 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011543 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544 ProcessRecord app = addAppLocked(ai);
11545 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011546 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547 app.instrumentationProfileFile = profileFile;
11548 app.instrumentationArguments = arguments;
11549 app.instrumentationWatcher = watcher;
11550 app.instrumentationResultClass = className;
11551 Binder.restoreCallingIdentity(origId);
11552 }
11553
11554 return true;
11555 }
11556
11557 /**
11558 * Report errors that occur while attempting to start Instrumentation. Always writes the
11559 * error to the logs, but if somebody is watching, send the report there too. This enables
11560 * the "am" command to report errors with more information.
11561 *
11562 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11563 * @param cn The component name of the instrumentation.
11564 * @param report The error report.
11565 */
11566 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11567 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011568 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011569 try {
11570 if (watcher != null) {
11571 Bundle results = new Bundle();
11572 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11573 results.putString("Error", report);
11574 watcher.instrumentationStatus(cn, -1, results);
11575 }
11576 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011577 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 }
11579 }
11580
11581 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11582 if (app.instrumentationWatcher != null) {
11583 try {
11584 // NOTE: IInstrumentationWatcher *must* be oneway here
11585 app.instrumentationWatcher.instrumentationFinished(
11586 app.instrumentationClass,
11587 resultCode,
11588 results);
11589 } catch (RemoteException e) {
11590 }
11591 }
11592 app.instrumentationWatcher = null;
11593 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011594 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011595 app.instrumentationProfileFile = null;
11596 app.instrumentationArguments = null;
11597
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011598 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599 }
11600
11601 public void finishInstrumentation(IApplicationThread target,
11602 int resultCode, Bundle results) {
11603 // Refuse possible leaked file descriptors
11604 if (results != null && results.hasFileDescriptors()) {
11605 throw new IllegalArgumentException("File descriptors passed in Intent");
11606 }
11607
11608 synchronized(this) {
11609 ProcessRecord app = getRecordForAppLocked(target);
11610 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011611 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 return;
11613 }
11614 final long origId = Binder.clearCallingIdentity();
11615 finishInstrumentationLocked(app, resultCode, results);
11616 Binder.restoreCallingIdentity(origId);
11617 }
11618 }
11619
11620 // =========================================================
11621 // CONFIGURATION
11622 // =========================================================
11623
11624 public ConfigurationInfo getDeviceConfigurationInfo() {
11625 ConfigurationInfo config = new ConfigurationInfo();
11626 synchronized (this) {
11627 config.reqTouchScreen = mConfiguration.touchscreen;
11628 config.reqKeyboardType = mConfiguration.keyboard;
11629 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011630 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11631 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11633 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011634 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11635 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11637 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011638 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 }
11640 return config;
11641 }
11642
11643 public Configuration getConfiguration() {
11644 Configuration ci;
11645 synchronized(this) {
11646 ci = new Configuration(mConfiguration);
11647 }
11648 return ci;
11649 }
11650
11651 public void updateConfiguration(Configuration values) {
11652 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11653 "updateConfiguration()");
11654
11655 synchronized(this) {
11656 if (values == null && mWindowManager != null) {
11657 // sentinel: fetch the current configuration from the window manager
11658 values = mWindowManager.computeNewConfiguration();
11659 }
11660
11661 final long origId = Binder.clearCallingIdentity();
11662 updateConfigurationLocked(values, null);
11663 Binder.restoreCallingIdentity(origId);
11664 }
11665 }
11666
11667 /**
11668 * Do either or both things: (1) change the current configuration, and (2)
11669 * make sure the given activity is running with the (now) current
11670 * configuration. Returns true if the activity has been left running, or
11671 * false if <var>starting</var> is being destroyed to match the new
11672 * configuration.
11673 */
11674 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011675 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676 int changes = 0;
11677
11678 boolean kept = true;
11679
11680 if (values != null) {
11681 Configuration newConfig = new Configuration(mConfiguration);
11682 changes = newConfig.updateFrom(values);
11683 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011684 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011685 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011686 }
11687
Doug Zongker2bec3d42009-12-04 12:52:44 -080011688 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689
11690 if (values.locale != null) {
11691 saveLocaleLocked(values.locale,
11692 !values.locale.equals(mConfiguration.locale),
11693 values.userSetLocale);
11694 }
11695
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011696 mConfigurationSeq++;
11697 if (mConfigurationSeq <= 0) {
11698 mConfigurationSeq = 1;
11699 }
11700 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011701 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011702 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011703
11704 AttributeCache ac = AttributeCache.instance();
11705 if (ac != null) {
11706 ac.updateConfiguration(mConfiguration);
11707 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011708
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011709 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11710 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11711 msg.obj = new Configuration(mConfiguration);
11712 mHandler.sendMessage(msg);
11713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011714
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011715 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11716 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011717 try {
11718 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011719 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011720 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011721 app.thread.scheduleConfigurationChanged(mConfiguration);
11722 }
11723 } catch (Exception e) {
11724 }
11725 }
11726 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011727 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11728 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011729 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11730 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011731 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11732 broadcastIntentLocked(null, null,
11733 new Intent(Intent.ACTION_LOCALE_CHANGED),
11734 null, null, 0, null, null,
11735 null, false, false, MY_PID, Process.SYSTEM_UID);
11736 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 }
11738 }
11739
11740 if (changes != 0 && starting == null) {
11741 // If the configuration changed, and the caller is not already
11742 // in the process of starting an activity, then find the top
11743 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011744 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011745 }
11746
11747 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011748 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011749 if (kept) {
11750 // If this didn't result in the starting activity being
11751 // destroyed, then we need to make sure at this point that all
11752 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011753 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011754 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011755 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011756 }
11757 }
11758
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011759 if (values != null && mWindowManager != null) {
11760 mWindowManager.setNewConfiguration(mConfiguration);
11761 }
11762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 return kept;
11764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011765
11766 /**
11767 * Save the locale. You must be inside a synchronized (this) block.
11768 */
11769 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11770 if(isDiff) {
11771 SystemProperties.set("user.language", l.getLanguage());
11772 SystemProperties.set("user.region", l.getCountry());
11773 }
11774
11775 if(isPersist) {
11776 SystemProperties.set("persist.sys.language", l.getLanguage());
11777 SystemProperties.set("persist.sys.country", l.getCountry());
11778 SystemProperties.set("persist.sys.localevar", l.getVariant());
11779 }
11780 }
11781
11782 // =========================================================
11783 // LIFETIME MANAGEMENT
11784 // =========================================================
11785
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011786 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11787 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011788 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011789 // This adjustment has already been computed. If we are calling
11790 // from the top, we may have already computed our adjustment with
11791 // an earlier hidden adjustment that isn't really for us... if
11792 // so, use the new hidden adjustment.
11793 if (!recursed && app.hidden) {
11794 app.curAdj = hiddenAdj;
11795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 return app.curAdj;
11797 }
11798
11799 if (app.thread == null) {
11800 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011801 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 return (app.curAdj=EMPTY_APP_ADJ);
11803 }
11804
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011805 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11806 // The max adjustment doesn't allow this app to be anything
11807 // below foreground, so it is not worth doing work for it.
11808 app.adjType = "fixed";
11809 app.adjSeq = mAdjSeq;
11810 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011811 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011812 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11813 return (app.curAdj=app.maxAdj);
11814 }
11815
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011816 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011817 app.adjSource = null;
11818 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011819 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011820 app.empty = false;
11821 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011822
The Android Open Source Project4df24232009-03-05 14:34:35 -080011823 // Determine the importance of the process, starting with most
11824 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011825 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011826 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011827 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011828 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011829 // The last app on the list is the foreground app.
11830 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011831 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011832 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011833 } else if (app.instrumentationClass != null) {
11834 // Don't want to kill running instrumentation.
11835 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011836 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011837 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011838 } else if (app.curReceiver != null ||
11839 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11840 // An app that is currently receiving a broadcast also
11841 // counts as being in the foreground.
11842 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011843 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011844 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011845 } else if (app.executingServices.size() > 0) {
11846 // An app that is currently executing a service callback also
11847 // counts as being in the foreground.
11848 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011849 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011850 app.adjType = "exec-service";
11851 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011852 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011853 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011854 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011855 app.adjType = "foreground-service";
11856 } else if (app.forcingToForeground != null) {
11857 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011858 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011859 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011860 app.adjType = "force-foreground";
11861 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011862 } else if (app == mHeavyWeightProcess) {
11863 // We don't want to kill the current heavy-weight process.
11864 adj = HEAVY_WEIGHT_APP_ADJ;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011865 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011866 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011867 } else if (app == mHomeProcess) {
11868 // This process is hosting what we currently consider to be the
11869 // home app, so we don't want to let it go into the background.
11870 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011871 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011872 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011873 } else if ((N=app.activities.size()) != 0) {
11874 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011875 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011877 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011878 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011879 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011880 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011881 ActivityRecord r = app.activities.get(j);
11882 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011883 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011884 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011885 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011886 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011887 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011888 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011889 } else if (r.state == ActivityState.PAUSING
11890 || r.state == ActivityState.PAUSED
11891 || r.state == ActivityState.STOPPING) {
11892 adj = PERCEPTIBLE_APP_ADJ;
11893 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 }
11895 }
11896 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011897 // A very not-needed process. If this is lower in the lru list,
11898 // we will push it in to the empty bucket.
11899 app.hidden = true;
11900 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011901 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011902 adj = hiddenAdj;
11903 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011904 }
11905
Joe Onorato8a9b2202010-02-26 18:56:32 -080011906 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011907
The Android Open Source Project4df24232009-03-05 14:34:35 -080011908 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 // there are applications dependent on our services or providers, but
11910 // this gives us a baseline and makes sure we don't get into an
11911 // infinite recursion.
11912 app.adjSeq = mAdjSeq;
11913 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011914
Christopher Tate6fa95972009-06-05 18:43:55 -070011915 if (mBackupTarget != null && app == mBackupTarget.app) {
11916 // If possible we want to avoid killing apps while they're being backed up
11917 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011918 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011919 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011920 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011921 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011922 }
11923 }
11924
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011925 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11926 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011927 final long now = SystemClock.uptimeMillis();
11928 // This process is more important if the top activity is
11929 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011930 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011931 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011932 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011933 if (s.startRequested) {
11934 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11935 // This service has seen some activity within
11936 // recent memory, so we will keep its process ahead
11937 // of the background processes.
11938 if (adj > SECONDARY_SERVER_ADJ) {
11939 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011940 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011941 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011942 }
11943 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011944 // If we have let the service slide into the background
11945 // state, still have some text describing what it is doing
11946 // even though the service no longer has an impact.
11947 if (adj > SECONDARY_SERVER_ADJ) {
11948 app.adjType = "started-bg-services";
11949 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011950 // Don't kill this process because it is doing work; it
11951 // has said it is doing work.
11952 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011953 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011954 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11955 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011956 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011957 = s.connections.values().iterator();
11958 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011959 ArrayList<ConnectionRecord> clist = kt.next();
11960 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11961 // XXX should compute this based on the max of
11962 // all connected clients.
11963 ConnectionRecord cr = clist.get(i);
11964 if (cr.binding.client == app) {
11965 // Binding to ourself is not interesting.
11966 continue;
11967 }
11968 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11969 ProcessRecord client = cr.binding.client;
11970 int myHiddenAdj = hiddenAdj;
11971 if (myHiddenAdj > client.hiddenAdj) {
11972 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11973 myHiddenAdj = client.hiddenAdj;
11974 } else {
11975 myHiddenAdj = VISIBLE_APP_ADJ;
11976 }
11977 }
11978 int clientAdj = computeOomAdjLocked(
11979 client, myHiddenAdj, TOP_APP, true);
11980 if (adj > clientAdj) {
11981 adj = clientAdj >= VISIBLE_APP_ADJ
11982 ? clientAdj : VISIBLE_APP_ADJ;
11983 if (!client.hidden) {
11984 app.hidden = false;
11985 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011986 if (client.keeping) {
11987 app.keeping = true;
11988 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011989 app.adjType = "service";
11990 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11991 .REASON_SERVICE_IN_USE;
11992 app.adjSource = cr.binding.client;
11993 app.adjTarget = s.name;
11994 }
11995 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11996 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11997 schedGroup = Process.THREAD_GROUP_DEFAULT;
11998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011999 }
12000 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012001 ActivityRecord a = cr.activity;
12002 //if (a != null) {
12003 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12004 //}
12005 if (a != null && adj > FOREGROUND_APP_ADJ &&
12006 (a.state == ActivityState.RESUMED
12007 || a.state == ActivityState.PAUSING)) {
12008 adj = FOREGROUND_APP_ADJ;
12009 schedGroup = Process.THREAD_GROUP_DEFAULT;
12010 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012011 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012012 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12013 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012014 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012015 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 }
12018 }
12019 }
12020 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012021
Dianne Hackborn287952c2010-09-22 22:34:31 -070012022 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012023 // would like to avoid killing it unless it would prevent the current
12024 // application from running. By default we put the process in
12025 // with the rest of the background processes; as we scan through
12026 // its services we may bump it up from there.
12027 if (adj > hiddenAdj) {
12028 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012029 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012030 app.adjType = "bg-services";
12031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012032 }
12033
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012034 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12035 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012036 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012037 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12038 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012039 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012040 if (cpr.clients.size() != 0) {
12041 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12042 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12043 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012044 if (client == app) {
12045 // Being our own client is not interesting.
12046 continue;
12047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012048 int myHiddenAdj = hiddenAdj;
12049 if (myHiddenAdj > client.hiddenAdj) {
12050 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12051 myHiddenAdj = client.hiddenAdj;
12052 } else {
12053 myHiddenAdj = FOREGROUND_APP_ADJ;
12054 }
12055 }
12056 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012057 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 if (adj > clientAdj) {
12059 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012060 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012061 if (!client.hidden) {
12062 app.hidden = false;
12063 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012064 if (client.keeping) {
12065 app.keeping = true;
12066 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012067 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012068 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12069 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012070 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012071 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012072 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012073 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12074 schedGroup = Process.THREAD_GROUP_DEFAULT;
12075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012076 }
12077 }
12078 // If the provider has external (non-framework) process
12079 // dependencies, ensure that its adjustment is at least
12080 // FOREGROUND_APP_ADJ.
12081 if (cpr.externals != 0) {
12082 if (adj > FOREGROUND_APP_ADJ) {
12083 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012084 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012085 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012086 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012087 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012088 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 }
12090 }
12091 }
12092 }
12093
12094 app.curRawAdj = adj;
12095
Joe Onorato8a9b2202010-02-26 18:56:32 -080012096 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012097 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12098 if (adj > app.maxAdj) {
12099 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012100 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012101 schedGroup = Process.THREAD_GROUP_DEFAULT;
12102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012103 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012104 if (adj < HIDDEN_APP_MIN_ADJ) {
12105 app.keeping = true;
12106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012107
12108 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012109 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012111 return adj;
12112 }
12113
12114 /**
12115 * Ask a given process to GC right now.
12116 */
12117 final void performAppGcLocked(ProcessRecord app) {
12118 try {
12119 app.lastRequestedGc = SystemClock.uptimeMillis();
12120 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012121 if (app.reportLowMemory) {
12122 app.reportLowMemory = false;
12123 app.thread.scheduleLowMemory();
12124 } else {
12125 app.thread.processInBackground();
12126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012127 }
12128 } catch (Exception e) {
12129 // whatever.
12130 }
12131 }
12132
12133 /**
12134 * Returns true if things are idle enough to perform GCs.
12135 */
Josh Bartel7f208742010-02-25 11:01:44 -060012136 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012137 return mParallelBroadcasts.size() == 0
12138 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012139 && (mSleeping || (mMainStack.mResumedActivity != null &&
12140 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012141 }
12142
12143 /**
12144 * Perform GCs on all processes that are waiting for it, but only
12145 * if things are idle.
12146 */
12147 final void performAppGcsLocked() {
12148 final int N = mProcessesToGc.size();
12149 if (N <= 0) {
12150 return;
12151 }
Josh Bartel7f208742010-02-25 11:01:44 -060012152 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 while (mProcessesToGc.size() > 0) {
12154 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012155 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012156 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12157 <= SystemClock.uptimeMillis()) {
12158 // To avoid spamming the system, we will GC processes one
12159 // at a time, waiting a few seconds between each.
12160 performAppGcLocked(proc);
12161 scheduleAppGcsLocked();
12162 return;
12163 } else {
12164 // It hasn't been long enough since we last GCed this
12165 // process... put it in the list to wait for its time.
12166 addProcessToGcListLocked(proc);
12167 break;
12168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012169 }
12170 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012171
12172 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012173 }
12174 }
12175
12176 /**
12177 * If all looks good, perform GCs on all processes waiting for them.
12178 */
12179 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012180 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012181 performAppGcsLocked();
12182 return;
12183 }
12184 // Still not idle, wait some more.
12185 scheduleAppGcsLocked();
12186 }
12187
12188 /**
12189 * Schedule the execution of all pending app GCs.
12190 */
12191 final void scheduleAppGcsLocked() {
12192 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012193
12194 if (mProcessesToGc.size() > 0) {
12195 // Schedule a GC for the time to the next process.
12196 ProcessRecord proc = mProcessesToGc.get(0);
12197 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12198
12199 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12200 long now = SystemClock.uptimeMillis();
12201 if (when < (now+GC_TIMEOUT)) {
12202 when = now + GC_TIMEOUT;
12203 }
12204 mHandler.sendMessageAtTime(msg, when);
12205 }
12206 }
12207
12208 /**
12209 * Add a process to the array of processes waiting to be GCed. Keeps the
12210 * list in sorted order by the last GC time. The process can't already be
12211 * on the list.
12212 */
12213 final void addProcessToGcListLocked(ProcessRecord proc) {
12214 boolean added = false;
12215 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12216 if (mProcessesToGc.get(i).lastRequestedGc <
12217 proc.lastRequestedGc) {
12218 added = true;
12219 mProcessesToGc.add(i+1, proc);
12220 break;
12221 }
12222 }
12223 if (!added) {
12224 mProcessesToGc.add(0, proc);
12225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 }
12227
12228 /**
12229 * Set up to ask a process to GC itself. This will either do it
12230 * immediately, or put it on the list of processes to gc the next
12231 * time things are idle.
12232 */
12233 final void scheduleAppGcLocked(ProcessRecord app) {
12234 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012235 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012236 return;
12237 }
12238 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012239 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012240 scheduleAppGcsLocked();
12241 }
12242 }
12243
Dianne Hackborn287952c2010-09-22 22:34:31 -070012244 final void checkExcessivePowerUsageLocked(boolean doKills) {
12245 updateCpuStatsNow();
12246
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012247 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012248 boolean doWakeKills = doKills;
12249 boolean doCpuKills = doKills;
12250 if (mLastPowerCheckRealtime == 0) {
12251 doWakeKills = false;
12252 }
12253 if (mLastPowerCheckUptime == 0) {
12254 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012255 }
12256 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012257 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012258 }
12259 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012260 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12261 final long curUptime = SystemClock.uptimeMillis();
12262 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12263 mLastPowerCheckRealtime = curRealtime;
12264 mLastPowerCheckUptime = curUptime;
12265 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12266 doWakeKills = false;
12267 }
12268 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12269 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012270 }
12271 int i = mLruProcesses.size();
12272 while (i > 0) {
12273 i--;
12274 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012275 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012276 long wtime;
12277 synchronized (stats) {
12278 wtime = stats.getProcessWakeTime(app.info.uid,
12279 app.pid, curRealtime);
12280 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012281 long wtimeUsed = wtime - app.lastWakeTime;
12282 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12283 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012284 StringBuilder sb = new StringBuilder(128);
12285 sb.append("Wake for ");
12286 app.toShortString(sb);
12287 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012288 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012289 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012290 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012291 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012292 sb.append((wtimeUsed*100)/realtimeSince);
12293 sb.append("%)");
12294 Slog.i(TAG, sb.toString());
12295 sb.setLength(0);
12296 sb.append("CPU for ");
12297 app.toShortString(sb);
12298 sb.append(": over ");
12299 TimeUtils.formatDuration(uptimeSince, sb);
12300 sb.append(" used ");
12301 TimeUtils.formatDuration(cputimeUsed, sb);
12302 sb.append(" (");
12303 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012304 sb.append("%)");
12305 Slog.i(TAG, sb.toString());
12306 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012307 // If a process has held a wake lock for more
12308 // than 50% of the time during this period,
12309 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012310 if (doWakeKills && realtimeSince > 0
12311 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12312 synchronized (stats) {
12313 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12314 realtimeSince, wtimeUsed);
12315 }
12316 Slog.w(TAG, "Excessive wake lock in " + app.processName
12317 + " (pid " + app.pid + "): held " + wtimeUsed
12318 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012319 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12320 app.processName, app.setAdj, "excessive wake lock");
12321 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012322 } else if (doCpuKills && uptimeSince > 0
12323 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12324 synchronized (stats) {
12325 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12326 uptimeSince, cputimeUsed);
12327 }
12328 Slog.w(TAG, "Excessive CPU in " + app.processName
12329 + " (pid " + app.pid + "): used " + cputimeUsed
12330 + " during " + uptimeSince);
12331 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12332 app.processName, app.setAdj, "excessive cpu");
12333 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012334 } else {
12335 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012336 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012337 }
12338 }
12339 }
12340 }
12341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012342 private final boolean updateOomAdjLocked(
12343 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12344 app.hiddenAdj = hiddenAdj;
12345
12346 if (app.thread == null) {
12347 return true;
12348 }
12349
Dianne Hackborn287952c2010-09-22 22:34:31 -070012350 final boolean wasKeeping = app.keeping;
12351
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012352 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012353
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012354 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012355 if (app.curRawAdj != app.setRawAdj) {
12356 if (app.curRawAdj > FOREGROUND_APP_ADJ
12357 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12358 // If this app is transitioning from foreground to
12359 // non-foreground, have it do a gc.
12360 scheduleAppGcLocked(app);
12361 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12362 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12363 // Likewise do a gc when an app is moving in to the
12364 // background (such as a service stopping).
12365 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012366 }
12367
12368 if (wasKeeping && !app.keeping) {
12369 // This app is no longer something we want to keep. Note
12370 // its current wake lock time to later know to kill it if
12371 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012372 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12373 synchronized (stats) {
12374 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12375 app.pid, SystemClock.elapsedRealtime());
12376 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012377 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012378 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012380 app.setRawAdj = app.curRawAdj;
12381 }
12382 if (adj != app.setAdj) {
12383 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012384 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012385 TAG, "Set app " + app.processName +
12386 " oom adj to " + adj);
12387 app.setAdj = adj;
12388 } else {
12389 return false;
12390 }
12391 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012392 if (app.setSchedGroup != app.curSchedGroup) {
12393 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012394 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012395 "Setting process group of " + app.processName
12396 + " to " + app.curSchedGroup);
12397 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012398 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012399 try {
12400 Process.setProcessGroup(app.pid, app.curSchedGroup);
12401 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012402 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012403 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012404 e.printStackTrace();
12405 } finally {
12406 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012407 }
12408 }
12409 if (false) {
12410 if (app.thread != null) {
12411 try {
12412 app.thread.setSchedulingGroup(app.curSchedGroup);
12413 } catch (RemoteException e) {
12414 }
12415 }
12416 }
12417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012418 }
12419
12420 return true;
12421 }
12422
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012423 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012424 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012425 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012426 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012427 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012428 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012429 }
12430 }
12431 return resumedActivity;
12432 }
12433
12434 private final boolean updateOomAdjLocked(ProcessRecord app) {
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 int curAdj = app.curAdj;
12438 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12439 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12440
12441 mAdjSeq++;
12442
12443 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12444 if (res) {
12445 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12446 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12447 if (nowHidden != wasHidden) {
12448 // Changed to/from hidden state, so apps after it in the LRU
12449 // list may also be changed.
12450 updateOomAdjLocked();
12451 }
12452 }
12453 return res;
12454 }
12455
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012456 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012457 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012458 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012459 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12460
12461 if (false) {
12462 RuntimeException e = new RuntimeException();
12463 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012464 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012465 }
12466
12467 mAdjSeq++;
12468
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012469 // Let's determine how many processes we have running vs.
12470 // how many slots we have for background processes; we may want
12471 // to put multiple processes in a slot of there are enough of
12472 // them.
12473 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12474 int factor = (mLruProcesses.size()-4)/numSlots;
12475 if (factor < 1) factor = 1;
12476 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012477 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012479 // First try updating the OOM adjustment for each of the
12480 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012481 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012482 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12483 while (i > 0) {
12484 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012485 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012486 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012487 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012488 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012489 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012490 step++;
12491 if (step >= factor) {
12492 step = 0;
12493 curHiddenAdj++;
12494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012495 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012496 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012497 if (!app.killedBackground) {
12498 numHidden++;
12499 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012500 Slog.i(TAG, "No longer want " + app.processName
12501 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012502 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12503 app.processName, app.setAdj, "too many background");
12504 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012505 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012506 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012507 }
12508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012509 } else {
12510 didOomAdj = false;
12511 }
12512 }
12513
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012514 // If we return false, we will fall back on killing processes to
12515 // have a fixed limit. Do this if a limit has been requested; else
12516 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012517 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12518 }
12519
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012520 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012521 synchronized (this) {
12522 int i;
12523
12524 // First remove any unused application processes whose package
12525 // has been removed.
12526 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12527 final ProcessRecord app = mRemovedProcesses.get(i);
12528 if (app.activities.size() == 0
12529 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012530 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 TAG, "Exiting empty application process "
12532 + app.processName + " ("
12533 + (app.thread != null ? app.thread.asBinder() : null)
12534 + ")\n");
12535 if (app.pid > 0 && app.pid != MY_PID) {
12536 Process.killProcess(app.pid);
12537 } else {
12538 try {
12539 app.thread.scheduleExit();
12540 } catch (Exception e) {
12541 // Ignore exceptions.
12542 }
12543 }
12544 cleanUpApplicationRecordLocked(app, false, -1);
12545 mRemovedProcesses.remove(i);
12546
12547 if (app.persistent) {
12548 if (app.persistent) {
12549 addAppLocked(app.info);
12550 }
12551 }
12552 }
12553 }
12554
12555 // Now try updating the OOM adjustment for each of the
12556 // application processes based on their current state.
12557 // If the setOomAdj() API is not supported, then go with our
12558 // back-up plan...
12559 if (!updateOomAdjLocked()) {
12560
12561 // Count how many processes are running services.
12562 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012563 for (i=mLruProcesses.size()-1; i>=0; i--) {
12564 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012565
12566 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012567 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012568 // Don't count processes holding services against our
12569 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012570 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012571 TAG, "Not trimming app " + app + " with services: "
12572 + app.services);
12573 numServiceProcs++;
12574 }
12575 }
12576
12577 int curMaxProcs = mProcessLimit;
12578 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12579 if (mAlwaysFinishActivities) {
12580 curMaxProcs = 1;
12581 }
12582 curMaxProcs += numServiceProcs;
12583
12584 // Quit as many processes as we can to get down to the desired
12585 // process count. First remove any processes that no longer
12586 // have activites running in them.
12587 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012588 i<mLruProcesses.size()
12589 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012590 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012591 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012592 // Quit an application only if it is not currently
12593 // running any activities.
12594 if (!app.persistent && app.activities.size() == 0
12595 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012596 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012597 TAG, "Exiting empty application process "
12598 + app.processName + " ("
12599 + (app.thread != null ? app.thread.asBinder() : null)
12600 + ")\n");
12601 if (app.pid > 0 && app.pid != MY_PID) {
12602 Process.killProcess(app.pid);
12603 } else {
12604 try {
12605 app.thread.scheduleExit();
12606 } catch (Exception e) {
12607 // Ignore exceptions.
12608 }
12609 }
12610 // todo: For now we assume the application is not buggy
12611 // or evil, and will quit as a result of our request.
12612 // Eventually we need to drive this off of the death
12613 // notification, and kill the process if it takes too long.
12614 cleanUpApplicationRecordLocked(app, false, i);
12615 i--;
12616 }
12617 }
12618
12619 // If we still have too many processes, now from the least
12620 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012621 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012622 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012623 " of " + curMaxProcs + " processes");
12624 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012625 i<mLruProcesses.size()
12626 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012627 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012628 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012629 // Quit the application only if we have a state saved for
12630 // all of its activities.
12631 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012632 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012633 int NUMA = app.activities.size();
12634 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012635 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012636 TAG, "Looking to quit " + app.processName);
12637 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012638 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012639 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012640 TAG, " " + r.intent.getComponent().flattenToShortString()
12641 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12642 canQuit = (r.haveState || !r.stateNotNeeded)
12643 && !r.visible && r.stopped;
12644 }
12645 if (canQuit) {
12646 // Finish all of the activities, and then the app itself.
12647 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012648 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012649 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012650 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012651 }
12652 r.resultTo = null;
12653 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012654 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012655 + app.processName + " ("
12656 + (app.thread != null ? app.thread.asBinder() : null)
12657 + ")\n");
12658 if (app.pid > 0 && app.pid != MY_PID) {
12659 Process.killProcess(app.pid);
12660 } else {
12661 try {
12662 app.thread.scheduleExit();
12663 } catch (Exception e) {
12664 // Ignore exceptions.
12665 }
12666 }
12667 // todo: For now we assume the application is not buggy
12668 // or evil, and will quit as a result of our request.
12669 // Eventually we need to drive this off of the death
12670 // notification, and kill the process if it takes too long.
12671 cleanUpApplicationRecordLocked(app, false, i);
12672 i--;
12673 //dump();
12674 }
12675 }
12676
12677 }
12678
12679 int curMaxActivities = MAX_ACTIVITIES;
12680 if (mAlwaysFinishActivities) {
12681 curMaxActivities = 1;
12682 }
12683
12684 // Finally, if there are too many activities now running, try to
12685 // finish as many as we can to get back down to the limit.
12686 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012687 i<mMainStack.mLRUActivities.size()
12688 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012689 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012690 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012691 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012692
12693 // We can finish this one if we have its icicle saved and
12694 // it is not persistent.
12695 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012696 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012697 final int origSize = mMainStack.mLRUActivities.size();
12698 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012699
12700 // This will remove it from the LRU list, so keep
12701 // our index at the same value. Note that this check to
12702 // see if the size changes is just paranoia -- if
12703 // something unexpected happens, we don't want to end up
12704 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012705 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012706 i--;
12707 }
12708 }
12709 }
12710 }
12711 }
12712
12713 /** This method sends the specified signal to each of the persistent apps */
12714 public void signalPersistentProcesses(int sig) throws RemoteException {
12715 if (sig != Process.SIGNAL_USR1) {
12716 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12717 }
12718
12719 synchronized (this) {
12720 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12721 != PackageManager.PERMISSION_GRANTED) {
12722 throw new SecurityException("Requires permission "
12723 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12724 }
12725
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012726 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12727 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012728 if (r.thread != null && r.persistent) {
12729 Process.sendSignal(r.pid, sig);
12730 }
12731 }
12732 }
12733 }
12734
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012735 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012736 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012737
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012738 try {
12739 synchronized (this) {
12740 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12741 // its own permission.
12742 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12743 != PackageManager.PERMISSION_GRANTED) {
12744 throw new SecurityException("Requires permission "
12745 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012746 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012747
12748 if (start && fd == null) {
12749 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012750 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012751
12752 ProcessRecord proc = null;
12753 try {
12754 int pid = Integer.parseInt(process);
12755 synchronized (mPidsSelfLocked) {
12756 proc = mPidsSelfLocked.get(pid);
12757 }
12758 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012759 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012760
12761 if (proc == null) {
12762 HashMap<String, SparseArray<ProcessRecord>> all
12763 = mProcessNames.getMap();
12764 SparseArray<ProcessRecord> procs = all.get(process);
12765 if (procs != null && procs.size() > 0) {
12766 proc = procs.valueAt(0);
12767 }
12768 }
12769
12770 if (proc == null || proc.thread == null) {
12771 throw new IllegalArgumentException("Unknown process: " + process);
12772 }
12773
12774 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12775 if (isSecure) {
12776 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12777 throw new SecurityException("Process not debuggable: " + proc);
12778 }
12779 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012780
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012781 proc.thread.profilerControl(start, path, fd);
12782 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012783 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012784 }
12785 } catch (RemoteException e) {
12786 throw new IllegalStateException("Process disappeared");
12787 } finally {
12788 if (fd != null) {
12789 try {
12790 fd.close();
12791 } catch (IOException e) {
12792 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012793 }
12794 }
12795 }
Andy McFadden824c5102010-07-09 16:26:57 -070012796
12797 public boolean dumpHeap(String process, boolean managed,
12798 String path, ParcelFileDescriptor fd) throws RemoteException {
12799
12800 try {
12801 synchronized (this) {
12802 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12803 // its own permission (same as profileControl).
12804 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12805 != PackageManager.PERMISSION_GRANTED) {
12806 throw new SecurityException("Requires permission "
12807 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12808 }
12809
12810 if (fd == null) {
12811 throw new IllegalArgumentException("null fd");
12812 }
12813
12814 ProcessRecord proc = null;
12815 try {
12816 int pid = Integer.parseInt(process);
12817 synchronized (mPidsSelfLocked) {
12818 proc = mPidsSelfLocked.get(pid);
12819 }
12820 } catch (NumberFormatException e) {
12821 }
12822
12823 if (proc == null) {
12824 HashMap<String, SparseArray<ProcessRecord>> all
12825 = mProcessNames.getMap();
12826 SparseArray<ProcessRecord> procs = all.get(process);
12827 if (procs != null && procs.size() > 0) {
12828 proc = procs.valueAt(0);
12829 }
12830 }
12831
12832 if (proc == null || proc.thread == null) {
12833 throw new IllegalArgumentException("Unknown process: " + process);
12834 }
12835
12836 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12837 if (isSecure) {
12838 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12839 throw new SecurityException("Process not debuggable: " + proc);
12840 }
12841 }
12842
12843 proc.thread.dumpHeap(managed, path, fd);
12844 fd = null;
12845 return true;
12846 }
12847 } catch (RemoteException e) {
12848 throw new IllegalStateException("Process disappeared");
12849 } finally {
12850 if (fd != null) {
12851 try {
12852 fd.close();
12853 } catch (IOException e) {
12854 }
12855 }
12856 }
12857 }
12858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012859 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12860 public void monitor() {
12861 synchronized (this) { }
12862 }
12863}