blob: c7c3fb213309127a3bd6be8430eeeb17a517ad9d [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;
132import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700133import java.util.Collections;
134import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135import java.util.HashMap;
136import java.util.HashSet;
137import java.util.Iterator;
138import java.util.List;
139import java.util.Locale;
140import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700141import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700142import java.util.concurrent.atomic.AtomicBoolean;
143import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700145public final class ActivityManagerService extends ActivityManagerNative
146 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 static final String TAG = "ActivityManager";
148 static final boolean DEBUG = false;
149 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
150 static final boolean DEBUG_SWITCH = localLOGV || false;
151 static final boolean DEBUG_TASKS = localLOGV || false;
152 static final boolean DEBUG_PAUSE = localLOGV || false;
153 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
154 static final boolean DEBUG_TRANSITION = localLOGV || false;
155 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700156 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700158 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG_VISBILITY = localLOGV || false;
160 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700161 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800162 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700164 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700165 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700166 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700167 static final boolean DEBUG_POWER = localLOGV || false;
168 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 static final boolean VALIDATE_TOKENS = false;
170 static final boolean SHOW_ACTIVITY_START_TIME = true;
171
172 // Control over CPU and battery monitoring.
173 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
174 static final boolean MONITOR_CPU_USAGE = true;
175 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
176 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
177 static final boolean MONITOR_THREAD_CPU_USAGE = false;
178
Dianne Hackborn1655be42009-05-08 14:29:01 -0700179 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700180 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 private static final String SYSTEM_SECURE = "ro.secure";
183
184 // This is the maximum number of application processes we would like
185 // to have running. Due to the asynchronous nature of things, we can
186 // temporarily go beyond this limit.
187 static final int MAX_PROCESSES = 2;
188
189 // Set to false to leave processes running indefinitely, relying on
190 // the kernel killing them as resources are required.
191 static final boolean ENFORCE_PROCESS_LIMIT = false;
192
193 // This is the maximum number of activities that we would like to have
194 // running at a given time.
195 static final int MAX_ACTIVITIES = 20;
196
197 // Maximum number of recent tasks that we can remember.
198 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700199
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700200 // Amount of time after a call to stopAppSwitches() during which we will
201 // prevent further untrusted switches from happening.
202 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203
204 // How long we wait for a launched process to attach to the activity manager
205 // before we decide it's never going to come up for real.
206 static final int PROC_START_TIMEOUT = 10*1000;
207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 // How long to wait after going idle before forcing apps to GC.
209 static final int GC_TIMEOUT = 5*1000;
210
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700211 // The minimum amount of time between successive GC requests for a process.
212 static final int GC_MIN_INTERVAL = 60*1000;
213
Dianne Hackborn287952c2010-09-22 22:34:31 -0700214 // The rate at which we check for apps using excessive power -- 15 mins.
215 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
216
217 // The minimum sample duration we will allow before deciding we have
218 // enough data on wake locks to start killing things.
219 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
220
221 // The minimum sample duration we will allow before deciding we have
222 // enough data on CPU usage to start killing things.
223 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // How long we allow a receiver to run before giving up on it.
226 static final int BROADCAST_TIMEOUT = 10*1000;
227
228 // How long we wait for a service to finish executing.
229 static final int SERVICE_TIMEOUT = 20*1000;
230
231 // How long a service needs to be running until restarting its process
232 // is no longer considered to be a relaunch of the service.
233 static final int SERVICE_RESTART_DURATION = 5*1000;
234
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700235 // How long a service needs to be running until it will start back at
236 // SERVICE_RESTART_DURATION after being killed.
237 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
238
239 // Multiplying factor to increase restart duration time by, for each time
240 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
241 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
242
243 // The minimum amount of time between restarting services that we allow.
244 // That is, when multiple services are restarting, we won't allow each
245 // to restart less than this amount of time from the last one.
246 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 // Maximum amount of time for there to be no activity on a service before
249 // we consider it non-essential and allow its process to go on the
250 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700251 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
253 // How long we wait until we timeout on key dispatching.
254 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
255
256 // The minimum time we allow between crashes, for us to consider this
257 // application to be bad and stop and its services and reject broadcasts.
258 static final int MIN_CRASH_INTERVAL = 60*1000;
259
260 // How long we wait until we timeout on key dispatching during instrumentation.
261 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
262
263 // OOM adjustments for processes in various states:
264
265 // This is a process without anything currently running in it. Definitely
266 // the first to go! Value set in system/rootdir/init.rc on startup.
267 // This value is initalized in the constructor, careful when refering to
268 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270
271 // This is a process only hosting activities that are not visible,
272 // so it can be killed without any disruption. Value set in
273 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800274 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 static int HIDDEN_APP_MIN_ADJ;
276
The Android Open Source Project4df24232009-03-05 14:34:35 -0800277 // This is a process holding the home application -- we want to try
278 // avoiding killing it, even if it would normally be in the background,
279 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800280 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800281
Christopher Tate6fa95972009-06-05 18:43:55 -0700282 // This is a process currently hosting a backup operation. Killing it
283 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 // This is a process holding a secondary server -- killing it will not
287 // have much of an impact as far as the user is concerned. Value set in
288 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700291 // This is a process with a heavy-weight application. It is in the
292 // background, but we want to try to avoid killing it. Value set in
293 // system/rootdir/init.rc on startup.
294 static final int HEAVY_WEIGHT_APP_ADJ;
295
296 // This is a process only hosting components that are perceptible to the
297 // user, and we really want to avoid killing them, but they are not
298 // immediately visible. An example is background music playback. Value set in
299 // system/rootdir/init.rc on startup.
300 static final int PERCEPTIBLE_APP_ADJ;
301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 // This is a process only hosting activities that are visible to the
303 // user, so we'd prefer they don't disappear. Value set in
304 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800305 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306
307 // This is the process running the current foreground app. We'd really
308 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800309 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310
311 // This is a process running a core server, such as telephony. Definitely
312 // don't want to kill it, but doing so is not completely fatal.
313 static final int CORE_SERVER_ADJ = -12;
314
315 // The system process runs at the default adjustment.
316 static final int SYSTEM_ADJ = -16;
317
318 // Memory pages are 4K.
319 static final int PAGE_SIZE = 4*1024;
320
321 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800322 static final int EMPTY_APP_MEM;
323 static final int HIDDEN_APP_MEM;
324 static final int HOME_APP_MEM;
325 static final int BACKUP_APP_MEM;
326 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700327 static final int HEAVY_WEIGHT_APP_MEM;
328 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800329 static final int VISIBLE_APP_MEM;
330 static final int FOREGROUND_APP_MEM;
331
332 // The minimum number of hidden apps we want to be able to keep around,
333 // without empty apps being able to push them out of memory.
334 static final int MIN_HIDDEN_APPS = 2;
335
Dianne Hackborn8633e682010-04-22 16:03:41 -0700336 // The maximum number of hidden processes we will keep around before
337 // killing them; this is just a control to not let us go too crazy with
338 // keeping around processes on devices with large amounts of RAM.
339 static final int MAX_HIDDEN_APPS = 15;
340
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800341 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700342 // been idle for less than 15 seconds.
343 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800344
345 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700346 // been idle for less than 120 seconds.
347 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800348
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700349 static int getIntProp(String name, boolean allowZero) {
350 String str = SystemProperties.get(name);
351 if (str == null) {
352 throw new IllegalArgumentException("Property not defined: " + name);
353 }
354 int val = Integer.valueOf(str);
355 if (val == 0 && !allowZero) {
356 throw new IllegalArgumentException("Property must not be zero: " + name);
357 }
358 return val;
359 }
360
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800361 static {
362 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700363 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
364 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
365 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
366 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
367 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
368 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
369 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
370 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
371 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
372 // These days we use the last empty slot for hidden apps as well.
373 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
374 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
375 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
376 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
377 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
378 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
379 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
380 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
381 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
382 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
Dan Egnor42471dd2010-01-07 17:25:22 -0800385 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386
387 static final String[] EMPTY_STRING_ARRAY = new String[0];
388
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700389 public ActivityStack mMainStack;
390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700392 * Description of a request to start a new activity, which has been held
393 * due to app switches being disabled.
394 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700395 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700396 ActivityRecord r;
397 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700398 Uri[] grantedUriPermissions;
399 int grantedMode;
400 boolean onlyIfNeeded;
401 }
402
403 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
404 = new ArrayList<PendingActivityLaunch>();
405
406 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 * List of all active broadcasts that are to be executed immediately
408 * (without waiting for another broadcast to finish). Currently this only
409 * contains broadcasts to registered receivers, to avoid spinning up
410 * a bunch of processes to execute IntentReceiver components.
411 */
412 final ArrayList<BroadcastRecord> mParallelBroadcasts
413 = new ArrayList<BroadcastRecord>();
414
415 /**
416 * List of all active broadcasts that are to be executed one at a time.
417 * The object at the top of the list is the currently activity broadcasts;
418 * those after it are waiting for the top to finish..
419 */
420 final ArrayList<BroadcastRecord> mOrderedBroadcasts
421 = new ArrayList<BroadcastRecord>();
422
423 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800424 * Historical data of past broadcasts, for debugging.
425 */
426 static final int MAX_BROADCAST_HISTORY = 100;
427 final BroadcastRecord[] mBroadcastHistory
428 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
429
430 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 * Set when we current have a BROADCAST_INTENT_MSG in flight.
432 */
433 boolean mBroadcastsScheduled = false;
434
435 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 * Activity we have told the window manager to have key focus.
437 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700438 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700439 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 * List of intents that were used to start the most recent tasks.
441 */
442 final ArrayList<TaskRecord> mRecentTasks
443 = new ArrayList<TaskRecord>();
444
445 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 * All of the applications we currently have running organized by name.
447 * The keys are strings of the application package name (as
448 * returned by the package manager), and the keys are ApplicationRecord
449 * objects.
450 */
451 final ProcessMap<ProcessRecord> mProcessNames
452 = new ProcessMap<ProcessRecord>();
453
454 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700455 * The currently running heavy-weight process, if any.
456 */
457 ProcessRecord mHeavyWeightProcess = null;
458
459 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 * The last time that various processes have crashed.
461 */
462 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
463
464 /**
465 * Set of applications that we consider to be bad, and will reject
466 * incoming broadcasts from (which the user has no control over).
467 * Processes are added to this set when they have crashed twice within
468 * a minimum amount of time; they are removed from it when they are
469 * later restarted (hopefully due to some user action). The value is the
470 * time it was added to the list.
471 */
472 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
473
474 /**
475 * All of the processes we currently have running organized by pid.
476 * The keys are the pid running the application.
477 *
478 * <p>NOTE: This object is protected by its own lock, NOT the global
479 * activity manager lock!
480 */
481 final SparseArray<ProcessRecord> mPidsSelfLocked
482 = new SparseArray<ProcessRecord>();
483
484 /**
485 * All of the processes that have been forced to be foreground. The key
486 * is the pid of the caller who requested it (we hold a death
487 * link on it).
488 */
489 abstract class ForegroundToken implements IBinder.DeathRecipient {
490 int pid;
491 IBinder token;
492 }
493 final SparseArray<ForegroundToken> mForegroundProcesses
494 = new SparseArray<ForegroundToken>();
495
496 /**
497 * List of records for processes that someone had tried to start before the
498 * system was ready. We don't start them at that point, but ensure they
499 * are started by the time booting is complete.
500 */
501 final ArrayList<ProcessRecord> mProcessesOnHold
502 = new ArrayList<ProcessRecord>();
503
504 /**
505 * List of records for processes that we have started and are waiting
506 * for them to call back. This is really only needed when running in
507 * single processes mode, in which case we do not have a unique pid for
508 * each process.
509 */
510 final ArrayList<ProcessRecord> mStartingProcesses
511 = new ArrayList<ProcessRecord>();
512
513 /**
514 * List of persistent applications that are in the process
515 * of being started.
516 */
517 final ArrayList<ProcessRecord> mPersistentStartingProcesses
518 = new ArrayList<ProcessRecord>();
519
520 /**
521 * Processes that are being forcibly torn down.
522 */
523 final ArrayList<ProcessRecord> mRemovedProcesses
524 = new ArrayList<ProcessRecord>();
525
526 /**
527 * List of running applications, sorted by recent usage.
528 * The first entry in the list is the least recently used.
529 * It contains ApplicationRecord objects. This list does NOT include
530 * any persistent application records (since we never want to exit them).
531 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800532 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 = new ArrayList<ProcessRecord>();
534
535 /**
536 * List of processes that should gc as soon as things are idle.
537 */
538 final ArrayList<ProcessRecord> mProcessesToGc
539 = new ArrayList<ProcessRecord>();
540
541 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800542 * This is the process holding what we currently consider to be
543 * the "home" activity.
544 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700545 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800546
547 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 * Set of PendingResultRecord objects that are currently active.
549 */
550 final HashSet mPendingResultRecords = new HashSet();
551
552 /**
553 * Set of IntentSenderRecord objects that are currently active.
554 */
555 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
556 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
557
558 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800559 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700560 * already logged DropBox entries for. Guarded by itself. If
561 * something (rogue user app) forces this over
562 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
563 */
564 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
565 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
566
567 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700568 * Strict Mode background batched logging state.
569 *
570 * The string buffer is guarded by itself, and its lock is also
571 * used to determine if another batched write is already
572 * in-flight.
573 */
574 private final StringBuilder mStrictModeBuffer = new StringBuilder();
575
576 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700577 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
578 */
579 private boolean mPendingBroadcastTimeoutMessage;
580
581 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 * Intent broadcast that we have tried to start, but are
583 * waiting for its application's process to be created. We only
584 * need one (instead of a list) because we always process broadcasts
585 * one at a time, so no others can be started while waiting for this
586 * one.
587 */
588 BroadcastRecord mPendingBroadcast = null;
589
590 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700591 * The receiver index that is pending, to restart the broadcast if needed.
592 */
593 int mPendingBroadcastRecvIndex;
594
595 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 * Keeps track of all IIntentReceivers that have been registered for
597 * broadcasts. Hash keys are the receiver IBinder, hash value is
598 * a ReceiverList.
599 */
600 final HashMap mRegisteredReceivers = new HashMap();
601
602 /**
603 * Resolver for broadcast intents to registered receivers.
604 * Holds BroadcastFilter (subclass of IntentFilter).
605 */
606 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
607 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
608 @Override
609 protected boolean allowFilterResult(
610 BroadcastFilter filter, List<BroadcastFilter> dest) {
611 IBinder target = filter.receiverList.receiver.asBinder();
612 for (int i=dest.size()-1; i>=0; i--) {
613 if (dest.get(i).receiverList.receiver.asBinder() == target) {
614 return false;
615 }
616 }
617 return true;
618 }
619 };
620
621 /**
622 * State of all active sticky broadcasts. Keys are the action of the
623 * sticky Intent, values are an ArrayList of all broadcasted intents with
624 * that action (which should usually be one).
625 */
626 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
627 new HashMap<String, ArrayList<Intent>>();
628
629 /**
630 * All currently running services.
631 */
632 final HashMap<ComponentName, ServiceRecord> mServices =
633 new HashMap<ComponentName, ServiceRecord>();
634
635 /**
636 * All currently running services indexed by the Intent used to start them.
637 */
638 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
639 new HashMap<Intent.FilterComparison, ServiceRecord>();
640
641 /**
642 * All currently bound service connections. Keys are the IBinder of
643 * the client's IServiceConnection.
644 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700645 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
646 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647
648 /**
649 * List of services that we have been asked to start,
650 * but haven't yet been able to. It is used to hold start requests
651 * while waiting for their corresponding application thread to get
652 * going.
653 */
654 final ArrayList<ServiceRecord> mPendingServices
655 = new ArrayList<ServiceRecord>();
656
657 /**
658 * List of services that are scheduled to restart following a crash.
659 */
660 final ArrayList<ServiceRecord> mRestartingServices
661 = new ArrayList<ServiceRecord>();
662
663 /**
664 * List of services that are in the process of being stopped.
665 */
666 final ArrayList<ServiceRecord> mStoppingServices
667 = new ArrayList<ServiceRecord>();
668
669 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700670 * Backup/restore process management
671 */
672 String mBackupAppName = null;
673 BackupRecord mBackupTarget = null;
674
675 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 * List of PendingThumbnailsRecord objects of clients who are still
677 * waiting to receive all of the thumbnails for a task.
678 */
679 final ArrayList mPendingThumbnails = new ArrayList();
680
681 /**
682 * List of HistoryRecord objects that have been finished and must
683 * still report back to a pending thumbnail receiver.
684 */
685 final ArrayList mCancelledThumbnails = new ArrayList();
686
687 /**
688 * All of the currently running global content providers. Keys are a
689 * string containing the provider name and values are a
690 * ContentProviderRecord object containing the data about it. Note
691 * that a single provider may be published under multiple names, so
692 * there may be multiple entries here for a single one in mProvidersByClass.
693 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700694 final HashMap<String, ContentProviderRecord> mProvidersByName
695 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696
697 /**
698 * All of the currently running global content providers. Keys are a
699 * string containing the provider's implementation class and values are a
700 * ContentProviderRecord object containing the data about it.
701 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700702 final HashMap<String, ContentProviderRecord> mProvidersByClass
703 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704
705 /**
706 * List of content providers who have clients waiting for them. The
707 * application is currently being launched and the provider will be
708 * removed from this list once it is published.
709 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700710 final ArrayList<ContentProviderRecord> mLaunchingProviders
711 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712
713 /**
714 * Global set of specific Uri permissions that have been granted.
715 */
716 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
717 = new SparseArray<HashMap<Uri, UriPermission>>();
718
719 /**
720 * Thread-local storage used to carry caller permissions over through
721 * indirect content-provider access.
722 * @see #ActivityManagerService.openContentUri()
723 */
724 private class Identity {
725 public int pid;
726 public int uid;
727
728 Identity(int _pid, int _uid) {
729 pid = _pid;
730 uid = _uid;
731 }
732 }
733 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
734
735 /**
736 * All information we have collected about the runtime performance of
737 * any user id that can impact battery performance.
738 */
739 final BatteryStatsService mBatteryStatsService;
740
741 /**
742 * information about component usage
743 */
744 final UsageStatsService mUsageStatsService;
745
746 /**
747 * Current configuration information. HistoryRecord objects are given
748 * a reference to this object to indicate which configuration they are
749 * currently running in, so this object must be kept immutable.
750 */
751 Configuration mConfiguration = new Configuration();
752
753 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800754 * Current sequencing integer of the configuration, for skipping old
755 * configurations.
756 */
757 int mConfigurationSeq = 0;
758
759 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700760 * Hardware-reported OpenGLES version.
761 */
762 final int GL_ES_VERSION;
763
764 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 * List of initialization arguments to pass to all processes when binding applications to them.
766 * For example, references to the commonly used services.
767 */
768 HashMap<String, IBinder> mAppBindArgs;
769
770 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700771 * Temporary to avoid allocations. Protected by main lock.
772 */
773 final StringBuilder mStringBuilder = new StringBuilder(256);
774
775 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 * Used to control how we initialize the service.
777 */
778 boolean mStartRunning = false;
779 ComponentName mTopComponent;
780 String mTopAction;
781 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700782 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 boolean mSystemReady = false;
784 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700785 boolean mWaitingUpdate = false;
786 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700787 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700788 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789
790 Context mContext;
791
792 int mFactoryTest;
793
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700794 boolean mCheckedForSetup;
795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700797 * The time at which we will allow normal application switches again,
798 * after a call to {@link #stopAppSwitches()}.
799 */
800 long mAppSwitchesAllowedTime;
801
802 /**
803 * This is set to true after the first switch after mAppSwitchesAllowedTime
804 * is set; any switches after that will clear the time.
805 */
806 boolean mDidAppSwitch;
807
808 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700809 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700810 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700811 long mLastPowerCheckRealtime;
812
813 /**
814 * Last time (in uptime) at which we checked for power usage.
815 */
816 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700817
818 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 * Set while we are wanting to sleep, to prevent any
820 * activities from being started/resumed.
821 */
822 boolean mSleeping = false;
823
824 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700825 * Set if we are shutting down the system, similar to sleeping.
826 */
827 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828
829 /**
830 * Task identifier that activities are currently being started
831 * in. Incremented each time a new task is created.
832 * todo: Replace this with a TokenSpace class that generates non-repeating
833 * integers that won't wrap.
834 */
835 int mCurTask = 1;
836
837 /**
838 * Current sequence id for oom_adj computation traversal.
839 */
840 int mAdjSeq = 0;
841
842 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700843 * Current sequence id for process LRU updating.
844 */
845 int mLruSeq = 0;
846
847 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
849 * is set, indicating the user wants processes started in such a way
850 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
851 * running in each process (thus no pre-initialized process, etc).
852 */
853 boolean mSimpleProcessManagement = false;
854
855 /**
856 * System monitoring: number of processes that died since the last
857 * N procs were started.
858 */
859 int[] mProcDeaths = new int[20];
860
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700861 /**
862 * This is set if we had to do a delayed dexopt of an app before launching
863 * it, to increasing the ANR timeouts in that case.
864 */
865 boolean mDidDexOpt;
866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 String mDebugApp = null;
868 boolean mWaitForDebugger = false;
869 boolean mDebugTransient = false;
870 String mOrigDebugApp = null;
871 boolean mOrigWaitForDebugger = false;
872 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700873 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700875 final RemoteCallbackList<IActivityWatcher> mWatchers
876 = new RemoteCallbackList<IActivityWatcher>();
877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 /**
879 * Callback of last caller to {@link #requestPss}.
880 */
881 Runnable mRequestPssCallback;
882
883 /**
884 * Remaining processes for which we are waiting results from the last
885 * call to {@link #requestPss}.
886 */
887 final ArrayList<ProcessRecord> mRequestPssList
888 = new ArrayList<ProcessRecord>();
889
890 /**
891 * Runtime statistics collection thread. This object's lock is used to
892 * protect all related state.
893 */
894 final Thread mProcessStatsThread;
895
896 /**
897 * Used to collect process stats when showing not responding dialog.
898 * Protected by mProcessStatsThread.
899 */
900 final ProcessStats mProcessStats = new ProcessStats(
901 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700902 final AtomicLong mLastCpuTime = new AtomicLong(0);
903 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 long mLastWriteTime = 0;
906
907 /**
908 * Set to true after the system has finished booting.
909 */
910 boolean mBooted = false;
911
912 int mProcessLimit = 0;
913
914 WindowManagerService mWindowManager;
915
916 static ActivityManagerService mSelf;
917 static ActivityThread mSystemThread;
918
919 private final class AppDeathRecipient implements IBinder.DeathRecipient {
920 final ProcessRecord mApp;
921 final int mPid;
922 final IApplicationThread mAppThread;
923
924 AppDeathRecipient(ProcessRecord app, int pid,
925 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800926 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 TAG, "New death recipient " + this
928 + " for thread " + thread.asBinder());
929 mApp = app;
930 mPid = pid;
931 mAppThread = thread;
932 }
933
934 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800935 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 TAG, "Death received in " + this
937 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 synchronized(ActivityManagerService.this) {
939 appDiedLocked(mApp, mPid, mAppThread);
940 }
941 }
942 }
943
944 static final int SHOW_ERROR_MSG = 1;
945 static final int SHOW_NOT_RESPONDING_MSG = 2;
946 static final int SHOW_FACTORY_ERROR_MSG = 3;
947 static final int UPDATE_CONFIGURATION_MSG = 4;
948 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
949 static final int WAIT_FOR_DEBUGGER_MSG = 6;
950 static final int BROADCAST_INTENT_MSG = 7;
951 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 static final int SERVICE_TIMEOUT_MSG = 12;
953 static final int UPDATE_TIME_ZONE = 13;
954 static final int SHOW_UID_ERROR_MSG = 14;
955 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700957 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700958 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800959 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700960 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
961 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700962 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700963 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700964 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700965 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966
967 AlertDialog mUidAlert;
968
969 final Handler mHandler = new Handler() {
970 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800971 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 //}
973
974 public void handleMessage(Message msg) {
975 switch (msg.what) {
976 case SHOW_ERROR_MSG: {
977 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 synchronized (ActivityManagerService.this) {
979 ProcessRecord proc = (ProcessRecord)data.get("app");
980 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800981 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 return;
983 }
984 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700985 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800986 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 d.show();
988 proc.crashDialog = d;
989 } else {
990 // The device is asleep, so just pretend that the user
991 // saw a crash dialog and hit "force quit".
992 res.set(0);
993 }
994 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700995
996 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 } break;
998 case SHOW_NOT_RESPONDING_MSG: {
999 synchronized (ActivityManagerService.this) {
1000 HashMap data = (HashMap) msg.obj;
1001 ProcessRecord proc = (ProcessRecord)data.get("app");
1002 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001003 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 return;
1005 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001006
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001007 Intent intent = new Intent("android.intent.action.ANR");
1008 if (!mProcessesReady) {
1009 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1010 }
1011 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001012 null, null, 0, null, null, null,
1013 false, false, MY_PID, Process.SYSTEM_UID);
1014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001016 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 d.show();
1018 proc.anrDialog = d;
1019 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001020
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001021 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001023 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1024 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1025 synchronized (ActivityManagerService.this) {
1026 ProcessRecord proc = (ProcessRecord) data.get("app");
1027 if (proc == null) {
1028 Slog.e(TAG, "App not found when showing strict mode dialog.");
1029 break;
1030 }
1031 if (proc.crashDialog != null) {
1032 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1033 return;
1034 }
1035 AppErrorResult res = (AppErrorResult) data.get("result");
1036 if (!mSleeping && !mShuttingDown) {
1037 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1038 d.show();
1039 proc.crashDialog = d;
1040 } else {
1041 // The device is asleep, so just pretend that the user
1042 // saw a crash dialog and hit "force quit".
1043 res.set(0);
1044 }
1045 }
1046 ensureBootCompleted();
1047 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 case SHOW_FACTORY_ERROR_MSG: {
1049 Dialog d = new FactoryErrorDialog(
1050 mContext, msg.getData().getCharSequence("msg"));
1051 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001052 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 } break;
1054 case UPDATE_CONFIGURATION_MSG: {
1055 final ContentResolver resolver = mContext.getContentResolver();
1056 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1057 } break;
1058 case GC_BACKGROUND_PROCESSES_MSG: {
1059 synchronized (ActivityManagerService.this) {
1060 performAppGcsIfAppropriateLocked();
1061 }
1062 } break;
1063 case WAIT_FOR_DEBUGGER_MSG: {
1064 synchronized (ActivityManagerService.this) {
1065 ProcessRecord app = (ProcessRecord)msg.obj;
1066 if (msg.arg1 != 0) {
1067 if (!app.waitedForDebugger) {
1068 Dialog d = new AppWaitingForDebuggerDialog(
1069 ActivityManagerService.this,
1070 mContext, app);
1071 app.waitDialog = d;
1072 app.waitedForDebugger = true;
1073 d.show();
1074 }
1075 } else {
1076 if (app.waitDialog != null) {
1077 app.waitDialog.dismiss();
1078 app.waitDialog = null;
1079 }
1080 }
1081 }
1082 } break;
1083 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001084 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 TAG, "Received BROADCAST_INTENT_MSG");
1086 processNextBroadcast(true);
1087 } break;
1088 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001089 synchronized (ActivityManagerService.this) {
1090 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001094 if (mDidDexOpt) {
1095 mDidDexOpt = false;
1096 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1097 nmsg.obj = msg.obj;
1098 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1099 return;
1100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 serviceTimeout((ProcessRecord)msg.obj);
1102 } break;
1103 case UPDATE_TIME_ZONE: {
1104 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001105 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1106 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 if (r.thread != null) {
1108 try {
1109 r.thread.updateTimeZone();
1110 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001111 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 }
1113 }
1114 }
1115 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001116 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001117 case CLEAR_DNS_CACHE: {
1118 synchronized (ActivityManagerService.this) {
1119 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1120 ProcessRecord r = mLruProcesses.get(i);
1121 if (r.thread != null) {
1122 try {
1123 r.thread.clearDnsCache();
1124 } catch (RemoteException ex) {
1125 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1126 }
1127 }
1128 }
1129 }
1130 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001131 case UPDATE_HTTP_PROXY: {
1132 ProxyProperties proxy = (ProxyProperties)msg.obj;
1133 String host = "";
1134 String port = "";
1135 String exclList = "";
1136 if (proxy != null) {
1137 host = proxy.getHost();
1138 port = Integer.toString(proxy.getPort());
1139 exclList = proxy.getExclusionList();
1140 }
1141 synchronized (ActivityManagerService.this) {
1142 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1143 ProcessRecord r = mLruProcesses.get(i);
1144 if (r.thread != null) {
1145 try {
1146 r.thread.setHttpProxy(host, port, exclList);
1147 } catch (RemoteException ex) {
1148 Slog.w(TAG, "Failed to update http proxy for: " +
1149 r.info.processName);
1150 }
1151 }
1152 }
1153 }
1154 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 case SHOW_UID_ERROR_MSG: {
1156 // XXX This is a temporary dialog, no need to localize.
1157 AlertDialog d = new BaseErrorDialog(mContext);
1158 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1159 d.setCancelable(false);
1160 d.setTitle("System UIDs Inconsistent");
1161 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 +02001162 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1164 mUidAlert = d;
1165 d.show();
1166 } break;
1167 case IM_FEELING_LUCKY_MSG: {
1168 if (mUidAlert != null) {
1169 mUidAlert.dismiss();
1170 mUidAlert = null;
1171 }
1172 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001174 if (mDidDexOpt) {
1175 mDidDexOpt = false;
1176 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1177 nmsg.obj = msg.obj;
1178 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1179 return;
1180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 ProcessRecord app = (ProcessRecord)msg.obj;
1182 synchronized (ActivityManagerService.this) {
1183 processStartTimedOutLocked(app);
1184 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001185 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001186 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1187 synchronized (ActivityManagerService.this) {
1188 doPendingActivityLaunchesLocked(true);
1189 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001190 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001191 case KILL_APPLICATION_MSG: {
1192 synchronized (ActivityManagerService.this) {
1193 int uid = msg.arg1;
1194 boolean restart = (msg.arg2 == 1);
1195 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001196 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001197 }
1198 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001199 case FINALIZE_PENDING_INTENT_MSG: {
1200 ((PendingIntentRecord)msg.obj).completeFinalize();
1201 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001202 case POST_HEAVY_NOTIFICATION_MSG: {
1203 INotificationManager inm = NotificationManager.getService();
1204 if (inm == null) {
1205 return;
1206 }
1207
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001208 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001209 ProcessRecord process = root.app;
1210 if (process == null) {
1211 return;
1212 }
1213
1214 try {
1215 Context context = mContext.createPackageContext(process.info.packageName, 0);
1216 String text = mContext.getString(R.string.heavy_weight_notification,
1217 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1218 Notification notification = new Notification();
1219 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1220 notification.when = 0;
1221 notification.flags = Notification.FLAG_ONGOING_EVENT;
1222 notification.tickerText = text;
1223 notification.defaults = 0; // please be quiet
1224 notification.sound = null;
1225 notification.vibrate = null;
1226 notification.setLatestEventInfo(context, text,
1227 mContext.getText(R.string.heavy_weight_notification_detail),
1228 PendingIntent.getActivity(mContext, 0, root.intent,
1229 PendingIntent.FLAG_CANCEL_CURRENT));
1230
1231 try {
1232 int[] outId = new int[1];
1233 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1234 notification, outId);
1235 } catch (RuntimeException e) {
1236 Slog.w(ActivityManagerService.TAG,
1237 "Error showing notification for heavy-weight app", e);
1238 } catch (RemoteException e) {
1239 }
1240 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001241 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001242 }
1243 } break;
1244 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1245 INotificationManager inm = NotificationManager.getService();
1246 if (inm == null) {
1247 return;
1248 }
1249 try {
1250 inm.cancelNotification("android",
1251 R.string.heavy_weight_notification);
1252 } catch (RuntimeException e) {
1253 Slog.w(ActivityManagerService.TAG,
1254 "Error canceling notification for service", e);
1255 } catch (RemoteException e) {
1256 }
1257 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001258 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1259 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001260 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001261 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001262 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1263 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001264 }
1265 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 }
1267 }
1268 };
1269
1270 public static void setSystemProcess() {
1271 try {
1272 ActivityManagerService m = mSelf;
1273
1274 ServiceManager.addService("activity", m);
1275 ServiceManager.addService("meminfo", new MemBinder(m));
1276 if (MONITOR_CPU_USAGE) {
1277 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 ServiceManager.addService("permission", new PermissionController(m));
1280
1281 ApplicationInfo info =
1282 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001283 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001284 mSystemThread.installSystemApplicationInfo(info);
1285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 synchronized (mSelf) {
1287 ProcessRecord app = mSelf.newProcessRecordLocked(
1288 mSystemThread.getApplicationThread(), info,
1289 info.processName);
1290 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001291 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 app.maxAdj = SYSTEM_ADJ;
1293 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1294 synchronized (mSelf.mPidsSelfLocked) {
1295 mSelf.mPidsSelfLocked.put(app.pid, app);
1296 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001297 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 }
1299 } catch (PackageManager.NameNotFoundException e) {
1300 throw new RuntimeException(
1301 "Unable to find android system package", e);
1302 }
1303 }
1304
1305 public void setWindowManager(WindowManagerService wm) {
1306 mWindowManager = wm;
1307 }
1308
1309 public static final Context main(int factoryTest) {
1310 AThread thr = new AThread();
1311 thr.start();
1312
1313 synchronized (thr) {
1314 while (thr.mService == null) {
1315 try {
1316 thr.wait();
1317 } catch (InterruptedException e) {
1318 }
1319 }
1320 }
1321
1322 ActivityManagerService m = thr.mService;
1323 mSelf = m;
1324 ActivityThread at = ActivityThread.systemMain();
1325 mSystemThread = at;
1326 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001327 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 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 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002318 // Quick case: check if the top-most recent task is the same.
2319 if (N > 0 && mRecentTasks.get(0) == task) {
2320 return;
2321 }
2322 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 for (int i=0; i<N; i++) {
2324 TaskRecord tr = mRecentTasks.get(i);
2325 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2326 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2327 mRecentTasks.remove(i);
2328 i--;
2329 N--;
2330 if (task.intent == null) {
2331 // If the new recent task we are adding is not fully
2332 // specified, then replace it with the existing recent task.
2333 task = tr;
2334 }
2335 }
2336 }
2337 if (N >= MAX_RECENT_TASKS) {
2338 mRecentTasks.remove(N-1);
2339 }
2340 mRecentTasks.add(0, task);
2341 }
2342
2343 public void setRequestedOrientation(IBinder token,
2344 int requestedOrientation) {
2345 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002346 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 if (index < 0) {
2348 return;
2349 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002350 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 final long origId = Binder.clearCallingIdentity();
2352 mWindowManager.setAppOrientation(r, requestedOrientation);
2353 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002354 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002355 r.mayFreezeScreenLocked(r.app) ? r : null);
2356 if (config != null) {
2357 r.frozenBeforeDestroy = true;
2358 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002359 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 }
2361 }
2362 Binder.restoreCallingIdentity(origId);
2363 }
2364 }
2365
2366 public int getRequestedOrientation(IBinder token) {
2367 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002368 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 if (index < 0) {
2370 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2371 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002372 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 return mWindowManager.getAppOrientation(r);
2374 }
2375 }
2376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377 /**
2378 * This is the internal entry point for handling Activity.finish().
2379 *
2380 * @param token The Binder token referencing the Activity we want to finish.
2381 * @param resultCode Result code, if any, from this Activity.
2382 * @param resultData Result data (Intent), if any, from this Activity.
2383 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002384 * @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 -08002385 */
2386 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2387 // Refuse possible leaked file descriptors
2388 if (resultData != null && resultData.hasFileDescriptors() == true) {
2389 throw new IllegalArgumentException("File descriptors passed in Intent");
2390 }
2391
2392 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002393 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002394 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002395 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002396 if (next != null) {
2397 // ask watcher if this is allowed
2398 boolean resumeOK = true;
2399 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002400 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002402 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002403 }
2404
2405 if (!resumeOK) {
2406 return false;
2407 }
2408 }
2409 }
2410 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002411 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 resultData, "app-request");
2413 Binder.restoreCallingIdentity(origId);
2414 return res;
2415 }
2416 }
2417
Dianne Hackborn860755f2010-06-03 18:47:52 -07002418 public final void finishHeavyWeightApp() {
2419 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2420 != PackageManager.PERMISSION_GRANTED) {
2421 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2422 + Binder.getCallingPid()
2423 + ", uid=" + Binder.getCallingUid()
2424 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2425 Slog.w(TAG, msg);
2426 throw new SecurityException(msg);
2427 }
2428
2429 synchronized(this) {
2430 if (mHeavyWeightProcess == null) {
2431 return;
2432 }
2433
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002434 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002435 mHeavyWeightProcess.activities);
2436 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002437 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002438 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002439 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002440 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002441 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002442 null, "finish-heavy");
2443 }
2444 }
2445 }
2446
2447 mHeavyWeightProcess = null;
2448 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2449 }
2450 }
2451
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002452 public void crashApplication(int uid, int initialPid, String packageName,
2453 String message) {
2454 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2455 != PackageManager.PERMISSION_GRANTED) {
2456 String msg = "Permission Denial: crashApplication() from pid="
2457 + Binder.getCallingPid()
2458 + ", uid=" + Binder.getCallingUid()
2459 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2460 Slog.w(TAG, msg);
2461 throw new SecurityException(msg);
2462 }
2463
2464 synchronized(this) {
2465 ProcessRecord proc = null;
2466
2467 // Figure out which process to kill. We don't trust that initialPid
2468 // still has any relation to current pids, so must scan through the
2469 // list.
2470 synchronized (mPidsSelfLocked) {
2471 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2472 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2473 if (p.info.uid != uid) {
2474 continue;
2475 }
2476 if (p.pid == initialPid) {
2477 proc = p;
2478 break;
2479 }
2480 for (String str : p.pkgList) {
2481 if (str.equals(packageName)) {
2482 proc = p;
2483 }
2484 }
2485 }
2486 }
2487
2488 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002489 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002490 + " initialPid=" + initialPid
2491 + " packageName=" + packageName);
2492 return;
2493 }
2494
2495 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002496 if (proc.pid == Process.myPid()) {
2497 Log.w(TAG, "crashApplication: trying to crash self!");
2498 return;
2499 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002500 long ident = Binder.clearCallingIdentity();
2501 try {
2502 proc.thread.scheduleCrash(message);
2503 } catch (RemoteException e) {
2504 }
2505 Binder.restoreCallingIdentity(ident);
2506 }
2507 }
2508 }
2509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 public final void finishSubActivity(IBinder token, String resultWho,
2511 int requestCode) {
2512 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002513 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514 if (index < 0) {
2515 return;
2516 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002517 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518
2519 final long origId = Binder.clearCallingIdentity();
2520
2521 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002522 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2523 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 if (r.resultTo == self && r.requestCode == requestCode) {
2525 if ((r.resultWho == null && resultWho == null) ||
2526 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002527 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 Activity.RESULT_CANCELED, null, "request-sub");
2529 }
2530 }
2531 }
2532
2533 Binder.restoreCallingIdentity(origId);
2534 }
2535 }
2536
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002537 public boolean willActivityBeVisible(IBinder token) {
2538 synchronized(this) {
2539 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002540 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2541 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002542 if (r == token) {
2543 return true;
2544 }
2545 if (r.fullscreen && !r.finishing) {
2546 return false;
2547 }
2548 }
2549 return true;
2550 }
2551 }
2552
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002553 public void overridePendingTransition(IBinder token, String packageName,
2554 int enterAnim, int exitAnim) {
2555 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002556 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002557 if (index < 0) {
2558 return;
2559 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002560 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002561
2562 final long origId = Binder.clearCallingIdentity();
2563
2564 if (self.state == ActivityState.RESUMED
2565 || self.state == ActivityState.PAUSING) {
2566 mWindowManager.overridePendingAppTransition(packageName,
2567 enterAnim, exitAnim);
2568 }
2569
2570 Binder.restoreCallingIdentity(origId);
2571 }
2572 }
2573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 * Main function for removing an existing process from the activity manager
2576 * as a result of that process going away. Clears out all connections
2577 * to the process.
2578 */
2579 private final void handleAppDiedLocked(ProcessRecord app,
2580 boolean restarting) {
2581 cleanUpApplicationRecordLocked(app, restarting, -1);
2582 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002583 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 }
2585
2586 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002587 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2588 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2589 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002591 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2592 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 }
2594
2595 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002596 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597
2598 boolean atTop = true;
2599 boolean hasVisibleActivities = false;
2600
2601 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002602 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002603 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 TAG, "Removing app " + app + " from history with " + i + " entries");
2605 while (i > 0) {
2606 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002607 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002608 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2610 if (r.app == app) {
2611 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002612 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 TAG, "Removing this entry! frozen=" + r.haveState
2614 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002615 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616
2617 r.inHistory = false;
2618 mWindowManager.removeAppToken(r);
2619 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002620 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002622 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623
2624 } else {
2625 // We have the current state for this activity, so
2626 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002627 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 TAG, "Keeping entry, setting app to null");
2629 if (r.visible) {
2630 hasVisibleActivities = true;
2631 }
2632 r.app = null;
2633 r.nowVisible = false;
2634 if (!r.haveState) {
2635 r.icicle = null;
2636 }
2637 }
2638
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002639 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 r.state = ActivityState.STOPPED;
2641 }
2642 atTop = false;
2643 }
2644
2645 app.activities.clear();
2646
2647 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002648 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649 + " running instrumentation " + app.instrumentationClass);
2650 Bundle info = new Bundle();
2651 info.putString("shortMsg", "Process crashed.");
2652 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2653 }
2654
2655 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002656 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002657 // If there was nothing to resume, and we are not already
2658 // restarting this process, but there is a visible activity that
2659 // is hosted by the process... then make sure all visible
2660 // activities are running, taking care of restarting this
2661 // process.
2662 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002663 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 }
2665 }
2666 }
2667 }
2668
2669 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2670 IBinder threadBinder = thread.asBinder();
2671
2672 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002673 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2674 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002675 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2676 return i;
2677 }
2678 }
2679 return -1;
2680 }
2681
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002682 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 IApplicationThread thread) {
2684 if (thread == null) {
2685 return null;
2686 }
2687
2688 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002689 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 }
2691
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002692 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693 IApplicationThread thread) {
2694
2695 mProcDeaths[0]++;
2696
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002697 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2698 synchronized (stats) {
2699 stats.noteProcessDiedLocked(app.info.uid, pid);
2700 }
2701
Magnus Edlund7bb25812010-02-24 15:45:06 +01002702 // Clean up already done if the process has been re-started.
2703 if (app.pid == pid && app.thread != null &&
2704 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002705 if (!app.killedBackground) {
2706 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2707 + ") has died.");
2708 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002709 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002710 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 TAG, "Dying app: " + app + ", pid: " + pid
2712 + ", thread: " + thread.asBinder());
2713 boolean doLowMem = app.instrumentationClass == null;
2714 handleAppDiedLocked(app, false);
2715
2716 if (doLowMem) {
2717 // If there are no longer any background processes running,
2718 // and the app that died was not running instrumentation,
2719 // then tell everyone we are now low on memory.
2720 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002721 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2722 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2724 haveBg = true;
2725 break;
2726 }
2727 }
2728
2729 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002730 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002731 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002732 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002733 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2734 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002735 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002736 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2737 // The low memory report is overriding any current
2738 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002739 // heavy/important/visible/foreground processes first.
2740 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002741 rec.lastRequestedGc = 0;
2742 } else {
2743 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002745 rec.reportLowMemory = true;
2746 rec.lastLowMemory = now;
2747 mProcessesToGc.remove(rec);
2748 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 }
2750 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002751 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 }
2753 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002754 } else if (app.pid != pid) {
2755 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002756 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002757 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002758 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002759 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002760 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 + thread.asBinder());
2762 }
2763 }
2764
Dan Egnor42471dd2010-01-07 17:25:22 -08002765 /**
2766 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002767 * @param clearTraces causes the dump file to be erased prior to the new
2768 * traces being written, if true; when false, the new traces will be
2769 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002770 * @param firstPids of dalvik VM processes to dump stack traces for first
2771 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002772 * @return file containing stack traces, or null if no dump file is configured
2773 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002774 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2775 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002776 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2777 if (tracesPath == null || tracesPath.length() == 0) {
2778 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002780
2781 File tracesFile = new File(tracesPath);
2782 try {
2783 File tracesDir = tracesFile.getParentFile();
2784 if (!tracesDir.exists()) tracesFile.mkdirs();
2785 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2786
Christopher Tate6ee412d2010-05-28 12:01:56 -07002787 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002788 tracesFile.createNewFile();
2789 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2790 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002791 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002792 return null;
2793 }
2794
2795 // Use a FileObserver to detect when traces finish writing.
2796 // The order of traces is considered important to maintain for legibility.
2797 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2798 public synchronized void onEvent(int event, String path) { notify(); }
2799 };
2800
2801 try {
2802 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002803
2804 // First collect all of the stacks of the most important pids.
2805 try {
2806 int num = firstPids.size();
2807 for (int i = 0; i < num; i++) {
2808 synchronized (observer) {
2809 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2810 observer.wait(200); // Wait for write-close, give up after 200msec
2811 }
2812 }
2813 } catch (InterruptedException e) {
2814 Log.wtf(TAG, e);
2815 }
2816
2817 // Next measure CPU usage.
2818 if (processStats != null) {
2819 processStats.init();
2820 System.gc();
2821 processStats.update();
2822 try {
2823 synchronized (processStats) {
2824 processStats.wait(500); // measure over 1/2 second.
2825 }
2826 } catch (InterruptedException e) {
2827 }
2828 processStats.update();
2829
2830 // We'll take the stack crawls of just the top apps using CPU.
2831 final int N = processStats.countWorkingStats();
2832 int numProcs = 0;
2833 for (int i=0; i<N && numProcs<5; i++) {
2834 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2835 if (lastPids.indexOfKey(stats.pid) >= 0) {
2836 numProcs++;
2837 try {
2838 synchronized (observer) {
2839 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2840 observer.wait(200); // Wait for write-close, give up after 200msec
2841 }
2842 } catch (InterruptedException e) {
2843 Log.wtf(TAG, e);
2844 }
2845
2846 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002847 }
2848 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002849
2850 return tracesFile;
2851
Dan Egnor42471dd2010-01-07 17:25:22 -08002852 } finally {
2853 observer.stopWatching();
2854 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855 }
2856
Jeff Brown4d94a762010-09-23 11:33:28 -07002857 private final class AppNotResponding implements Runnable {
2858 private final ProcessRecord mApp;
2859 private final String mAnnotation;
2860
2861 public AppNotResponding(ProcessRecord app, String annotation) {
2862 mApp = app;
2863 mAnnotation = annotation;
2864 }
2865
2866 @Override
2867 public void run() {
2868 appNotResponding(mApp, null, null, mAnnotation);
2869 }
2870 }
2871
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002872 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2873 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002874 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2875 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2876
Dianne Hackborn287952c2010-09-22 22:34:31 -07002877 if (mController != null) {
2878 try {
2879 // 0 == continue, -1 = kill process immediately
2880 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2881 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2882 } catch (RemoteException e) {
2883 mController = null;
2884 }
2885 }
2886
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002887 long anrTime = SystemClock.uptimeMillis();
2888 if (MONITOR_CPU_USAGE) {
2889 updateCpuStatsNow();
2890 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002891
2892 synchronized (this) {
2893 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2894 if (mShuttingDown) {
2895 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2896 return;
2897 } else if (app.notResponding) {
2898 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2899 return;
2900 } else if (app.crashing) {
2901 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2902 return;
2903 }
2904
2905 // In case we come through here for the same app before completing
2906 // this one, mark as anring now so we will bail out.
2907 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002908
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002909 // Log the ANR to the event log.
2910 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2911 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002912
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002913 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002914 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002915
2916 int parentPid = app.pid;
2917 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002918 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002919
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002920 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002921
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002922 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2923 ProcessRecord r = mLruProcesses.get(i);
2924 if (r != null && r.thread != null) {
2925 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002926 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2927 if (r.persistent) {
2928 firstPids.add(pid);
2929 } else {
2930 lastPids.put(pid, Boolean.TRUE);
2931 }
2932 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 }
2935 }
2936
Dan Egnor42471dd2010-01-07 17:25:22 -08002937 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002938 StringBuilder info = mStringBuilder;
2939 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002940 info.append("ANR in ").append(app.processName);
2941 if (activity != null && activity.shortComponentName != null) {
2942 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002943 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002944 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002945 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002946 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002948 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002949 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951
Dianne Hackborn287952c2010-09-22 22:34:31 -07002952 final ProcessStats processStats = new ProcessStats(true);
2953
2954 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2955
Dan Egnor42471dd2010-01-07 17:25:22 -08002956 String cpuInfo = null;
2957 if (MONITOR_CPU_USAGE) {
2958 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002959 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002960 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002961 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002962 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002963 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 }
2965
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002966 info.append(processStats.printCurrentState(anrTime));
2967
Joe Onorato8a9b2202010-02-26 18:56:32 -08002968 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002969 if (tracesFile == null) {
2970 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2971 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2972 }
2973
2974 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2975
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002976 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002978 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2979 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002981 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2982 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983 }
2984 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002985 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 }
2987 }
2988
Dan Egnor42471dd2010-01-07 17:25:22 -08002989 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2990 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2991 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002992
2993 synchronized (this) {
2994 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2995 Process.killProcess(app.pid);
2996 return;
2997 }
2998
2999 // Set the app's notResponding state, and look up the errorReportReceiver
3000 makeAppNotRespondingLocked(app,
3001 activity != null ? activity.shortComponentName : null,
3002 annotation != null ? "ANR " + annotation : "ANR",
3003 info.toString());
3004
3005 // Bring up the infamous App Not Responding dialog
3006 Message msg = Message.obtain();
3007 HashMap map = new HashMap();
3008 msg.what = SHOW_NOT_RESPONDING_MSG;
3009 msg.obj = map;
3010 map.put("app", app);
3011 if (activity != null) {
3012 map.put("activity", activity);
3013 }
3014
3015 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003017 }
3018
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003019 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3020 if (!mLaunchWarningShown) {
3021 mLaunchWarningShown = true;
3022 mHandler.post(new Runnable() {
3023 @Override
3024 public void run() {
3025 synchronized (ActivityManagerService.this) {
3026 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3027 d.show();
3028 mHandler.postDelayed(new Runnable() {
3029 @Override
3030 public void run() {
3031 synchronized (ActivityManagerService.this) {
3032 d.dismiss();
3033 mLaunchWarningShown = false;
3034 }
3035 }
3036 }, 4000);
3037 }
3038 }
3039 });
3040 }
3041 }
3042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 public boolean clearApplicationUserData(final String packageName,
3044 final IPackageDataObserver observer) {
3045 int uid = Binder.getCallingUid();
3046 int pid = Binder.getCallingPid();
3047 long callingId = Binder.clearCallingIdentity();
3048 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003049 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003050 int pkgUid = -1;
3051 synchronized(this) {
3052 try {
3053 pkgUid = pm.getPackageUid(packageName);
3054 } catch (RemoteException e) {
3055 }
3056 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003057 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003058 return false;
3059 }
3060 if (uid == pkgUid || checkComponentPermission(
3061 android.Manifest.permission.CLEAR_APP_USER_DATA,
3062 pid, uid, -1)
3063 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003064 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 } else {
3066 throw new SecurityException(pid+" does not have permission:"+
3067 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3068 "for process:"+packageName);
3069 }
3070 }
3071
3072 try {
3073 //clear application user data
3074 pm.clearApplicationUserData(packageName, observer);
3075 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3076 Uri.fromParts("package", packageName, null));
3077 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003078 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3079 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 } catch (RemoteException e) {
3081 }
3082 } finally {
3083 Binder.restoreCallingIdentity(callingId);
3084 }
3085 return true;
3086 }
3087
Dianne Hackborn03abb812010-01-04 18:43:19 -08003088 public void killBackgroundProcesses(final String packageName) {
3089 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3090 != PackageManager.PERMISSION_GRANTED &&
3091 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3092 != PackageManager.PERMISSION_GRANTED) {
3093 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 + Binder.getCallingPid()
3095 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003096 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003097 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 throw new SecurityException(msg);
3099 }
3100
3101 long callingId = Binder.clearCallingIdentity();
3102 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003103 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 int pkgUid = -1;
3105 synchronized(this) {
3106 try {
3107 pkgUid = pm.getPackageUid(packageName);
3108 } catch (RemoteException e) {
3109 }
3110 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003111 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003112 return;
3113 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003114 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003115 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003116 }
3117 } finally {
3118 Binder.restoreCallingIdentity(callingId);
3119 }
3120 }
3121
3122 public void forceStopPackage(final String packageName) {
3123 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3124 != PackageManager.PERMISSION_GRANTED) {
3125 String msg = "Permission Denial: forceStopPackage() from pid="
3126 + Binder.getCallingPid()
3127 + ", uid=" + Binder.getCallingUid()
3128 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003129 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003130 throw new SecurityException(msg);
3131 }
3132
3133 long callingId = Binder.clearCallingIdentity();
3134 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003135 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003136 int pkgUid = -1;
3137 synchronized(this) {
3138 try {
3139 pkgUid = pm.getPackageUid(packageName);
3140 } catch (RemoteException e) {
3141 }
3142 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003143 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003144 return;
3145 }
3146 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003147 }
3148 } finally {
3149 Binder.restoreCallingIdentity(callingId);
3150 }
3151 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003152
3153 /*
3154 * The pkg name and uid have to be specified.
3155 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3156 */
3157 public void killApplicationWithUid(String pkg, int uid) {
3158 if (pkg == null) {
3159 return;
3160 }
3161 // Make sure the uid is valid.
3162 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003163 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003164 return;
3165 }
3166 int callerUid = Binder.getCallingUid();
3167 // Only the system server can kill an application
3168 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003169 // Post an aysnc message to kill the application
3170 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3171 msg.arg1 = uid;
3172 msg.arg2 = 0;
3173 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003174 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003175 } else {
3176 throw new SecurityException(callerUid + " cannot kill pkg: " +
3177 pkg);
3178 }
3179 }
3180
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003181 public void closeSystemDialogs(String reason) {
3182 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003183 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003184 if (reason != null) {
3185 intent.putExtra("reason", reason);
3186 }
3187
3188 final int uid = Binder.getCallingUid();
3189 final long origId = Binder.clearCallingIdentity();
3190 synchronized (this) {
3191 int i = mWatchers.beginBroadcast();
3192 while (i > 0) {
3193 i--;
3194 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3195 if (w != null) {
3196 try {
3197 w.closingSystemDialogs(reason);
3198 } catch (RemoteException e) {
3199 }
3200 }
3201 }
3202 mWatchers.finishBroadcast();
3203
Dianne Hackbornffa42482009-09-23 22:20:11 -07003204 mWindowManager.closeSystemDialogs(reason);
3205
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003206 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3207 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003208 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003209 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003210 Activity.RESULT_CANCELED, null, "close-sys");
3211 }
3212 }
3213
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003214 broadcastIntentLocked(null, null, intent, null,
3215 null, 0, null, null, null, false, false, -1, uid);
3216 }
3217 Binder.restoreCallingIdentity(origId);
3218 }
3219
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003220 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003221 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003222 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3223 for (int i=pids.length-1; i>=0; i--) {
3224 infos[i] = new Debug.MemoryInfo();
3225 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003226 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003227 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003228 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003229
3230 public void killApplicationProcess(String processName, int uid) {
3231 if (processName == null) {
3232 return;
3233 }
3234
3235 int callerUid = Binder.getCallingUid();
3236 // Only the system server can kill an application
3237 if (callerUid == Process.SYSTEM_UID) {
3238 synchronized (this) {
3239 ProcessRecord app = getProcessRecordLocked(processName, uid);
3240 if (app != null) {
3241 try {
3242 app.thread.scheduleSuicide();
3243 } catch (RemoteException e) {
3244 // If the other end already died, then our work here is done.
3245 }
3246 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003247 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003248 + processName + " / " + uid);
3249 }
3250 }
3251 } else {
3252 throw new SecurityException(callerUid + " cannot kill app process: " +
3253 processName);
3254 }
3255 }
3256
Dianne Hackborn03abb812010-01-04 18:43:19 -08003257 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003258 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003259 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3260 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003261 if (!mProcessesReady) {
3262 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 intent.putExtra(Intent.EXTRA_UID, uid);
3265 broadcastIntentLocked(null, null, intent,
3266 null, null, 0, null, null, null,
3267 false, false, MY_PID, Process.SYSTEM_UID);
3268 }
3269
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003270 private final boolean killPackageProcessesLocked(String packageName, int uid,
3271 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003272 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273
Dianne Hackborn03abb812010-01-04 18:43:19 -08003274 // Remove all processes this package may have touched: all with the
3275 // same UID (except for the system or root user), and all whose name
3276 // matches the package name.
3277 final String procNamePrefix = packageName + ":";
3278 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3279 final int NA = apps.size();
3280 for (int ia=0; ia<NA; ia++) {
3281 ProcessRecord app = apps.valueAt(ia);
3282 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003283 if (doit) {
3284 procs.add(app);
3285 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003286 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3287 || app.processName.equals(packageName)
3288 || app.processName.startsWith(procNamePrefix)) {
3289 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003290 if (!doit) {
3291 return true;
3292 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003293 app.removed = true;
3294 procs.add(app);
3295 }
3296 }
3297 }
3298 }
3299
3300 int N = procs.size();
3301 for (int i=0; i<N; i++) {
3302 removeProcessLocked(procs.get(i), callerWillRestart);
3303 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003304 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003305 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003306
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003307 private final boolean forceStopPackageLocked(String name, int uid,
3308 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 int i, N;
3310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 if (uid < 0) {
3312 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003313 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 } catch (RemoteException e) {
3315 }
3316 }
3317
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003318 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003319 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003320
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003321 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3322 while (badApps.hasNext()) {
3323 SparseArray<Long> ba = badApps.next();
3324 if (ba.get(uid) != null) {
3325 badApps.remove();
3326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003327 }
3328 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003329
3330 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3331 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003333 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3334 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003336 if (!doit) {
3337 return true;
3338 }
3339 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003340 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 if (r.app != null) {
3342 r.app.removed = true;
3343 }
3344 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003345 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 }
3347 }
3348
3349 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3350 for (ServiceRecord service : mServices.values()) {
3351 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003352 if (!doit) {
3353 return true;
3354 }
3355 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003356 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 if (service.app != null) {
3358 service.app.removed = true;
3359 }
3360 service.app = null;
3361 services.add(service);
3362 }
3363 }
3364
3365 N = services.size();
3366 for (i=0; i<N; i++) {
3367 bringDownServiceLocked(services.get(i), true);
3368 }
3369
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003370 if (doit) {
3371 if (purgeCache) {
3372 AttributeCache ac = AttributeCache.instance();
3373 if (ac != null) {
3374 ac.removePackage(name);
3375 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003376 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003377 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003378 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003379
3380 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003381 }
3382
3383 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3384 final String name = app.processName;
3385 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003386 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003387 TAG, "Force removing process " + app + " (" + name
3388 + "/" + uid + ")");
3389
3390 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003391 if (mHeavyWeightProcess == app) {
3392 mHeavyWeightProcess = null;
3393 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 boolean needRestart = false;
3396 if (app.pid > 0 && app.pid != MY_PID) {
3397 int pid = app.pid;
3398 synchronized (mPidsSelfLocked) {
3399 mPidsSelfLocked.remove(pid);
3400 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3401 }
3402 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003403 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003404 Process.killProcess(pid);
3405
3406 if (app.persistent) {
3407 if (!callerWillRestart) {
3408 addAppLocked(app.info);
3409 } else {
3410 needRestart = true;
3411 }
3412 }
3413 } else {
3414 mRemovedProcesses.add(app);
3415 }
3416
3417 return needRestart;
3418 }
3419
3420 private final void processStartTimedOutLocked(ProcessRecord app) {
3421 final int pid = app.pid;
3422 boolean gone = false;
3423 synchronized (mPidsSelfLocked) {
3424 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3425 if (knownApp != null && knownApp.thread == null) {
3426 mPidsSelfLocked.remove(pid);
3427 gone = true;
3428 }
3429 }
3430
3431 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003432 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003433 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003434 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003436 if (mHeavyWeightProcess == app) {
3437 mHeavyWeightProcess = null;
3438 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3439 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003440 // Take care of any launching providers waiting for this process.
3441 checkAppInLaunchingProvidersLocked(app, true);
3442 // Take care of any services that are waiting for the process.
3443 for (int i=0; i<mPendingServices.size(); i++) {
3444 ServiceRecord sr = mPendingServices.get(i);
3445 if (app.info.uid == sr.appInfo.uid
3446 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003447 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003448 mPendingServices.remove(i);
3449 i--;
3450 bringDownServiceLocked(sr, true);
3451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003453 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003454 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003455 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003456 try {
3457 IBackupManager bm = IBackupManager.Stub.asInterface(
3458 ServiceManager.getService(Context.BACKUP_SERVICE));
3459 bm.agentDisconnected(app.info.packageName);
3460 } catch (RemoteException e) {
3461 // Can't happen; the backup manager is local
3462 }
3463 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003464 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003465 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003466 mPendingBroadcast.state = BroadcastRecord.IDLE;
3467 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003468 mPendingBroadcast = null;
3469 scheduleBroadcastsLocked();
3470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003472 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 }
3474 }
3475
3476 private final boolean attachApplicationLocked(IApplicationThread thread,
3477 int pid) {
3478
3479 // Find the application record that is being attached... either via
3480 // the pid if we are running in multiple processes, or just pull the
3481 // next app record if we are emulating process with anonymous threads.
3482 ProcessRecord app;
3483 if (pid != MY_PID && pid >= 0) {
3484 synchronized (mPidsSelfLocked) {
3485 app = mPidsSelfLocked.get(pid);
3486 }
3487 } else if (mStartingProcesses.size() > 0) {
3488 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003489 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490 } else {
3491 app = null;
3492 }
3493
3494 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003495 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003497 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 if (pid > 0 && pid != MY_PID) {
3499 Process.killProcess(pid);
3500 } else {
3501 try {
3502 thread.scheduleExit();
3503 } catch (Exception e) {
3504 // Ignore exceptions.
3505 }
3506 }
3507 return false;
3508 }
3509
3510 // If this application record is still attached to a previous
3511 // process, clean it up now.
3512 if (app.thread != null) {
3513 handleAppDiedLocked(app, true);
3514 }
3515
3516 // Tell the process all about itself.
3517
Joe Onorato8a9b2202010-02-26 18:56:32 -08003518 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 TAG, "Binding process pid " + pid + " to record " + app);
3520
3521 String processName = app.processName;
3522 try {
3523 thread.asBinder().linkToDeath(new AppDeathRecipient(
3524 app, pid, thread), 0);
3525 } catch (RemoteException e) {
3526 app.resetPackageList();
3527 startProcessLocked(app, "link fail", processName);
3528 return false;
3529 }
3530
Doug Zongker2bec3d42009-12-04 12:52:44 -08003531 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532
3533 app.thread = thread;
3534 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003535 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3536 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 app.forcingToForeground = null;
3538 app.foregroundServices = false;
3539 app.debugging = false;
3540
3541 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3542
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003543 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003544 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003546 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003547 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003548 }
3549
Joe Onorato8a9b2202010-02-26 18:56:32 -08003550 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 TAG, "New app record " + app
3552 + " thread=" + thread.asBinder() + " pid=" + pid);
3553 try {
3554 int testMode = IApplicationThread.DEBUG_OFF;
3555 if (mDebugApp != null && mDebugApp.equals(processName)) {
3556 testMode = mWaitForDebugger
3557 ? IApplicationThread.DEBUG_WAIT
3558 : IApplicationThread.DEBUG_ON;
3559 app.debugging = true;
3560 if (mDebugTransient) {
3561 mDebugApp = mOrigDebugApp;
3562 mWaitForDebugger = mOrigWaitForDebugger;
3563 }
3564 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003565
Christopher Tate181fafa2009-05-14 11:12:14 -07003566 // If the app is being launched for restore or full backup, set it up specially
3567 boolean isRestrictedBackupMode = false;
3568 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3569 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3570 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3571 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003572
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003573 ensurePackageDexOpt(app.instrumentationInfo != null
3574 ? app.instrumentationInfo.packageName
3575 : app.info.packageName);
3576 if (app.instrumentationClass != null) {
3577 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003578 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003579 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003580 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003581 thread.bindApplication(processName, app.instrumentationInfo != null
3582 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 app.instrumentationClass, app.instrumentationProfileFile,
3584 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003585 isRestrictedBackupMode || !normalMode,
3586 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003587 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003588 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 } catch (Exception e) {
3590 // todo: Yikes! What should we do? For now we will try to
3591 // start another process, but that could easily get us in
3592 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003593 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594
3595 app.resetPackageList();
3596 startProcessLocked(app, "bind fail", processName);
3597 return false;
3598 }
3599
3600 // Remove this record from the list of starting applications.
3601 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003602 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3603 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003604 mProcessesOnHold.remove(app);
3605
3606 boolean badApp = false;
3607 boolean didSomething = false;
3608
3609 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003610 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003611 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003612 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3613 && processName.equals(hr.processName)) {
3614 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003615 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 didSomething = true;
3617 }
3618 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003619 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 + hr.intent.getComponent().flattenToShortString(), e);
3621 badApp = true;
3622 }
3623 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003624 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625 }
3626 }
3627
3628 // Find any services that should be running in this process...
3629 if (!badApp && mPendingServices.size() > 0) {
3630 ServiceRecord sr = null;
3631 try {
3632 for (int i=0; i<mPendingServices.size(); i++) {
3633 sr = mPendingServices.get(i);
3634 if (app.info.uid != sr.appInfo.uid
3635 || !processName.equals(sr.processName)) {
3636 continue;
3637 }
3638
3639 mPendingServices.remove(i);
3640 i--;
3641 realStartServiceLocked(sr, app);
3642 didSomething = true;
3643 }
3644 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003645 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003646 + sr.shortName, e);
3647 badApp = true;
3648 }
3649 }
3650
3651 // Check if the next broadcast receiver is in this process...
3652 BroadcastRecord br = mPendingBroadcast;
3653 if (!badApp && br != null && br.curApp == app) {
3654 try {
3655 mPendingBroadcast = null;
3656 processCurBroadcastLocked(br, app);
3657 didSomething = true;
3658 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003659 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 + br.curComponent.flattenToShortString(), e);
3661 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003662 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3664 br.resultExtras, br.resultAbort, true);
3665 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003666 // We need to reset the state if we fails to start the receiver.
3667 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 }
3669 }
3670
Christopher Tate181fafa2009-05-14 11:12:14 -07003671 // Check whether the next backup agent is in this process...
3672 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003673 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003674 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003675 try {
3676 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3677 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003678 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003679 e.printStackTrace();
3680 }
3681 }
3682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 if (badApp) {
3684 // todo: Also need to kill application to deal with all
3685 // kinds of exceptions.
3686 handleAppDiedLocked(app, false);
3687 return false;
3688 }
3689
3690 if (!didSomething) {
3691 updateOomAdjLocked();
3692 }
3693
3694 return true;
3695 }
3696
3697 public final void attachApplication(IApplicationThread thread) {
3698 synchronized (this) {
3699 int callingPid = Binder.getCallingPid();
3700 final long origId = Binder.clearCallingIdentity();
3701 attachApplicationLocked(thread, callingPid);
3702 Binder.restoreCallingIdentity(origId);
3703 }
3704 }
3705
Dianne Hackborne88846e2009-09-30 21:34:25 -07003706 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003707 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003708 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003709 Binder.restoreCallingIdentity(origId);
3710 }
3711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003713 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003714 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003715 mWindowManager.enableScreenAfterBoot();
3716 }
3717
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003718 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003719 IntentFilter pkgFilter = new IntentFilter();
3720 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3721 pkgFilter.addDataScheme("package");
3722 mContext.registerReceiver(new BroadcastReceiver() {
3723 @Override
3724 public void onReceive(Context context, Intent intent) {
3725 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3726 if (pkgs != null) {
3727 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003728 synchronized (ActivityManagerService.this) {
3729 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3730 setResultCode(Activity.RESULT_OK);
3731 return;
3732 }
3733 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003734 }
3735 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003736 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003737 }, pkgFilter);
3738
3739 synchronized (this) {
3740 // Ensure that any processes we had put on hold are now started
3741 // up.
3742 final int NP = mProcessesOnHold.size();
3743 if (NP > 0) {
3744 ArrayList<ProcessRecord> procs =
3745 new ArrayList<ProcessRecord>(mProcessesOnHold);
3746 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003747 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3748 + procs.get(ip));
3749 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003750 }
3751 }
3752
3753 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003754 // Start looking for apps that are abusing wake locks.
3755 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003756 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003757 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003758 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003759 broadcastIntentLocked(null, null,
3760 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3761 null, null, 0, null, null,
3762 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3763 false, false, MY_PID, Process.SYSTEM_UID);
3764 }
3765 }
3766 }
3767
3768 final void ensureBootCompleted() {
3769 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003770 boolean enableScreen;
3771 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003772 booting = mBooting;
3773 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003774 enableScreen = !mBooted;
3775 mBooted = true;
3776 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003777
3778 if (booting) {
3779 finishBooting();
3780 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003781
3782 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003783 enableScreenAfterBoot();
3784 }
3785 }
3786
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003787 public final void activityPaused(IBinder token) {
3788 final long origId = Binder.clearCallingIdentity();
3789 mMainStack.activityPaused(token, false);
3790 Binder.restoreCallingIdentity(origId);
3791 }
3792
3793 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3794 CharSequence description) {
3795 if (localLOGV) Slog.v(
3796 TAG, "Activity stopped: token=" + token);
3797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 // Refuse possible leaked file descriptors
3799 if (icicle != null && icicle.hasFileDescriptors()) {
3800 throw new IllegalArgumentException("File descriptors passed in Bundle");
3801 }
3802
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003803 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804
3805 final long origId = Binder.clearCallingIdentity();
3806
3807 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003808 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003810 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003811 r.icicle = icicle;
3812 r.haveState = true;
3813 if (thumbnail != null) {
3814 r.thumbnail = thumbnail;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003815 if (r.task != null) {
3816 r.task.lastThumbnail = r.thumbnail;
3817 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 r.description = description;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003820 if (r.task != null) {
3821 r.task.lastDescription = r.description;
3822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 r.stopped = true;
3824 r.state = ActivityState.STOPPED;
3825 if (!r.finishing) {
3826 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003827 r.stack.destroyActivityLocked(r, true);
3828 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 }
3830 }
3831 }
3832 }
3833
3834 if (r != null) {
3835 sendPendingThumbnail(r, null, null, null, false);
3836 }
3837
3838 trimApplications();
3839
3840 Binder.restoreCallingIdentity(origId);
3841 }
3842
3843 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003844 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003845 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 }
3847
3848 public String getCallingPackage(IBinder token) {
3849 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003850 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003851 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003852 }
3853 }
3854
3855 public ComponentName getCallingActivity(IBinder token) {
3856 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003857 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003858 return r != null ? r.intent.getComponent() : null;
3859 }
3860 }
3861
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003862 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003863 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003865 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 if (r != null) {
3867 return r.resultTo;
3868 }
3869 }
3870 return null;
3871 }
3872
3873 public ComponentName getActivityClassForToken(IBinder token) {
3874 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003875 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003877 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003878 return r.intent.getComponent();
3879 }
3880 return null;
3881 }
3882 }
3883
3884 public String getPackageForToken(IBinder token) {
3885 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003886 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003888 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889 return r.packageName;
3890 }
3891 return null;
3892 }
3893 }
3894
3895 public IIntentSender getIntentSender(int type,
3896 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003897 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003899 if (intents != null) {
3900 if (intents.length < 1) {
3901 throw new IllegalArgumentException("Intents array length must be >= 1");
3902 }
3903 for (int i=0; i<intents.length; i++) {
3904 Intent intent = intents[i];
3905 if (intent == null) {
3906 throw new IllegalArgumentException("Null intent at index " + i);
3907 }
3908 if (intent.hasFileDescriptors()) {
3909 throw new IllegalArgumentException("File descriptors passed in Intent");
3910 }
3911 if (type == INTENT_SENDER_BROADCAST &&
3912 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3913 throw new IllegalArgumentException(
3914 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3915 }
3916 intents[i] = new Intent(intent);
3917 }
3918 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003919 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003920 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003921 }
3922 }
3923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 synchronized(this) {
3925 int callingUid = Binder.getCallingUid();
3926 try {
3927 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3928 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003929 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 .getPackageUid(packageName);
3931 if (uid != Binder.getCallingUid()) {
3932 String msg = "Permission Denial: getIntentSender() from pid="
3933 + Binder.getCallingPid()
3934 + ", uid=" + Binder.getCallingUid()
3935 + ", (need uid=" + uid + ")"
3936 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003937 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 throw new SecurityException(msg);
3939 }
3940 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003941
3942 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003943 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 } catch (RemoteException e) {
3946 throw new SecurityException(e);
3947 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003948 }
3949 }
3950
3951 IIntentSender getIntentSenderLocked(int type,
3952 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003953 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003954 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003955 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003956 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003957 if (index < 0) {
3958 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003959 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003960 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003961 if (activity.finishing) {
3962 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003964 }
3965
3966 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3967 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3968 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3969 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3970 |PendingIntent.FLAG_UPDATE_CURRENT);
3971
3972 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3973 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003974 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003975 WeakReference<PendingIntentRecord> ref;
3976 ref = mIntentSenderRecords.get(key);
3977 PendingIntentRecord rec = ref != null ? ref.get() : null;
3978 if (rec != null) {
3979 if (!cancelCurrent) {
3980 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003981 if (rec.key.requestIntent != null) {
3982 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3983 }
3984 if (intents != null) {
3985 intents[intents.length-1] = rec.key.requestIntent;
3986 rec.key.allIntents = intents;
3987 rec.key.allResolvedTypes = resolvedTypes;
3988 } else {
3989 rec.key.allIntents = null;
3990 rec.key.allResolvedTypes = null;
3991 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 return rec;
3994 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003995 rec.canceled = true;
3996 mIntentSenderRecords.remove(key);
3997 }
3998 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 return rec;
4000 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004001 rec = new PendingIntentRecord(this, key, callingUid);
4002 mIntentSenderRecords.put(key, rec.ref);
4003 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4004 if (activity.pendingResults == null) {
4005 activity.pendingResults
4006 = new HashSet<WeakReference<PendingIntentRecord>>();
4007 }
4008 activity.pendingResults.add(rec.ref);
4009 }
4010 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 }
4012
4013 public void cancelIntentSender(IIntentSender sender) {
4014 if (!(sender instanceof PendingIntentRecord)) {
4015 return;
4016 }
4017 synchronized(this) {
4018 PendingIntentRecord rec = (PendingIntentRecord)sender;
4019 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004020 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 .getPackageUid(rec.key.packageName);
4022 if (uid != Binder.getCallingUid()) {
4023 String msg = "Permission Denial: cancelIntentSender() from pid="
4024 + Binder.getCallingPid()
4025 + ", uid=" + Binder.getCallingUid()
4026 + " is not allowed to cancel packges "
4027 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004028 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004029 throw new SecurityException(msg);
4030 }
4031 } catch (RemoteException e) {
4032 throw new SecurityException(e);
4033 }
4034 cancelIntentSenderLocked(rec, true);
4035 }
4036 }
4037
4038 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4039 rec.canceled = true;
4040 mIntentSenderRecords.remove(rec.key);
4041 if (cleanActivity && rec.key.activity != null) {
4042 rec.key.activity.pendingResults.remove(rec.ref);
4043 }
4044 }
4045
4046 public String getPackageForIntentSender(IIntentSender pendingResult) {
4047 if (!(pendingResult instanceof PendingIntentRecord)) {
4048 return null;
4049 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004050 try {
4051 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4052 return res.key.packageName;
4053 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004054 }
4055 return null;
4056 }
4057
4058 public void setProcessLimit(int max) {
4059 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4060 "setProcessLimit()");
4061 mProcessLimit = max;
4062 }
4063
4064 public int getProcessLimit() {
4065 return mProcessLimit;
4066 }
4067
4068 void foregroundTokenDied(ForegroundToken token) {
4069 synchronized (ActivityManagerService.this) {
4070 synchronized (mPidsSelfLocked) {
4071 ForegroundToken cur
4072 = mForegroundProcesses.get(token.pid);
4073 if (cur != token) {
4074 return;
4075 }
4076 mForegroundProcesses.remove(token.pid);
4077 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4078 if (pr == null) {
4079 return;
4080 }
4081 pr.forcingToForeground = null;
4082 pr.foregroundServices = false;
4083 }
4084 updateOomAdjLocked();
4085 }
4086 }
4087
4088 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4089 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4090 "setProcessForeground()");
4091 synchronized(this) {
4092 boolean changed = false;
4093
4094 synchronized (mPidsSelfLocked) {
4095 ProcessRecord pr = mPidsSelfLocked.get(pid);
4096 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004097 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 return;
4099 }
4100 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4101 if (oldToken != null) {
4102 oldToken.token.unlinkToDeath(oldToken, 0);
4103 mForegroundProcesses.remove(pid);
4104 pr.forcingToForeground = null;
4105 changed = true;
4106 }
4107 if (isForeground && token != null) {
4108 ForegroundToken newToken = new ForegroundToken() {
4109 public void binderDied() {
4110 foregroundTokenDied(this);
4111 }
4112 };
4113 newToken.pid = pid;
4114 newToken.token = token;
4115 try {
4116 token.linkToDeath(newToken, 0);
4117 mForegroundProcesses.put(pid, newToken);
4118 pr.forcingToForeground = token;
4119 changed = true;
4120 } catch (RemoteException e) {
4121 // If the process died while doing this, we will later
4122 // do the cleanup with the process death link.
4123 }
4124 }
4125 }
4126
4127 if (changed) {
4128 updateOomAdjLocked();
4129 }
4130 }
4131 }
4132
4133 // =========================================================
4134 // PERMISSIONS
4135 // =========================================================
4136
4137 static class PermissionController extends IPermissionController.Stub {
4138 ActivityManagerService mActivityManagerService;
4139 PermissionController(ActivityManagerService activityManagerService) {
4140 mActivityManagerService = activityManagerService;
4141 }
4142
4143 public boolean checkPermission(String permission, int pid, int uid) {
4144 return mActivityManagerService.checkPermission(permission, pid,
4145 uid) == PackageManager.PERMISSION_GRANTED;
4146 }
4147 }
4148
4149 /**
4150 * This can be called with or without the global lock held.
4151 */
4152 int checkComponentPermission(String permission, int pid, int uid,
4153 int reqUid) {
4154 // We might be performing an operation on behalf of an indirect binder
4155 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4156 // client identity accordingly before proceeding.
4157 Identity tlsIdentity = sCallerIdentity.get();
4158 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004159 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004160 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4161 uid = tlsIdentity.uid;
4162 pid = tlsIdentity.pid;
4163 }
4164
4165 // Root, system server and our own process get to do everything.
4166 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4167 !Process.supportsProcesses()) {
4168 return PackageManager.PERMISSION_GRANTED;
4169 }
4170 // If the target requires a specific UID, always fail for others.
4171 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004172 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 return PackageManager.PERMISSION_DENIED;
4174 }
4175 if (permission == null) {
4176 return PackageManager.PERMISSION_GRANTED;
4177 }
4178 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004179 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 .checkUidPermission(permission, uid);
4181 } catch (RemoteException e) {
4182 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004183 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004184 }
4185 return PackageManager.PERMISSION_DENIED;
4186 }
4187
4188 /**
4189 * As the only public entry point for permissions checking, this method
4190 * can enforce the semantic that requesting a check on a null global
4191 * permission is automatically denied. (Internally a null permission
4192 * string is used when calling {@link #checkComponentPermission} in cases
4193 * when only uid-based security is needed.)
4194 *
4195 * This can be called with or without the global lock held.
4196 */
4197 public int checkPermission(String permission, int pid, int uid) {
4198 if (permission == null) {
4199 return PackageManager.PERMISSION_DENIED;
4200 }
4201 return checkComponentPermission(permission, pid, uid, -1);
4202 }
4203
4204 /**
4205 * Binder IPC calls go through the public entry point.
4206 * This can be called with or without the global lock held.
4207 */
4208 int checkCallingPermission(String permission) {
4209 return checkPermission(permission,
4210 Binder.getCallingPid(),
4211 Binder.getCallingUid());
4212 }
4213
4214 /**
4215 * This can be called with or without the global lock held.
4216 */
4217 void enforceCallingPermission(String permission, String func) {
4218 if (checkCallingPermission(permission)
4219 == PackageManager.PERMISSION_GRANTED) {
4220 return;
4221 }
4222
4223 String msg = "Permission Denial: " + func + " from pid="
4224 + Binder.getCallingPid()
4225 + ", uid=" + Binder.getCallingUid()
4226 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004227 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 throw new SecurityException(msg);
4229 }
4230
4231 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004232 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4233 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4234 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4235 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4236 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004238 // Is the component private from the target uid?
4239 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4240
4241 // Acceptable if the there is no read permission needed from the
4242 // target or the target is holding the read permission.
4243 if (!readPerm) {
4244 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004246 == PackageManager.PERMISSION_GRANTED)) {
4247 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004248 }
4249 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004250
4251 // Acceptable if the there is no write permission needed from the
4252 // target or the target is holding the read permission.
4253 if (!writePerm) {
4254 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004255 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004256 == PackageManager.PERMISSION_GRANTED)) {
4257 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 }
4259 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004260
4261 // Acceptable if there is a path permission matching the URI that
4262 // the target holds the permission on.
4263 PathPermission[] pps = pi.pathPermissions;
4264 if (pps != null && (!readPerm || !writePerm)) {
4265 final String path = uri.getPath();
4266 int i = pps.length;
4267 while (i > 0 && (!readPerm || !writePerm)) {
4268 i--;
4269 PathPermission pp = pps[i];
4270 if (!readPerm) {
4271 final String pprperm = pp.getReadPermission();
4272 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4273 + pprperm + " for " + pp.getPath()
4274 + ": match=" + pp.match(path)
4275 + " check=" + pm.checkUidPermission(pprperm, uid));
4276 if (pprperm != null && pp.match(path) &&
4277 (pm.checkUidPermission(pprperm, uid)
4278 == PackageManager.PERMISSION_GRANTED)) {
4279 readPerm = true;
4280 }
4281 }
4282 if (!writePerm) {
4283 final String ppwperm = pp.getWritePermission();
4284 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4285 + ppwperm + " for " + pp.getPath()
4286 + ": match=" + pp.match(path)
4287 + " check=" + pm.checkUidPermission(ppwperm, uid));
4288 if (ppwperm != null && pp.match(path) &&
4289 (pm.checkUidPermission(ppwperm, uid)
4290 == PackageManager.PERMISSION_GRANTED)) {
4291 writePerm = true;
4292 }
4293 }
4294 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296 } catch (RemoteException e) {
4297 return false;
4298 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004299
4300 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 }
4302
4303 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4304 int modeFlags) {
4305 // Root gets to do everything.
4306 if (uid == 0 || !Process.supportsProcesses()) {
4307 return true;
4308 }
4309 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4310 if (perms == null) return false;
4311 UriPermission perm = perms.get(uri);
4312 if (perm == null) return false;
4313 return (modeFlags&perm.modeFlags) == modeFlags;
4314 }
4315
4316 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4317 // Another redirected-binder-call permissions check as in
4318 // {@link checkComponentPermission}.
4319 Identity tlsIdentity = sCallerIdentity.get();
4320 if (tlsIdentity != null) {
4321 uid = tlsIdentity.uid;
4322 pid = tlsIdentity.pid;
4323 }
4324
4325 // Our own process gets to do everything.
4326 if (pid == MY_PID) {
4327 return PackageManager.PERMISSION_GRANTED;
4328 }
4329 synchronized(this) {
4330 return checkUriPermissionLocked(uri, uid, modeFlags)
4331 ? PackageManager.PERMISSION_GRANTED
4332 : PackageManager.PERMISSION_DENIED;
4333 }
4334 }
4335
Dianne Hackborn39792d22010-08-19 18:01:52 -07004336 /**
4337 * Check if the targetPkg can be granted permission to access uri by
4338 * the callingUid using the given modeFlags. Throws a security exception
4339 * if callingUid is not allowed to do this. Returns the uid of the target
4340 * if the URI permission grant should be performed; returns -1 if it is not
4341 * needed (for example targetPkg already has permission to access the URI).
4342 */
4343 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4344 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4346 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4347 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004348 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004349 }
4350
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004351 if (targetPkg != null) {
4352 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4353 "Checking grant " + targetPkg + " permission to " + uri);
4354 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004355
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004356 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357
4358 // If this is not a content: uri, we can't do anything with it.
4359 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004360 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004361 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004362 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 }
4364
4365 String name = uri.getAuthority();
4366 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004367 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 if (cpr != null) {
4369 pi = cpr.info;
4370 } else {
4371 try {
4372 pi = pm.resolveContentProvider(name,
4373 PackageManager.GET_URI_PERMISSION_PATTERNS);
4374 } catch (RemoteException ex) {
4375 }
4376 }
4377 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004378 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004379 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 }
4381
4382 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004383 if (targetPkg != null) {
4384 try {
4385 targetUid = pm.getPackageUid(targetPkg);
4386 if (targetUid < 0) {
4387 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4388 "Can't grant URI permission no uid for: " + targetPkg);
4389 return -1;
4390 }
4391 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004392 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004394 } else {
4395 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 }
4397
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004398 if (targetUid >= 0) {
4399 // First... does the target actually need this permission?
4400 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4401 // No need to grant the target this permission.
4402 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4403 "Target " + targetPkg + " already has full permission to " + uri);
4404 return -1;
4405 }
4406 } else {
4407 // First... there is no target package, so can anyone access it?
4408 boolean allowed = pi.exported;
4409 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4410 if (pi.readPermission != null) {
4411 allowed = false;
4412 }
4413 }
4414 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4415 if (pi.writePermission != null) {
4416 allowed = false;
4417 }
4418 }
4419 if (allowed) {
4420 return -1;
4421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 }
4423
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004424 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 if (!pi.grantUriPermissions) {
4426 throw new SecurityException("Provider " + pi.packageName
4427 + "/" + pi.name
4428 + " does not allow granting of Uri permissions (uri "
4429 + uri + ")");
4430 }
4431 if (pi.uriPermissionPatterns != null) {
4432 final int N = pi.uriPermissionPatterns.length;
4433 boolean allowed = false;
4434 for (int i=0; i<N; i++) {
4435 if (pi.uriPermissionPatterns[i] != null
4436 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4437 allowed = true;
4438 break;
4439 }
4440 }
4441 if (!allowed) {
4442 throw new SecurityException("Provider " + pi.packageName
4443 + "/" + pi.name
4444 + " does not allow granting of permission to path of Uri "
4445 + uri);
4446 }
4447 }
4448
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004449 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004450 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004451 if (callingUid != Process.myUid()) {
4452 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4453 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4454 throw new SecurityException("Uid " + callingUid
4455 + " does not have permission to uri " + uri);
4456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 }
4458 }
4459
Dianne Hackborn39792d22010-08-19 18:01:52 -07004460 return targetUid;
4461 }
4462
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004463 public int checkGrantUriPermission(int callingUid, String targetPkg,
4464 Uri uri, int modeFlags) {
4465 synchronized(this) {
4466 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4467 }
4468 }
4469
Dianne Hackborn39792d22010-08-19 18:01:52 -07004470 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4471 Uri uri, int modeFlags, UriPermissionOwner owner) {
4472 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4473 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4474 if (modeFlags == 0) {
4475 return;
4476 }
4477
4478 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 // to the uri, and the target doesn't. Let's now give this to
4480 // the target.
4481
Joe Onorato8a9b2202010-02-26 18:56:32 -08004482 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004483 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 HashMap<Uri, UriPermission> targetUris
4486 = mGrantedUriPermissions.get(targetUid);
4487 if (targetUris == null) {
4488 targetUris = new HashMap<Uri, UriPermission>();
4489 mGrantedUriPermissions.put(targetUid, targetUris);
4490 }
4491
4492 UriPermission perm = targetUris.get(uri);
4493 if (perm == null) {
4494 perm = new UriPermission(targetUid, uri);
4495 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004498 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004499 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 perm.globalModeFlags |= modeFlags;
4501 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004502 perm.readOwners.add(owner);
4503 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004505 perm.writeOwners.add(owner);
4506 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004507 }
4508 }
4509
Dianne Hackborn39792d22010-08-19 18:01:52 -07004510 void grantUriPermissionLocked(int callingUid,
4511 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004512 if (targetPkg == null) {
4513 throw new NullPointerException("targetPkg");
4514 }
4515
Dianne Hackborn39792d22010-08-19 18:01:52 -07004516 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4517 if (targetUid < 0) {
4518 return;
4519 }
4520
4521 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4522 }
4523
4524 /**
4525 * Like checkGrantUriPermissionLocked, but takes an Intent.
4526 */
4527 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4528 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004529 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004530 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004531 + " from " + intent + "; flags=0x"
4532 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4533
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004534 if (targetPkg == null) {
4535 throw new NullPointerException("targetPkg");
4536 }
4537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004539 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004540 }
4541 Uri data = intent.getData();
4542 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004543 return -1;
4544 }
4545 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4546 intent.getFlags());
4547 }
4548
4549 /**
4550 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4551 */
4552 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4553 String targetPkg, Intent intent, UriPermissionOwner owner) {
4554 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4555 intent.getFlags(), owner);
4556 }
4557
4558 void grantUriPermissionFromIntentLocked(int callingUid,
4559 String targetPkg, Intent intent, UriPermissionOwner owner) {
4560 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4561 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 return;
4563 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004564
4565 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004566 }
4567
4568 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4569 Uri uri, int modeFlags) {
4570 synchronized(this) {
4571 final ProcessRecord r = getRecordForAppLocked(caller);
4572 if (r == null) {
4573 throw new SecurityException("Unable to find app for caller "
4574 + caller
4575 + " when granting permission to uri " + uri);
4576 }
4577 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004578 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 }
4580 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004581 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004582 }
4583
4584 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4585 null);
4586 }
4587 }
4588
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004589 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004590 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4591 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4592 HashMap<Uri, UriPermission> perms
4593 = mGrantedUriPermissions.get(perm.uid);
4594 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004595 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004596 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 perms.remove(perm.uri);
4598 if (perms.size() == 0) {
4599 mGrantedUriPermissions.remove(perm.uid);
4600 }
4601 }
4602 }
4603 }
4604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4606 int modeFlags) {
4607 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4608 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4609 if (modeFlags == 0) {
4610 return;
4611 }
4612
Joe Onorato8a9b2202010-02-26 18:56:32 -08004613 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004614 "Revoking all granted permissions to " + uri);
4615
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004616 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617
4618 final String authority = uri.getAuthority();
4619 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004620 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004621 if (cpr != null) {
4622 pi = cpr.info;
4623 } else {
4624 try {
4625 pi = pm.resolveContentProvider(authority,
4626 PackageManager.GET_URI_PERMISSION_PATTERNS);
4627 } catch (RemoteException ex) {
4628 }
4629 }
4630 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004631 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004632 return;
4633 }
4634
4635 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004636 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 // Right now, if you are not the original owner of the permission,
4638 // you are not allowed to revoke it.
4639 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4640 throw new SecurityException("Uid " + callingUid
4641 + " does not have permission to uri " + uri);
4642 //}
4643 }
4644
4645 // Go through all of the permissions and remove any that match.
4646 final List<String> SEGMENTS = uri.getPathSegments();
4647 if (SEGMENTS != null) {
4648 final int NS = SEGMENTS.size();
4649 int N = mGrantedUriPermissions.size();
4650 for (int i=0; i<N; i++) {
4651 HashMap<Uri, UriPermission> perms
4652 = mGrantedUriPermissions.valueAt(i);
4653 Iterator<UriPermission> it = perms.values().iterator();
4654 toploop:
4655 while (it.hasNext()) {
4656 UriPermission perm = it.next();
4657 Uri targetUri = perm.uri;
4658 if (!authority.equals(targetUri.getAuthority())) {
4659 continue;
4660 }
4661 List<String> targetSegments = targetUri.getPathSegments();
4662 if (targetSegments == null) {
4663 continue;
4664 }
4665 if (targetSegments.size() < NS) {
4666 continue;
4667 }
4668 for (int j=0; j<NS; j++) {
4669 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4670 continue toploop;
4671 }
4672 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004673 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004674 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004675 perm.clearModes(modeFlags);
4676 if (perm.modeFlags == 0) {
4677 it.remove();
4678 }
4679 }
4680 if (perms.size() == 0) {
4681 mGrantedUriPermissions.remove(
4682 mGrantedUriPermissions.keyAt(i));
4683 N--;
4684 i--;
4685 }
4686 }
4687 }
4688 }
4689
4690 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4691 int modeFlags) {
4692 synchronized(this) {
4693 final ProcessRecord r = getRecordForAppLocked(caller);
4694 if (r == null) {
4695 throw new SecurityException("Unable to find app for caller "
4696 + caller
4697 + " when revoking permission to uri " + uri);
4698 }
4699 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004700 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004701 return;
4702 }
4703
4704 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4705 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4706 if (modeFlags == 0) {
4707 return;
4708 }
4709
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004710 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711
4712 final String authority = uri.getAuthority();
4713 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004714 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 if (cpr != null) {
4716 pi = cpr.info;
4717 } else {
4718 try {
4719 pi = pm.resolveContentProvider(authority,
4720 PackageManager.GET_URI_PERMISSION_PATTERNS);
4721 } catch (RemoteException ex) {
4722 }
4723 }
4724 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004725 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 return;
4727 }
4728
4729 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4730 }
4731 }
4732
Dianne Hackborn7e269642010-08-25 19:50:20 -07004733 @Override
4734 public IBinder newUriPermissionOwner(String name) {
4735 synchronized(this) {
4736 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4737 return owner.getExternalTokenLocked();
4738 }
4739 }
4740
4741 @Override
4742 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4743 Uri uri, int modeFlags) {
4744 synchronized(this) {
4745 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4746 if (owner == null) {
4747 throw new IllegalArgumentException("Unknown owner: " + token);
4748 }
4749 if (fromUid != Binder.getCallingUid()) {
4750 if (Binder.getCallingUid() != Process.myUid()) {
4751 // Only system code can grant URI permissions on behalf
4752 // of other users.
4753 throw new SecurityException("nice try");
4754 }
4755 }
4756 if (targetPkg == null) {
4757 throw new IllegalArgumentException("null target");
4758 }
4759 if (uri == null) {
4760 throw new IllegalArgumentException("null uri");
4761 }
4762
4763 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4764 }
4765 }
4766
4767 @Override
4768 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4769 synchronized(this) {
4770 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4771 if (owner == null) {
4772 throw new IllegalArgumentException("Unknown owner: " + token);
4773 }
4774
4775 if (uri == null) {
4776 owner.removeUriPermissionsLocked(mode);
4777 } else {
4778 owner.removeUriPermissionLocked(uri, mode);
4779 }
4780 }
4781 }
4782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4784 synchronized (this) {
4785 ProcessRecord app =
4786 who != null ? getRecordForAppLocked(who) : null;
4787 if (app == null) return;
4788
4789 Message msg = Message.obtain();
4790 msg.what = WAIT_FOR_DEBUGGER_MSG;
4791 msg.obj = app;
4792 msg.arg1 = waiting ? 1 : 0;
4793 mHandler.sendMessage(msg);
4794 }
4795 }
4796
4797 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4798 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004799 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004801 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004802 }
4803
4804 // =========================================================
4805 // TASK MANAGEMENT
4806 // =========================================================
4807
4808 public List getTasks(int maxNum, int flags,
4809 IThumbnailReceiver receiver) {
4810 ArrayList list = new ArrayList();
4811
4812 PendingThumbnailsRecord pending = null;
4813 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004814 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815
4816 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004817 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4819 + ", receiver=" + receiver);
4820
4821 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4822 != PackageManager.PERMISSION_GRANTED) {
4823 if (receiver != null) {
4824 // If the caller wants to wait for pending thumbnails,
4825 // it ain't gonna get them.
4826 try {
4827 receiver.finished();
4828 } catch (RemoteException ex) {
4829 }
4830 }
4831 String msg = "Permission Denial: getTasks() from pid="
4832 + Binder.getCallingPid()
4833 + ", uid=" + Binder.getCallingUid()
4834 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004835 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004836 throw new SecurityException(msg);
4837 }
4838
Dianne Hackbornd2835932010-12-13 16:28:46 -08004839 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4840 && checkCallingPermission(
4841 android.Manifest.permission.READ_FRAME_BUFFER)
4842 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004843
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004844 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004845 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004846 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004847 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004848 CharSequence topDescription = null;
4849 TaskRecord curTask = null;
4850 int numActivities = 0;
4851 int numRunning = 0;
4852 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004853 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004854 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004855 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004856
4857 // Initialize state for next task if needed.
4858 if (top == null ||
4859 (top.state == ActivityState.INITIALIZING
4860 && top.task == r.task)) {
4861 top = r;
4862 topDescription = r.description;
4863 curTask = r.task;
4864 numActivities = numRunning = 0;
4865 }
4866
4867 // Add 'r' into the current task.
4868 numActivities++;
4869 if (r.app != null && r.app.thread != null) {
4870 numRunning++;
4871 }
4872 if (topDescription == null) {
4873 topDescription = r.description;
4874 }
4875
Joe Onorato8a9b2202010-02-26 18:56:32 -08004876 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004877 TAG, r.intent.getComponent().flattenToShortString()
4878 + ": task=" + r.task);
4879
4880 // If the next one is a different task, generate a new
4881 // TaskInfo entry for what we have.
4882 if (next == null || next.task != curTask) {
4883 ActivityManager.RunningTaskInfo ci
4884 = new ActivityManager.RunningTaskInfo();
4885 ci.id = curTask.taskId;
4886 ci.baseActivity = r.intent.getComponent();
4887 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004888 if (canReadFb) {
4889 if (top.thumbnail != null) {
4890 ci.thumbnail = top.thumbnail;
4891 } else if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004892 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004893 }
4894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 ci.description = topDescription;
4896 ci.numActivities = numActivities;
4897 ci.numRunning = numRunning;
4898 //System.out.println(
4899 // "#" + maxNum + ": " + " descr=" + ci.description);
4900 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004901 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 TAG, "State=" + top.state + "Idle=" + top.idle
4903 + " app=" + top.app
4904 + " thr=" + (top.app != null ? top.app.thread : null));
4905 if (top.state == ActivityState.RESUMED
4906 || top.state == ActivityState.PAUSING) {
4907 if (top.idle && top.app != null
4908 && top.app.thread != null) {
4909 topRecord = top;
4910 topThumbnail = top.app.thread;
4911 } else {
4912 top.thumbnailNeeded = true;
4913 }
4914 }
4915 if (pending == null) {
4916 pending = new PendingThumbnailsRecord(receiver);
4917 }
4918 pending.pendingRecords.add(top);
4919 }
4920 list.add(ci);
4921 maxNum--;
4922 top = null;
4923 }
4924 }
4925
4926 if (pending != null) {
4927 mPendingThumbnails.add(pending);
4928 }
4929 }
4930
Joe Onorato8a9b2202010-02-26 18:56:32 -08004931 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004932
4933 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004934 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004935 try {
4936 topThumbnail.requestThumbnail(topRecord);
4937 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004938 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 sendPendingThumbnail(null, topRecord, null, null, true);
4940 }
4941 }
4942
4943 if (pending == null && receiver != null) {
4944 // In this case all thumbnails were available and the client
4945 // is being asked to be told when the remaining ones come in...
4946 // which is unusually, since the top-most currently running
4947 // activity should never have a canned thumbnail! Oh well.
4948 try {
4949 receiver.finished();
4950 } catch (RemoteException ex) {
4951 }
4952 }
4953
4954 return list;
4955 }
4956
4957 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4958 int flags) {
4959 synchronized (this) {
4960 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4961 "getRecentTasks()");
4962
Dianne Hackbornd2835932010-12-13 16:28:46 -08004963 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4964 && checkCallingPermission(
4965 android.Manifest.permission.READ_FRAME_BUFFER)
4966 == PackageManager.PERMISSION_GRANTED;
4967
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004968 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004969
Dianne Hackbornd2835932010-12-13 16:28:46 -08004970 ActivityRecord resumed = mMainStack.mResumedActivity;
4971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004972 final int N = mRecentTasks.size();
4973 ArrayList<ActivityManager.RecentTaskInfo> res
4974 = new ArrayList<ActivityManager.RecentTaskInfo>(
4975 maxNum < N ? maxNum : N);
4976 for (int i=0; i<N && maxNum > 0; i++) {
4977 TaskRecord tr = mRecentTasks.get(i);
4978 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4979 || (tr.intent == null)
4980 || ((tr.intent.getFlags()
4981 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4982 ActivityManager.RecentTaskInfo rti
4983 = new ActivityManager.RecentTaskInfo();
4984 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4985 rti.baseIntent = new Intent(
4986 tr.intent != null ? tr.intent : tr.affinityIntent);
4987 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004988
Dianne Hackbornd2835932010-12-13 16:28:46 -08004989 if (canReadFb) {
4990 if (resumed != null && resumed.task == tr) {
4991 rti.thumbnail = resumed.stack.screenshotActivities(resumed);
4992 } else {
4993 rti.thumbnail = tr.lastThumbnail;
4994 }
4995 }
4996 rti.description = tr.lastDescription;
4997
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004998 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4999 // Check whether this activity is currently available.
5000 try {
5001 if (rti.origActivity != null) {
5002 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5003 continue;
5004 }
5005 } else if (rti.baseIntent != null) {
5006 if (pm.queryIntentActivities(rti.baseIntent,
5007 null, 0) == null) {
5008 continue;
5009 }
5010 }
5011 } catch (RemoteException e) {
5012 // Will never happen.
5013 }
5014 }
5015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 res.add(rti);
5017 maxNum--;
5018 }
5019 }
5020 return res;
5021 }
5022 }
5023
5024 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5025 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005026 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005027 TaskRecord jt = startTask;
5028
5029 // First look backwards
5030 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005031 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 if (r.task != jt) {
5033 jt = r.task;
5034 if (affinity.equals(jt.affinity)) {
5035 return j;
5036 }
5037 }
5038 }
5039
5040 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005041 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 jt = startTask;
5043 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005044 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005045 if (r.task != jt) {
5046 if (affinity.equals(jt.affinity)) {
5047 return j;
5048 }
5049 jt = r.task;
5050 }
5051 }
5052
5053 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005054 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 return N-1;
5056 }
5057
5058 return -1;
5059 }
5060
5061 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005062 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005064 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5066 "moveTaskToFront()");
5067
5068 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005069 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5070 Binder.getCallingUid(), "Task to front")) {
5071 return;
5072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005073 final long origId = Binder.clearCallingIdentity();
5074 try {
5075 int N = mRecentTasks.size();
5076 for (int i=0; i<N; i++) {
5077 TaskRecord tr = mRecentTasks.get(i);
5078 if (tr.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005079 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5080 // Caller wants the home activity moved with it. To accomplish this,
5081 // we'll just move the home task to the top first.
5082 mMainStack.moveHomeToFrontLocked();
5083 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005084 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005085 return;
5086 }
5087 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005088 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5089 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 if (hr.task.taskId == task) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005091 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5092 // Caller wants the home activity moved with it. To accomplish this,
5093 // we'll just move the home task to the top first.
5094 mMainStack.moveHomeToFrontLocked();
5095 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005096 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 return;
5098 }
5099 }
5100 } finally {
5101 Binder.restoreCallingIdentity(origId);
5102 }
5103 }
5104 }
5105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005106 public void moveTaskToBack(int task) {
5107 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5108 "moveTaskToBack()");
5109
5110 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005111 if (mMainStack.mResumedActivity != null
5112 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005113 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5114 Binder.getCallingUid(), "Task to back")) {
5115 return;
5116 }
5117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005119 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005120 Binder.restoreCallingIdentity(origId);
5121 }
5122 }
5123
5124 /**
5125 * Moves an activity, and all of the other activities within the same task, to the bottom
5126 * of the history stack. The activity's order within the task is unchanged.
5127 *
5128 * @param token A reference to the activity we wish to move
5129 * @param nonRoot If false then this only works if the activity is the root
5130 * of a task; if true it will work for any activity in a task.
5131 * @return Returns true if the move completed, false if not.
5132 */
5133 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5134 synchronized(this) {
5135 final long origId = Binder.clearCallingIdentity();
5136 int taskId = getTaskForActivityLocked(token, !nonRoot);
5137 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005138 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 }
5140 Binder.restoreCallingIdentity(origId);
5141 }
5142 return false;
5143 }
5144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 public void moveTaskBackwards(int task) {
5146 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5147 "moveTaskBackwards()");
5148
5149 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005150 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5151 Binder.getCallingUid(), "Task backwards")) {
5152 return;
5153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 final long origId = Binder.clearCallingIdentity();
5155 moveTaskBackwardsLocked(task);
5156 Binder.restoreCallingIdentity(origId);
5157 }
5158 }
5159
5160 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005161 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 }
5163
5164 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5165 synchronized(this) {
5166 return getTaskForActivityLocked(token, onlyRoot);
5167 }
5168 }
5169
5170 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005171 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 TaskRecord lastTask = null;
5173 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005174 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 if (r == token) {
5176 if (!onlyRoot || lastTask != r.task) {
5177 return r.task.taskId;
5178 }
5179 return -1;
5180 }
5181 lastTask = r.task;
5182 }
5183
5184 return -1;
5185 }
5186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005187 public void finishOtherInstances(IBinder token, ComponentName className) {
5188 synchronized(this) {
5189 final long origId = Binder.clearCallingIdentity();
5190
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005191 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 TaskRecord lastTask = null;
5193 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005194 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 if (r.realActivity.equals(className)
5196 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005197 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005198 null, "others")) {
5199 i--;
5200 N--;
5201 }
5202 }
5203 lastTask = r.task;
5204 }
5205
5206 Binder.restoreCallingIdentity(origId);
5207 }
5208 }
5209
5210 // =========================================================
5211 // THUMBNAILS
5212 // =========================================================
5213
5214 public void reportThumbnail(IBinder token,
5215 Bitmap thumbnail, CharSequence description) {
5216 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5217 final long origId = Binder.clearCallingIdentity();
5218 sendPendingThumbnail(null, token, thumbnail, description, true);
5219 Binder.restoreCallingIdentity(origId);
5220 }
5221
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005222 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 Bitmap thumbnail, CharSequence description, boolean always) {
5224 TaskRecord task = null;
5225 ArrayList receivers = null;
5226
5227 //System.out.println("Send pending thumbnail: " + r);
5228
5229 synchronized(this) {
5230 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005231 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 if (index < 0) {
5233 return;
5234 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005235 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 }
5237 if (thumbnail == null) {
5238 thumbnail = r.thumbnail;
5239 description = r.description;
5240 }
5241 if (thumbnail == null && !always) {
5242 // If there is no thumbnail, and this entry is not actually
5243 // going away, then abort for now and pick up the next
5244 // thumbnail we get.
5245 return;
5246 }
5247 task = r.task;
5248
5249 int N = mPendingThumbnails.size();
5250 int i=0;
5251 while (i<N) {
5252 PendingThumbnailsRecord pr =
5253 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5254 //System.out.println("Looking in " + pr.pendingRecords);
5255 if (pr.pendingRecords.remove(r)) {
5256 if (receivers == null) {
5257 receivers = new ArrayList();
5258 }
5259 receivers.add(pr);
5260 if (pr.pendingRecords.size() == 0) {
5261 pr.finished = true;
5262 mPendingThumbnails.remove(i);
5263 N--;
5264 continue;
5265 }
5266 }
5267 i++;
5268 }
5269 }
5270
5271 if (receivers != null) {
5272 final int N = receivers.size();
5273 for (int i=0; i<N; i++) {
5274 try {
5275 PendingThumbnailsRecord pr =
5276 (PendingThumbnailsRecord)receivers.get(i);
5277 pr.receiver.newThumbnail(
5278 task != null ? task.taskId : -1, thumbnail, description);
5279 if (pr.finished) {
5280 pr.receiver.finished();
5281 }
5282 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005283 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 }
5285 }
5286 }
5287 }
5288
5289 // =========================================================
5290 // CONTENT PROVIDERS
5291 // =========================================================
5292
5293 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5294 List providers = null;
5295 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005296 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005297 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005298 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 } catch (RemoteException ex) {
5300 }
5301 if (providers != null) {
5302 final int N = providers.size();
5303 for (int i=0; i<N; i++) {
5304 ProviderInfo cpi =
5305 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005306 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 if (cpr == null) {
5308 cpr = new ContentProviderRecord(cpi, app.info);
5309 mProvidersByClass.put(cpi.name, cpr);
5310 }
5311 app.pubProviders.put(cpi.name, cpr);
5312 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005313 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 }
5315 }
5316 return providers;
5317 }
5318
5319 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005320 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5322 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5323 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5324 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005325 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 return null;
5327 }
5328 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5329 cpi.exported ? -1 : cpi.applicationInfo.uid)
5330 == PackageManager.PERMISSION_GRANTED) {
5331 return null;
5332 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005333
5334 PathPermission[] pps = cpi.pathPermissions;
5335 if (pps != null) {
5336 int i = pps.length;
5337 while (i > 0) {
5338 i--;
5339 PathPermission pp = pps[i];
5340 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5341 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005342 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005343 return null;
5344 }
5345 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5346 cpi.exported ? -1 : cpi.applicationInfo.uid)
5347 == PackageManager.PERMISSION_GRANTED) {
5348 return null;
5349 }
5350 }
5351 }
5352
Dianne Hackbornb424b632010-08-18 15:59:05 -07005353 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5354 if (perms != null) {
5355 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5356 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5357 return null;
5358 }
5359 }
5360 }
5361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362 String msg = "Permission Denial: opening provider " + cpi.name
5363 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5364 + ", uid=" + callingUid + ") requires "
5365 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005366 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367 return msg;
5368 }
5369
5370 private final ContentProviderHolder getContentProviderImpl(
5371 IApplicationThread caller, String name) {
5372 ContentProviderRecord cpr;
5373 ProviderInfo cpi = null;
5374
5375 synchronized(this) {
5376 ProcessRecord r = null;
5377 if (caller != null) {
5378 r = getRecordForAppLocked(caller);
5379 if (r == null) {
5380 throw new SecurityException(
5381 "Unable to find app for caller " + caller
5382 + " (pid=" + Binder.getCallingPid()
5383 + ") when getting content provider " + name);
5384 }
5385 }
5386
5387 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005388 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005389 if (cpr != null) {
5390 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005391 String msg;
5392 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5393 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005394 }
5395
5396 if (r != null && cpr.canRunHere(r)) {
5397 // This provider has been published or is in the process
5398 // of being published... but it is also allowed to run
5399 // in the caller's process, so don't make a connection
5400 // and just let the caller instantiate its own instance.
5401 if (cpr.provider != null) {
5402 // don't give caller the provider object, it needs
5403 // to make its own.
5404 cpr = new ContentProviderRecord(cpr);
5405 }
5406 return cpr;
5407 }
5408
5409 final long origId = Binder.clearCallingIdentity();
5410
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005411 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005412 // return it right away.
5413 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005414 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005415 "Adding provider requested by "
5416 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005417 + cpr.info.processName);
5418 Integer cnt = r.conProviders.get(cpr);
5419 if (cnt == null) {
5420 r.conProviders.put(cpr, new Integer(1));
5421 } else {
5422 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005425 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5426 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005427 // make sure to count it as being accessed and thus
5428 // back up on the LRU list. This is good because
5429 // content providers are often expensive to start.
5430 updateLruProcessLocked(cpr.app, false, true);
5431 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005432 } else {
5433 cpr.externals++;
5434 }
5435
5436 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437 updateOomAdjLocked(cpr.app);
5438 }
5439
5440 Binder.restoreCallingIdentity(origId);
5441
5442 } else {
5443 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005444 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005445 resolveContentProvider(name,
5446 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005447 } catch (RemoteException ex) {
5448 }
5449 if (cpi == null) {
5450 return null;
5451 }
5452
Dianne Hackbornb424b632010-08-18 15:59:05 -07005453 String msg;
5454 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5455 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005456 }
5457
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005458 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005459 && !cpi.processName.equals("system")) {
5460 // If this content provider does not run in the system
5461 // process, and the system is not yet ready to run other
5462 // processes, then fail fast instead of hanging.
5463 throw new IllegalArgumentException(
5464 "Attempt to launch content provider before system ready");
5465 }
5466
Dianne Hackborn860755f2010-06-03 18:47:52 -07005467 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005468 final boolean firstClass = cpr == null;
5469 if (firstClass) {
5470 try {
5471 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005472 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 getApplicationInfo(
5474 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005475 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005476 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005477 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 + cpi.name);
5479 return null;
5480 }
5481 cpr = new ContentProviderRecord(cpi, ai);
5482 } catch (RemoteException ex) {
5483 // pm is in same process, this will never happen.
5484 }
5485 }
5486
5487 if (r != null && cpr.canRunHere(r)) {
5488 // If this is a multiprocess provider, then just return its
5489 // info and allow the caller to instantiate it. Only do
5490 // this if the provider is the same user as the caller's
5491 // process, or can run as root (so can be in any process).
5492 return cpr;
5493 }
5494
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005495 if (DEBUG_PROVIDER) {
5496 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005497 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005498 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 }
5500
5501 // This is single process, and our app is now connecting to it.
5502 // See if we are already in the process of launching this
5503 // provider.
5504 final int N = mLaunchingProviders.size();
5505 int i;
5506 for (i=0; i<N; i++) {
5507 if (mLaunchingProviders.get(i) == cpr) {
5508 break;
5509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 }
5511
5512 // If the provider is not already being launched, then get it
5513 // started.
5514 if (i >= N) {
5515 final long origId = Binder.clearCallingIdentity();
5516 ProcessRecord proc = startProcessLocked(cpi.processName,
5517 cpr.appInfo, false, 0, "content provider",
5518 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005519 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005520 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005521 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005522 + cpi.applicationInfo.packageName + "/"
5523 + cpi.applicationInfo.uid + " for provider "
5524 + name + ": process is bad");
5525 return null;
5526 }
5527 cpr.launchingApp = proc;
5528 mLaunchingProviders.add(cpr);
5529 Binder.restoreCallingIdentity(origId);
5530 }
5531
5532 // Make sure the provider is published (the same provider class
5533 // may be published under multiple names).
5534 if (firstClass) {
5535 mProvidersByClass.put(cpi.name, cpr);
5536 }
5537 mProvidersByName.put(name, cpr);
5538
5539 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005540 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005541 "Adding provider requested by "
5542 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005543 + cpr.info.processName);
5544 Integer cnt = r.conProviders.get(cpr);
5545 if (cnt == null) {
5546 r.conProviders.put(cpr, new Integer(1));
5547 } else {
5548 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5549 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005550 cpr.clients.add(r);
5551 } else {
5552 cpr.externals++;
5553 }
5554 }
5555 }
5556
5557 // Wait for the provider to be published...
5558 synchronized (cpr) {
5559 while (cpr.provider == null) {
5560 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005561 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005562 + cpi.applicationInfo.packageName + "/"
5563 + cpi.applicationInfo.uid + " for provider "
5564 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005565 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005566 cpi.applicationInfo.packageName,
5567 cpi.applicationInfo.uid, name);
5568 return null;
5569 }
5570 try {
5571 cpr.wait();
5572 } catch (InterruptedException ex) {
5573 }
5574 }
5575 }
5576 return cpr;
5577 }
5578
5579 public final ContentProviderHolder getContentProvider(
5580 IApplicationThread caller, String name) {
5581 if (caller == null) {
5582 String msg = "null IApplicationThread when getting content provider "
5583 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005584 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005585 throw new SecurityException(msg);
5586 }
5587
5588 return getContentProviderImpl(caller, name);
5589 }
5590
5591 private ContentProviderHolder getContentProviderExternal(String name) {
5592 return getContentProviderImpl(null, name);
5593 }
5594
5595 /**
5596 * Drop a content provider from a ProcessRecord's bookkeeping
5597 * @param cpr
5598 */
5599 public void removeContentProvider(IApplicationThread caller, String name) {
5600 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005601 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005602 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005603 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005604 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005605 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005606 return;
5607 }
5608 final ProcessRecord r = getRecordForAppLocked(caller);
5609 if (r == null) {
5610 throw new SecurityException(
5611 "Unable to find app for caller " + caller +
5612 " when removing content provider " + name);
5613 }
5614 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005615 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005616 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005617 + r.info.processName + " from process "
5618 + localCpr.appInfo.processName);
5619 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005621 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005622 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 return;
5624 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005625 Integer cnt = r.conProviders.get(localCpr);
5626 if (cnt == null || cnt.intValue() <= 1) {
5627 localCpr.clients.remove(r);
5628 r.conProviders.remove(localCpr);
5629 } else {
5630 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 }
5633 updateOomAdjLocked();
5634 }
5635 }
5636
5637 private void removeContentProviderExternal(String name) {
5638 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005639 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 if(cpr == null) {
5641 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005642 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005643 return;
5644 }
5645
5646 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005647 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005648 localCpr.externals--;
5649 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005650 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005651 }
5652 updateOomAdjLocked();
5653 }
5654 }
5655
5656 public final void publishContentProviders(IApplicationThread caller,
5657 List<ContentProviderHolder> providers) {
5658 if (providers == null) {
5659 return;
5660 }
5661
5662 synchronized(this) {
5663 final ProcessRecord r = getRecordForAppLocked(caller);
5664 if (r == null) {
5665 throw new SecurityException(
5666 "Unable to find app for caller " + caller
5667 + " (pid=" + Binder.getCallingPid()
5668 + ") when publishing content providers");
5669 }
5670
5671 final long origId = Binder.clearCallingIdentity();
5672
5673 final int N = providers.size();
5674 for (int i=0; i<N; i++) {
5675 ContentProviderHolder src = providers.get(i);
5676 if (src == null || src.info == null || src.provider == null) {
5677 continue;
5678 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005679 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005680 if (dst != null) {
5681 mProvidersByClass.put(dst.info.name, dst);
5682 String names[] = dst.info.authority.split(";");
5683 for (int j = 0; j < names.length; j++) {
5684 mProvidersByName.put(names[j], dst);
5685 }
5686
5687 int NL = mLaunchingProviders.size();
5688 int j;
5689 for (j=0; j<NL; j++) {
5690 if (mLaunchingProviders.get(j) == dst) {
5691 mLaunchingProviders.remove(j);
5692 j--;
5693 NL--;
5694 }
5695 }
5696 synchronized (dst) {
5697 dst.provider = src.provider;
5698 dst.app = r;
5699 dst.notifyAll();
5700 }
5701 updateOomAdjLocked(r);
5702 }
5703 }
5704
5705 Binder.restoreCallingIdentity(origId);
5706 }
5707 }
5708
5709 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005710 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005711 synchronized (mSelf) {
5712 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5713 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005714 if (providers != null) {
5715 for (int i=providers.size()-1; i>=0; i--) {
5716 ProviderInfo pi = (ProviderInfo)providers.get(i);
5717 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5718 Slog.w(TAG, "Not installing system proc provider " + pi.name
5719 + ": not system .apk");
5720 providers.remove(i);
5721 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005722 }
5723 }
5724 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005725 if (providers != null) {
5726 mSystemThread.installSystemProviders(providers);
5727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005728 }
5729
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005730 /**
5731 * Allows app to retrieve the MIME type of a URI without having permission
5732 * to access its content provider.
5733 *
5734 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5735 *
5736 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5737 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5738 */
5739 public String getProviderMimeType(Uri uri) {
5740 final String name = uri.getAuthority();
5741 final long ident = Binder.clearCallingIdentity();
5742 ContentProviderHolder holder = null;
5743
5744 try {
5745 holder = getContentProviderExternal(name);
5746 if (holder != null) {
5747 return holder.provider.getType(uri);
5748 }
5749 } catch (RemoteException e) {
5750 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5751 return null;
5752 } finally {
5753 if (holder != null) {
5754 removeContentProviderExternal(name);
5755 }
5756 Binder.restoreCallingIdentity(ident);
5757 }
5758
5759 return null;
5760 }
5761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005762 // =========================================================
5763 // GLOBAL MANAGEMENT
5764 // =========================================================
5765
5766 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5767 ApplicationInfo info, String customProcess) {
5768 String proc = customProcess != null ? customProcess : info.processName;
5769 BatteryStatsImpl.Uid.Proc ps = null;
5770 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5771 synchronized (stats) {
5772 ps = stats.getProcessStatsLocked(info.uid, proc);
5773 }
5774 return new ProcessRecord(ps, thread, info, proc);
5775 }
5776
5777 final ProcessRecord addAppLocked(ApplicationInfo info) {
5778 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5779
5780 if (app == null) {
5781 app = newProcessRecordLocked(null, info, null);
5782 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005783 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005784 }
5785
5786 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5787 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5788 app.persistent = true;
5789 app.maxAdj = CORE_SERVER_ADJ;
5790 }
5791 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5792 mPersistentStartingProcesses.add(app);
5793 startProcessLocked(app, "added application", app.processName);
5794 }
5795
5796 return app;
5797 }
5798
5799 public void unhandledBack() {
5800 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5801 "unhandledBack()");
5802
5803 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005804 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005805 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 TAG, "Performing unhandledBack(): stack size = " + count);
5807 if (count > 1) {
5808 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005809 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005810 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5811 Binder.restoreCallingIdentity(origId);
5812 }
5813 }
5814 }
5815
5816 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5817 String name = uri.getAuthority();
5818 ContentProviderHolder cph = getContentProviderExternal(name);
5819 ParcelFileDescriptor pfd = null;
5820 if (cph != null) {
5821 // We record the binder invoker's uid in thread-local storage before
5822 // going to the content provider to open the file. Later, in the code
5823 // that handles all permissions checks, we look for this uid and use
5824 // that rather than the Activity Manager's own uid. The effect is that
5825 // we do the check against the caller's permissions even though it looks
5826 // to the content provider like the Activity Manager itself is making
5827 // the request.
5828 sCallerIdentity.set(new Identity(
5829 Binder.getCallingPid(), Binder.getCallingUid()));
5830 try {
5831 pfd = cph.provider.openFile(uri, "r");
5832 } catch (FileNotFoundException e) {
5833 // do nothing; pfd will be returned null
5834 } finally {
5835 // Ensure that whatever happens, we clean up the identity state
5836 sCallerIdentity.remove();
5837 }
5838
5839 // We've got the fd now, so we're done with the provider.
5840 removeContentProviderExternal(name);
5841 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005842 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 }
5844 return pfd;
5845 }
5846
5847 public void goingToSleep() {
5848 synchronized(this) {
5849 mSleeping = true;
5850 mWindowManager.setEventDispatching(false);
5851
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005852 if (mMainStack.mResumedActivity != null) {
5853 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005854 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005855 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005856 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005857
5858 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005859 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005860 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5861 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005862 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 }
5864 }
5865
Dianne Hackborn55280a92009-05-07 15:53:46 -07005866 public boolean shutdown(int timeout) {
5867 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5868 != PackageManager.PERMISSION_GRANTED) {
5869 throw new SecurityException("Requires permission "
5870 + android.Manifest.permission.SHUTDOWN);
5871 }
5872
5873 boolean timedout = false;
5874
5875 synchronized(this) {
5876 mShuttingDown = true;
5877 mWindowManager.setEventDispatching(false);
5878
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005879 if (mMainStack.mResumedActivity != null) {
5880 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005881 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005882 while (mMainStack.mResumedActivity != null
5883 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005884 long delay = endTime - System.currentTimeMillis();
5885 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005886 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005887 timedout = true;
5888 break;
5889 }
5890 try {
5891 this.wait();
5892 } catch (InterruptedException e) {
5893 }
5894 }
5895 }
5896 }
5897
5898 mUsageStatsService.shutdown();
5899 mBatteryStatsService.shutdown();
5900
5901 return timedout;
5902 }
5903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 public void wakingUp() {
5905 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005906 if (mMainStack.mGoingToSleep.isHeld()) {
5907 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005908 }
5909 mWindowManager.setEventDispatching(true);
5910 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005911 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005912 }
5913 }
5914
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005915 public void stopAppSwitches() {
5916 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5917 != PackageManager.PERMISSION_GRANTED) {
5918 throw new SecurityException("Requires permission "
5919 + android.Manifest.permission.STOP_APP_SWITCHES);
5920 }
5921
5922 synchronized(this) {
5923 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5924 + APP_SWITCH_DELAY_TIME;
5925 mDidAppSwitch = false;
5926 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5927 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5928 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5929 }
5930 }
5931
5932 public void resumeAppSwitches() {
5933 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5934 != PackageManager.PERMISSION_GRANTED) {
5935 throw new SecurityException("Requires permission "
5936 + android.Manifest.permission.STOP_APP_SWITCHES);
5937 }
5938
5939 synchronized(this) {
5940 // Note that we don't execute any pending app switches... we will
5941 // let those wait until either the timeout, or the next start
5942 // activity request.
5943 mAppSwitchesAllowedTime = 0;
5944 }
5945 }
5946
5947 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5948 String name) {
5949 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5950 return true;
5951 }
5952
5953 final int perm = checkComponentPermission(
5954 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5955 callingUid, -1);
5956 if (perm == PackageManager.PERMISSION_GRANTED) {
5957 return true;
5958 }
5959
Joe Onorato8a9b2202010-02-26 18:56:32 -08005960 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005961 return false;
5962 }
5963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 public void setDebugApp(String packageName, boolean waitForDebugger,
5965 boolean persistent) {
5966 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5967 "setDebugApp()");
5968
5969 // Note that this is not really thread safe if there are multiple
5970 // callers into it at the same time, but that's not a situation we
5971 // care about.
5972 if (persistent) {
5973 final ContentResolver resolver = mContext.getContentResolver();
5974 Settings.System.putString(
5975 resolver, Settings.System.DEBUG_APP,
5976 packageName);
5977 Settings.System.putInt(
5978 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5979 waitForDebugger ? 1 : 0);
5980 }
5981
5982 synchronized (this) {
5983 if (!persistent) {
5984 mOrigDebugApp = mDebugApp;
5985 mOrigWaitForDebugger = mWaitForDebugger;
5986 }
5987 mDebugApp = packageName;
5988 mWaitForDebugger = waitForDebugger;
5989 mDebugTransient = !persistent;
5990 if (packageName != null) {
5991 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005992 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005993 Binder.restoreCallingIdentity(origId);
5994 }
5995 }
5996 }
5997
5998 public void setAlwaysFinish(boolean enabled) {
5999 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6000 "setAlwaysFinish()");
6001
6002 Settings.System.putInt(
6003 mContext.getContentResolver(),
6004 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6005
6006 synchronized (this) {
6007 mAlwaysFinishActivities = enabled;
6008 }
6009 }
6010
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006011 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006013 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006015 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006016 }
6017 }
6018
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006019 public boolean isUserAMonkey() {
6020 // For now the fact that there is a controller implies
6021 // we have a monkey.
6022 synchronized (this) {
6023 return mController != null;
6024 }
6025 }
6026
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006027 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006028 synchronized (this) {
6029 mWatchers.register(watcher);
6030 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006031 }
6032
6033 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006034 synchronized (this) {
6035 mWatchers.unregister(watcher);
6036 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006037 }
6038
Daniel Sandler69a48172010-06-23 16:29:36 -04006039 public void setImmersive(IBinder token, boolean immersive) {
6040 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006041 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006042 if (index < 0) {
6043 throw new IllegalArgumentException();
6044 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006045 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006046 r.immersive = immersive;
6047 }
6048 }
6049
6050 public boolean isImmersive(IBinder token) {
6051 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006052 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006053 if (index < 0) {
6054 throw new IllegalArgumentException();
6055 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006056 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006057 return r.immersive;
6058 }
6059 }
6060
6061 public boolean isTopActivityImmersive() {
6062 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006063 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006064 return (r != null) ? r.immersive : false;
6065 }
6066 }
6067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006068 public final void enterSafeMode() {
6069 synchronized(this) {
6070 // It only makes sense to do this before the system is ready
6071 // and started launching other packages.
6072 if (!mSystemReady) {
6073 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006074 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006075 } catch (RemoteException e) {
6076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006077 }
6078 }
6079 }
6080
Jeff Brownb09abc12011-01-13 21:08:27 -08006081 public final void showSafeModeOverlay() {
6082 View v = LayoutInflater.from(mContext).inflate(
6083 com.android.internal.R.layout.safe_mode, null);
6084 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6085 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6086 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6087 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6088 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6089 lp.format = v.getBackground().getOpacity();
6090 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6091 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6092 ((WindowManager)mContext.getSystemService(
6093 Context.WINDOW_SERVICE)).addView(v, lp);
6094 }
6095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006096 public void noteWakeupAlarm(IIntentSender sender) {
6097 if (!(sender instanceof PendingIntentRecord)) {
6098 return;
6099 }
6100 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6101 synchronized (stats) {
6102 if (mBatteryStatsService.isOnBattery()) {
6103 mBatteryStatsService.enforceCallingPermission();
6104 PendingIntentRecord rec = (PendingIntentRecord)sender;
6105 int MY_UID = Binder.getCallingUid();
6106 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6107 BatteryStatsImpl.Uid.Pkg pkg =
6108 stats.getPackageStatsLocked(uid, rec.key.packageName);
6109 pkg.incWakeupsLocked();
6110 }
6111 }
6112 }
6113
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006114 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006116 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006117 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006118 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006119 // XXX Note: don't acquire main activity lock here, because the window
6120 // manager calls in with its locks held.
6121
6122 boolean killed = false;
6123 synchronized (mPidsSelfLocked) {
6124 int[] types = new int[pids.length];
6125 int worstType = 0;
6126 for (int i=0; i<pids.length; i++) {
6127 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6128 if (proc != null) {
6129 int type = proc.setAdj;
6130 types[i] = type;
6131 if (type > worstType) {
6132 worstType = type;
6133 }
6134 }
6135 }
6136
6137 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6138 // then constrain it so we will kill all hidden procs.
6139 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6140 worstType = HIDDEN_APP_MIN_ADJ;
6141 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006142 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006143 for (int i=0; i<pids.length; i++) {
6144 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6145 if (proc == null) {
6146 continue;
6147 }
6148 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006149 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006150 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006151 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6152 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006154 proc.killedBackground = true;
6155 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006156 }
6157 }
6158 }
6159 return killed;
6160 }
6161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006162 public final void startRunning(String pkg, String cls, String action,
6163 String data) {
6164 synchronized(this) {
6165 if (mStartRunning) {
6166 return;
6167 }
6168 mStartRunning = true;
6169 mTopComponent = pkg != null && cls != null
6170 ? new ComponentName(pkg, cls) : null;
6171 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6172 mTopData = data;
6173 if (!mSystemReady) {
6174 return;
6175 }
6176 }
6177
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006178 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006179 }
6180
6181 private void retrieveSettings() {
6182 final ContentResolver resolver = mContext.getContentResolver();
6183 String debugApp = Settings.System.getString(
6184 resolver, Settings.System.DEBUG_APP);
6185 boolean waitForDebugger = Settings.System.getInt(
6186 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6187 boolean alwaysFinishActivities = Settings.System.getInt(
6188 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6189
6190 Configuration configuration = new Configuration();
6191 Settings.System.getConfiguration(resolver, configuration);
6192
6193 synchronized (this) {
6194 mDebugApp = mOrigDebugApp = debugApp;
6195 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6196 mAlwaysFinishActivities = alwaysFinishActivities;
6197 // This happens before any activities are started, so we can
6198 // change mConfiguration in-place.
6199 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006200 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006201 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006202 }
6203 }
6204
6205 public boolean testIsSystemReady() {
6206 // no need to synchronize(this) just to read & return the value
6207 return mSystemReady;
6208 }
6209
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006210 private static File getCalledPreBootReceiversFile() {
6211 File dataDir = Environment.getDataDirectory();
6212 File systemDir = new File(dataDir, "system");
6213 File fname = new File(systemDir, "called_pre_boots.dat");
6214 return fname;
6215 }
6216
6217 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6218 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6219 File file = getCalledPreBootReceiversFile();
6220 FileInputStream fis = null;
6221 try {
6222 fis = new FileInputStream(file);
6223 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6224 int vers = dis.readInt();
6225 String codename = dis.readUTF();
6226 if (vers == android.os.Build.VERSION.SDK_INT
6227 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6228 int num = dis.readInt();
6229 while (num > 0) {
6230 num--;
6231 String pkg = dis.readUTF();
6232 String cls = dis.readUTF();
6233 lastDoneReceivers.add(new ComponentName(pkg, cls));
6234 }
6235 }
6236 } catch (FileNotFoundException e) {
6237 } catch (IOException e) {
6238 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6239 } finally {
6240 if (fis != null) {
6241 try {
6242 fis.close();
6243 } catch (IOException e) {
6244 }
6245 }
6246 }
6247 return lastDoneReceivers;
6248 }
6249
6250 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6251 File file = getCalledPreBootReceiversFile();
6252 FileOutputStream fos = null;
6253 DataOutputStream dos = null;
6254 try {
6255 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6256 fos = new FileOutputStream(file);
6257 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6258 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6259 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6260 dos.writeInt(list.size());
6261 for (int i=0; i<list.size(); i++) {
6262 dos.writeUTF(list.get(i).getPackageName());
6263 dos.writeUTF(list.get(i).getClassName());
6264 }
6265 } catch (IOException e) {
6266 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6267 file.delete();
6268 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006269 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006270 if (dos != null) {
6271 try {
6272 dos.close();
6273 } catch (IOException e) {
6274 // TODO Auto-generated catch block
6275 e.printStackTrace();
6276 }
6277 }
6278 }
6279 }
6280
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006281 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006282 // In the simulator, startRunning will never have been called, which
6283 // normally sets a few crucial variables. Do it here instead.
6284 if (!Process.supportsProcesses()) {
6285 mStartRunning = true;
6286 mTopAction = Intent.ACTION_MAIN;
6287 }
6288
6289 synchronized(this) {
6290 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006291 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 return;
6293 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006294
6295 // Check to see if there are any update receivers to run.
6296 if (!mDidUpdate) {
6297 if (mWaitingUpdate) {
6298 return;
6299 }
6300 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6301 List<ResolveInfo> ris = null;
6302 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006303 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006304 intent, null, 0);
6305 } catch (RemoteException e) {
6306 }
6307 if (ris != null) {
6308 for (int i=ris.size()-1; i>=0; i--) {
6309 if ((ris.get(i).activityInfo.applicationInfo.flags
6310 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6311 ris.remove(i);
6312 }
6313 }
6314 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006315
6316 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6317
6318 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006319 for (int i=0; i<ris.size(); i++) {
6320 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006321 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6322 if (lastDoneReceivers.contains(comp)) {
6323 ris.remove(i);
6324 i--;
6325 }
6326 }
6327
6328 for (int i=0; i<ris.size(); i++) {
6329 ActivityInfo ai = ris.get(i).activityInfo;
6330 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6331 doneReceivers.add(comp);
6332 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006333 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006334 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006335 finisher = new IIntentReceiver.Stub() {
6336 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006337 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006338 boolean sticky) {
6339 // The raw IIntentReceiver interface is called
6340 // with the AM lock held, so redispatch to
6341 // execute our code without the lock.
6342 mHandler.post(new Runnable() {
6343 public void run() {
6344 synchronized (ActivityManagerService.this) {
6345 mDidUpdate = true;
6346 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006347 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006348 systemReady(goingCallback);
6349 }
6350 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006351 }
6352 };
6353 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006354 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006355 broadcastIntentLocked(null, null, intent, null, finisher,
6356 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006357 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006358 mWaitingUpdate = true;
6359 }
6360 }
6361 }
6362 if (mWaitingUpdate) {
6363 return;
6364 }
6365 mDidUpdate = true;
6366 }
6367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006368 mSystemReady = true;
6369 if (!mStartRunning) {
6370 return;
6371 }
6372 }
6373
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006374 ArrayList<ProcessRecord> procsToKill = null;
6375 synchronized(mPidsSelfLocked) {
6376 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6377 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6378 if (!isAllowedWhileBooting(proc.info)){
6379 if (procsToKill == null) {
6380 procsToKill = new ArrayList<ProcessRecord>();
6381 }
6382 procsToKill.add(proc);
6383 }
6384 }
6385 }
6386
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006387 synchronized(this) {
6388 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006389 for (int i=procsToKill.size()-1; i>=0; i--) {
6390 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006391 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006392 removeProcessLocked(proc, true);
6393 }
6394 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006395
6396 // Now that we have cleaned up any update processes, we
6397 // are ready to start launching real processes and know that
6398 // we won't trample on them any more.
6399 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006400 }
6401
Joe Onorato8a9b2202010-02-26 18:56:32 -08006402 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006403 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006404 SystemClock.uptimeMillis());
6405
6406 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006407 // Make sure we have no pre-ready processes sitting around.
6408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006409 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6410 ResolveInfo ri = mContext.getPackageManager()
6411 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006412 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 CharSequence errorMsg = null;
6414 if (ri != null) {
6415 ActivityInfo ai = ri.activityInfo;
6416 ApplicationInfo app = ai.applicationInfo;
6417 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6418 mTopAction = Intent.ACTION_FACTORY_TEST;
6419 mTopData = null;
6420 mTopComponent = new ComponentName(app.packageName,
6421 ai.name);
6422 } else {
6423 errorMsg = mContext.getResources().getText(
6424 com.android.internal.R.string.factorytest_not_system);
6425 }
6426 } else {
6427 errorMsg = mContext.getResources().getText(
6428 com.android.internal.R.string.factorytest_no_action);
6429 }
6430 if (errorMsg != null) {
6431 mTopAction = null;
6432 mTopData = null;
6433 mTopComponent = null;
6434 Message msg = Message.obtain();
6435 msg.what = SHOW_FACTORY_ERROR_MSG;
6436 msg.getData().putCharSequence("msg", errorMsg);
6437 mHandler.sendMessage(msg);
6438 }
6439 }
6440 }
6441
6442 retrieveSettings();
6443
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006444 if (goingCallback != null) goingCallback.run();
6445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 synchronized (this) {
6447 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6448 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006449 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006450 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 if (apps != null) {
6452 int N = apps.size();
6453 int i;
6454 for (i=0; i<N; i++) {
6455 ApplicationInfo info
6456 = (ApplicationInfo)apps.get(i);
6457 if (info != null &&
6458 !info.packageName.equals("android")) {
6459 addAppLocked(info);
6460 }
6461 }
6462 }
6463 } catch (RemoteException ex) {
6464 // pm is in same process, this will never happen.
6465 }
6466 }
6467
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006468 // Start up initial activity.
6469 mBooting = true;
6470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006472 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006473 Message msg = Message.obtain();
6474 msg.what = SHOW_UID_ERROR_MSG;
6475 mHandler.sendMessage(msg);
6476 }
6477 } catch (RemoteException e) {
6478 }
6479
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006480 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 }
6482 }
6483
Dan Egnorb7f03672009-12-09 16:22:32 -08006484 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006485 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006487 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006488 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006489 startAppProblemLocked(app);
6490 app.stopFreezingAllLocked();
6491 return handleAppCrashLocked(app);
6492 }
6493
Dan Egnorb7f03672009-12-09 16:22:32 -08006494 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006495 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006497 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006498 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6499 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006500 startAppProblemLocked(app);
6501 app.stopFreezingAllLocked();
6502 }
6503
6504 /**
6505 * Generate a process error record, suitable for attachment to a ProcessRecord.
6506 *
6507 * @param app The ProcessRecord in which the error occurred.
6508 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6509 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006510 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006511 * @param shortMsg Short message describing the crash.
6512 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006513 * @param stackTrace Full crash stack trace, may be null.
6514 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 * @return Returns a fully-formed AppErrorStateInfo record.
6516 */
6517 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006518 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006521 report.condition = condition;
6522 report.processName = app.processName;
6523 report.pid = app.pid;
6524 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006525 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006526 report.shortMsg = shortMsg;
6527 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006528 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006529
6530 return report;
6531 }
6532
Dan Egnor42471dd2010-01-07 17:25:22 -08006533 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006534 synchronized (this) {
6535 app.crashing = false;
6536 app.crashingReport = null;
6537 app.notResponding = false;
6538 app.notRespondingReport = null;
6539 if (app.anrDialog == fromDialog) {
6540 app.anrDialog = null;
6541 }
6542 if (app.waitDialog == fromDialog) {
6543 app.waitDialog = null;
6544 }
6545 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006546 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006547 Slog.i(ActivityManagerService.TAG, "Killing "
6548 + app.processName + " (pid=" + app.pid + "): user's request");
6549 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6550 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006551 Process.killProcess(app.pid);
6552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 }
6554 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006555
Dan Egnorb7f03672009-12-09 16:22:32 -08006556 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006557 long now = SystemClock.uptimeMillis();
6558
6559 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6560 app.info.uid);
6561 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6562 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006563 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006565 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006567 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6568 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006569 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006570 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006571 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006572 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006573 }
6574 }
6575 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006576 // Don't let services in this process be restarted and potentially
6577 // annoy the user repeatedly. Unless it is persistent, since those
6578 // processes run critical code.
6579 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006580 // We don't want to start this process again until the user
6581 // explicitly does so... but for persistent process, we really
6582 // need to keep it running. If a persistent process is actually
6583 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006584 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006585 app.info.processName);
6586 mBadProcesses.put(app.info.processName, app.info.uid, now);
6587 app.bad = true;
6588 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6589 app.removed = true;
6590 removeProcessLocked(app, false);
6591 return false;
6592 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006593 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006594 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006595 if (r.app == app) {
6596 // If the top running activity is from this crashing
6597 // process, then terminate it to avoid getting in a loop.
6598 Slog.w(TAG, " Force finishing activity "
6599 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006600 int index = mMainStack.indexOfTokenLocked(r);
6601 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006602 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006603 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006604 // stopped, to avoid a situation where one will get
6605 // re-start our crashing activity once it gets resumed again.
6606 index--;
6607 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006608 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006609 if (r.state == ActivityState.RESUMED
6610 || r.state == ActivityState.PAUSING
6611 || r.state == ActivityState.PAUSED) {
6612 if (!r.isHomeActivity) {
6613 Slog.w(TAG, " Force finishing activity "
6614 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006615 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006616 Activity.RESULT_CANCELED, null, "crashed");
6617 }
6618 }
6619 }
6620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006621 }
6622
6623 // Bump up the crash count of any services currently running in the proc.
6624 if (app.services.size() != 0) {
6625 // Any services running in the application need to be placed
6626 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006627 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006629 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006630 sr.crashCount++;
6631 }
6632 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006633
6634 // If the crashing process is what we consider to be the "home process" and it has been
6635 // replaced by a third-party app, clear the package preferred activities from packages
6636 // with a home activity running in the process to prevent a repeatedly crashing app
6637 // from blocking the user to manually clear the list.
6638 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6639 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6640 Iterator it = mHomeProcess.activities.iterator();
6641 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006642 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006643 if (r.isHomeActivity) {
6644 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6645 try {
6646 ActivityThread.getPackageManager()
6647 .clearPackagePreferredActivities(r.packageName);
6648 } catch (RemoteException c) {
6649 // pm is in same process, this will never happen.
6650 }
6651 }
6652 }
6653 }
6654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006655 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6656 return true;
6657 }
6658
6659 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006660 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6661 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 skipCurrentReceiverLocked(app);
6663 }
6664
6665 void skipCurrentReceiverLocked(ProcessRecord app) {
6666 boolean reschedule = false;
6667 BroadcastRecord r = app.curReceiver;
6668 if (r != null) {
6669 // The current broadcast is waiting for this app's receiver
6670 // to be finished. Looks like that's not going to happen, so
6671 // let the broadcast continue.
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 r = mPendingBroadcast;
6678 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006679 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006680 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006681 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006682 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6683 r.resultExtras, r.resultAbort, true);
6684 reschedule = true;
6685 }
6686 if (reschedule) {
6687 scheduleBroadcastsLocked();
6688 }
6689 }
6690
Dan Egnor60d87622009-12-16 16:32:58 -08006691 /**
6692 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6693 * The application process will exit immediately after this call returns.
6694 * @param app object of the crashing app, null for the system server
6695 * @param crashInfo describing the exception
6696 */
6697 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6698 ProcessRecord r = findAppProcess(app);
6699
6700 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6701 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006702 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006703 crashInfo.exceptionClassName,
6704 crashInfo.exceptionMessage,
6705 crashInfo.throwFileName,
6706 crashInfo.throwLineNumber);
6707
Dan Egnor42471dd2010-01-07 17:25:22 -08006708 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006709
6710 crashApplication(r, crashInfo);
6711 }
6712
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006713 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006714 IBinder app,
6715 int violationMask,
6716 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006717 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006718
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006719 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006720 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006721 boolean logIt = true;
6722 synchronized (mAlreadyLoggedViolatedStacks) {
6723 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6724 logIt = false;
6725 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006726 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006727 // the relative pain numbers, without logging all
6728 // the stack traces repeatedly. We'd want to do
6729 // likewise in the client code, which also does
6730 // dup suppression, before the Binder call.
6731 } else {
6732 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6733 mAlreadyLoggedViolatedStacks.clear();
6734 }
6735 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6736 }
6737 }
6738 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006739 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006740 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006741 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006742
6743 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6744 AppErrorResult result = new AppErrorResult();
6745 synchronized (this) {
6746 final long origId = Binder.clearCallingIdentity();
6747
6748 Message msg = Message.obtain();
6749 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6750 HashMap<String, Object> data = new HashMap<String, Object>();
6751 data.put("result", result);
6752 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006753 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006754 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006755 msg.obj = data;
6756 mHandler.sendMessage(msg);
6757
6758 Binder.restoreCallingIdentity(origId);
6759 }
6760 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006761 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006762 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006763 }
6764
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006765 // Depending on the policy in effect, there could be a bunch of
6766 // these in quick succession so we try to batch these together to
6767 // minimize disk writes, number of dropbox entries, and maximize
6768 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006769 private void logStrictModeViolationToDropBox(
6770 ProcessRecord process,
6771 StrictMode.ViolationInfo info) {
6772 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006773 return;
6774 }
6775 final boolean isSystemApp = process == null ||
6776 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6777 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6778 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6779 final DropBoxManager dbox = (DropBoxManager)
6780 mContext.getSystemService(Context.DROPBOX_SERVICE);
6781
6782 // Exit early if the dropbox isn't configured to accept this report type.
6783 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6784
6785 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006786 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006787 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6788 synchronized (sb) {
6789 bufferWasEmpty = sb.length() == 0;
6790 appendDropBoxProcessHeaders(process, sb);
6791 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6792 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006793 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6794 if (info.violationNumThisLoop != 0) {
6795 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6796 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006797 if (info.numAnimationsRunning != 0) {
6798 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6799 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006800 if (info.broadcastIntentAction != null) {
6801 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6802 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006803 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006804 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006805 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006806 if (info.tags != null) {
6807 for (String tag : info.tags) {
6808 sb.append("Span-Tag: ").append(tag).append("\n");
6809 }
6810 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006811 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006812 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6813 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006814 }
6815 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006816
6817 // Only buffer up to ~64k. Various logging bits truncate
6818 // things at 128k.
6819 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006820 }
6821
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006822 // Flush immediately if the buffer's grown too large, or this
6823 // is a non-system app. Non-system apps are isolated with a
6824 // different tag & policy and not batched.
6825 //
6826 // Batching is useful during internal testing with
6827 // StrictMode settings turned up high. Without batching,
6828 // thousands of separate files could be created on boot.
6829 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006830 new Thread("Error dump: " + dropboxTag) {
6831 @Override
6832 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006833 String report;
6834 synchronized (sb) {
6835 report = sb.toString();
6836 sb.delete(0, sb.length());
6837 sb.trimToSize();
6838 }
6839 if (report.length() != 0) {
6840 dbox.addText(dropboxTag, report);
6841 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006842 }
6843 }.start();
6844 return;
6845 }
6846
6847 // System app batching:
6848 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006849 // An existing dropbox-writing thread is outstanding, so
6850 // we don't need to start it up. The existing thread will
6851 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006852 return;
6853 }
6854
6855 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6856 // (After this point, we shouldn't access AMS internal data structures.)
6857 new Thread("Error dump: " + dropboxTag) {
6858 @Override
6859 public void run() {
6860 // 5 second sleep to let stacks arrive and be batched together
6861 try {
6862 Thread.sleep(5000); // 5 seconds
6863 } catch (InterruptedException e) {}
6864
6865 String errorReport;
6866 synchronized (mStrictModeBuffer) {
6867 errorReport = mStrictModeBuffer.toString();
6868 if (errorReport.length() == 0) {
6869 return;
6870 }
6871 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6872 mStrictModeBuffer.trimToSize();
6873 }
6874 dbox.addText(dropboxTag, errorReport);
6875 }
6876 }.start();
6877 }
6878
Dan Egnor60d87622009-12-16 16:32:58 -08006879 /**
6880 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6881 * @param app object of the crashing app, null for the system server
6882 * @param tag reported by the caller
6883 * @param crashInfo describing the context of the error
6884 * @return true if the process should exit immediately (WTF is fatal)
6885 */
6886 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006887 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006888 ProcessRecord r = findAppProcess(app);
6889
6890 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6891 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006892 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006893 tag, crashInfo.exceptionMessage);
6894
Dan Egnor42471dd2010-01-07 17:25:22 -08006895 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006896
Doug Zongker43866e02010-01-07 12:09:54 -08006897 if (Settings.Secure.getInt(mContext.getContentResolver(),
6898 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006899 crashApplication(r, crashInfo);
6900 return true;
6901 } else {
6902 return false;
6903 }
6904 }
6905
6906 /**
6907 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6908 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6909 */
6910 private ProcessRecord findAppProcess(IBinder app) {
6911 if (app == null) {
6912 return null;
6913 }
6914
6915 synchronized (this) {
6916 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6917 final int NA = apps.size();
6918 for (int ia=0; ia<NA; ia++) {
6919 ProcessRecord p = apps.valueAt(ia);
6920 if (p.thread != null && p.thread.asBinder() == app) {
6921 return p;
6922 }
6923 }
6924 }
6925
Joe Onorato8a9b2202010-02-26 18:56:32 -08006926 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006927 return null;
6928 }
6929 }
6930
6931 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006932 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6933 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006934 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006935 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6936 // Note: ProcessRecord 'process' is guarded by the service
6937 // instance. (notably process.pkgList, which could otherwise change
6938 // concurrently during execution of this method)
6939 synchronized (this) {
6940 if (process == null || process.pid == MY_PID) {
6941 sb.append("Process: system_server\n");
6942 } else {
6943 sb.append("Process: ").append(process.processName).append("\n");
6944 }
6945 if (process == null) {
6946 return;
6947 }
Dan Egnora455d192010-03-12 08:52:28 -08006948 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006949 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006950 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6951 for (String pkg : process.pkgList) {
6952 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006953 try {
Dan Egnora455d192010-03-12 08:52:28 -08006954 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6955 if (pi != null) {
6956 sb.append(" v").append(pi.versionCode);
6957 if (pi.versionName != null) {
6958 sb.append(" (").append(pi.versionName).append(")");
6959 }
6960 }
6961 } catch (RemoteException e) {
6962 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006963 }
Dan Egnora455d192010-03-12 08:52:28 -08006964 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006965 }
Dan Egnora455d192010-03-12 08:52:28 -08006966 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006967 }
6968
6969 private static String processClass(ProcessRecord process) {
6970 if (process == null || process.pid == MY_PID) {
6971 return "system_server";
6972 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6973 return "system_app";
6974 } else {
6975 return "data_app";
6976 }
6977 }
6978
6979 /**
6980 * Write a description of an error (crash, WTF, ANR) to the drop box.
6981 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6982 * @param process which caused the error, null means the system server
6983 * @param activity which triggered the error, null if unknown
6984 * @param parent activity related to the error, null if unknown
6985 * @param subject line related to the error, null if absent
6986 * @param report in long form describing the error, null if absent
6987 * @param logFile to include in the report, null if none
6988 * @param crashInfo giving an application stack trace, null if absent
6989 */
6990 public void addErrorToDropBox(String eventType,
6991 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6992 final String report, final File logFile,
6993 final ApplicationErrorReport.CrashInfo crashInfo) {
6994 // NOTE -- this must never acquire the ActivityManagerService lock,
6995 // otherwise the watchdog may be prevented from resetting the system.
6996
6997 final String dropboxTag = processClass(process) + "_" + eventType;
6998 final DropBoxManager dbox = (DropBoxManager)
6999 mContext.getSystemService(Context.DROPBOX_SERVICE);
7000
7001 // Exit early if the dropbox isn't configured to accept this report type.
7002 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7003
7004 final StringBuilder sb = new StringBuilder(1024);
7005 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007006 if (activity != null) {
7007 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7008 }
7009 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7010 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7011 }
7012 if (parent != null && parent != activity) {
7013 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7014 }
7015 if (subject != null) {
7016 sb.append("Subject: ").append(subject).append("\n");
7017 }
7018 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007019 if (Debug.isDebuggerConnected()) {
7020 sb.append("Debugger: Connected\n");
7021 }
Dan Egnora455d192010-03-12 08:52:28 -08007022 sb.append("\n");
7023
7024 // Do the rest in a worker thread to avoid blocking the caller on I/O
7025 // (After this point, we shouldn't access AMS internal data structures.)
7026 Thread worker = new Thread("Error dump: " + dropboxTag) {
7027 @Override
7028 public void run() {
7029 if (report != null) {
7030 sb.append(report);
7031 }
7032 if (logFile != null) {
7033 try {
7034 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7035 } catch (IOException e) {
7036 Slog.e(TAG, "Error reading " + logFile, e);
7037 }
7038 }
7039 if (crashInfo != null && crashInfo.stackTrace != null) {
7040 sb.append(crashInfo.stackTrace);
7041 }
7042
7043 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7044 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7045 if (lines > 0) {
7046 sb.append("\n");
7047
7048 // Merge several logcat streams, and take the last N lines
7049 InputStreamReader input = null;
7050 try {
7051 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7052 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7053 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7054
7055 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7056 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7057 input = new InputStreamReader(logcat.getInputStream());
7058
7059 int num;
7060 char[] buf = new char[8192];
7061 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7062 } catch (IOException e) {
7063 Slog.e(TAG, "Error running logcat", e);
7064 } finally {
7065 if (input != null) try { input.close(); } catch (IOException e) {}
7066 }
7067 }
7068
7069 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007070 }
Dan Egnora455d192010-03-12 08:52:28 -08007071 };
7072
7073 if (process == null || process.pid == MY_PID) {
7074 worker.run(); // We may be about to die -- need to run this synchronously
7075 } else {
7076 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007077 }
7078 }
7079
7080 /**
7081 * Bring up the "unexpected error" dialog box for a crashing app.
7082 * Deal with edge cases (intercepts from instrumented applications,
7083 * ActivityController, error intent receivers, that sort of thing).
7084 * @param r the application crashing
7085 * @param crashInfo describing the failure
7086 */
7087 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007088 long timeMillis = System.currentTimeMillis();
7089 String shortMsg = crashInfo.exceptionClassName;
7090 String longMsg = crashInfo.exceptionMessage;
7091 String stackTrace = crashInfo.stackTrace;
7092 if (shortMsg != null && longMsg != null) {
7093 longMsg = shortMsg + ": " + longMsg;
7094 } else if (shortMsg != null) {
7095 longMsg = shortMsg;
7096 }
7097
Dan Egnor60d87622009-12-16 16:32:58 -08007098 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007099 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007100 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007101 try {
7102 String name = r != null ? r.processName : null;
7103 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007104 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007105 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007106 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007107 + " at watcher's request");
7108 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007109 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007110 }
7111 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007112 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007113 }
7114 }
7115
7116 final long origId = Binder.clearCallingIdentity();
7117
7118 // If this process is running instrumentation, finish it.
7119 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007120 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007121 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007122 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7123 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007124 Bundle info = new Bundle();
7125 info.putString("shortMsg", shortMsg);
7126 info.putString("longMsg", longMsg);
7127 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7128 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007129 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 }
7131
Dan Egnor60d87622009-12-16 16:32:58 -08007132 // If we can't identify the process or it's already exceeded its crash quota,
7133 // quit right away without showing a crash dialog.
7134 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007135 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007136 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 }
7138
7139 Message msg = Message.obtain();
7140 msg.what = SHOW_ERROR_MSG;
7141 HashMap data = new HashMap();
7142 data.put("result", result);
7143 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007144 msg.obj = data;
7145 mHandler.sendMessage(msg);
7146
7147 Binder.restoreCallingIdentity(origId);
7148 }
7149
7150 int res = result.get();
7151
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007152 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 synchronized (this) {
7154 if (r != null) {
7155 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7156 SystemClock.uptimeMillis());
7157 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007158 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007159 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007160 }
7161 }
7162
7163 if (appErrorIntent != null) {
7164 try {
7165 mContext.startActivity(appErrorIntent);
7166 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007167 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007170 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007171
7172 Intent createAppErrorIntentLocked(ProcessRecord r,
7173 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7174 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007175 if (report == null) {
7176 return null;
7177 }
7178 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7179 result.setComponent(r.errorReportReceiver);
7180 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7181 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7182 return result;
7183 }
7184
Dan Egnorb7f03672009-12-09 16:22:32 -08007185 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7186 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007187 if (r.errorReportReceiver == null) {
7188 return null;
7189 }
7190
7191 if (!r.crashing && !r.notResponding) {
7192 return null;
7193 }
7194
Dan Egnorb7f03672009-12-09 16:22:32 -08007195 ApplicationErrorReport report = new ApplicationErrorReport();
7196 report.packageName = r.info.packageName;
7197 report.installerPackageName = r.errorReportReceiver.getPackageName();
7198 report.processName = r.processName;
7199 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007200 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007201
Dan Egnorb7f03672009-12-09 16:22:32 -08007202 if (r.crashing) {
7203 report.type = ApplicationErrorReport.TYPE_CRASH;
7204 report.crashInfo = crashInfo;
7205 } else if (r.notResponding) {
7206 report.type = ApplicationErrorReport.TYPE_ANR;
7207 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007208
Dan Egnorb7f03672009-12-09 16:22:32 -08007209 report.anrInfo.activity = r.notRespondingReport.tag;
7210 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7211 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007212 }
7213
Dan Egnorb7f03672009-12-09 16:22:32 -08007214 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007215 }
7216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7218 // assume our apps are happy - lazy create the list
7219 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7220
7221 synchronized (this) {
7222
7223 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007224 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7225 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007226 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7227 // This one's in trouble, so we'll generate a report for it
7228 // crashes are higher priority (in case there's a crash *and* an anr)
7229 ActivityManager.ProcessErrorStateInfo report = null;
7230 if (app.crashing) {
7231 report = app.crashingReport;
7232 } else if (app.notResponding) {
7233 report = app.notRespondingReport;
7234 }
7235
7236 if (report != null) {
7237 if (errList == null) {
7238 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7239 }
7240 errList.add(report);
7241 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007242 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007243 " crashing = " + app.crashing +
7244 " notResponding = " + app.notResponding);
7245 }
7246 }
7247 }
7248 }
7249
7250 return errList;
7251 }
7252
7253 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7254 // Lazy instantiation of list
7255 List<ActivityManager.RunningAppProcessInfo> runList = null;
7256 synchronized (this) {
7257 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007258 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7259 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007260 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7261 // Generate process state info for running application
7262 ActivityManager.RunningAppProcessInfo currApp =
7263 new ActivityManager.RunningAppProcessInfo(app.processName,
7264 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007265 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007266 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007267 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007268 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007269 if (app.persistent) {
7270 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007273 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007274 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7275 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7276 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007277 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7278 } else if (adj >= HOME_APP_ADJ) {
7279 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7280 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007281 } else if (adj >= SECONDARY_SERVER_ADJ) {
7282 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007283 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007284 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007285 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7286 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007287 } else if (adj >= VISIBLE_APP_ADJ) {
7288 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7289 } else {
7290 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7291 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007292 currApp.importanceReasonCode = app.adjTypeCode;
7293 if (app.adjSource instanceof ProcessRecord) {
7294 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007295 } else if (app.adjSource instanceof ActivityRecord) {
7296 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007297 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7298 }
7299 if (app.adjTarget instanceof ComponentName) {
7300 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7301 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007302 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007303 // + " lru=" + currApp.lru);
7304 if (runList == null) {
7305 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7306 }
7307 runList.add(currApp);
7308 }
7309 }
7310 }
7311 return runList;
7312 }
7313
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007314 public List<ApplicationInfo> getRunningExternalApplications() {
7315 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7316 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7317 if (runningApps != null && runningApps.size() > 0) {
7318 Set<String> extList = new HashSet<String>();
7319 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7320 if (app.pkgList != null) {
7321 for (String pkg : app.pkgList) {
7322 extList.add(pkg);
7323 }
7324 }
7325 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007326 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007327 for (String pkg : extList) {
7328 try {
7329 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7330 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7331 retList.add(info);
7332 }
7333 } catch (RemoteException e) {
7334 }
7335 }
7336 }
7337 return retList;
7338 }
7339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007340 @Override
7341 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007342 if (checkCallingPermission(android.Manifest.permission.DUMP)
7343 != PackageManager.PERMISSION_GRANTED) {
7344 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7345 + Binder.getCallingPid()
7346 + ", uid=" + Binder.getCallingUid()
7347 + " without permission "
7348 + android.Manifest.permission.DUMP);
7349 return;
7350 }
7351
7352 boolean dumpAll = false;
7353
7354 int opti = 0;
7355 while (opti < args.length) {
7356 String opt = args[opti];
7357 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7358 break;
7359 }
7360 opti++;
7361 if ("-a".equals(opt)) {
7362 dumpAll = true;
7363 } else if ("-h".equals(opt)) {
7364 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007365 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007366 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007367 pw.println(" a[ctivities]: activity stack state");
7368 pw.println(" b[roadcasts]: broadcast state");
7369 pw.println(" i[ntents]: pending intent state");
7370 pw.println(" p[rocesses]: process state");
7371 pw.println(" o[om]: out of memory management");
7372 pw.println(" prov[iders]: content provider state");
7373 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007374 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007375 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7376 pw.println(" a partial substring in a component name, or an");
7377 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007379 } else {
7380 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007381 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007382 }
7383
7384 // Is the caller requesting to dump a particular piece of data?
7385 if (opti < args.length) {
7386 String cmd = args[opti];
7387 opti++;
7388 if ("activities".equals(cmd) || "a".equals(cmd)) {
7389 synchronized (this) {
7390 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007392 return;
7393 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7394 synchronized (this) {
7395 dumpBroadcastsLocked(fd, pw, args, opti, true);
7396 }
7397 return;
7398 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7399 synchronized (this) {
7400 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7401 }
7402 return;
7403 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7404 synchronized (this) {
7405 dumpProcessesLocked(fd, pw, args, opti, true);
7406 }
7407 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007408 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7409 synchronized (this) {
7410 dumpOomLocked(fd, pw, args, opti, true);
7411 }
7412 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007413 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7414 synchronized (this) {
7415 dumpProvidersLocked(fd, pw, args, opti, true);
7416 }
7417 return;
7418 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007419 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007420 return;
7421 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7422 synchronized (this) {
7423 dumpServicesLocked(fd, pw, args, opti, true);
7424 }
7425 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007426 } else {
7427 // Dumping a single activity?
7428 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7429 return;
7430 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007431 pw.println("Bad activity command, or no activities match: " + cmd);
7432 pw.println("Use -h for help.");
7433 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007435 }
7436
7437 // No piece of data specified, dump everything.
7438 synchronized (this) {
7439 boolean needSep;
7440 if (dumpAll) {
7441 pw.println("Providers in Current Activity Manager State:");
7442 }
7443 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7444 if (needSep) {
7445 pw.println(" ");
7446 }
7447 if (dumpAll) {
7448 pw.println("-------------------------------------------------------------------------------");
7449 pw.println("Broadcasts in Current Activity Manager State:");
7450 }
7451 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7452 if (needSep) {
7453 pw.println(" ");
7454 }
7455 if (dumpAll) {
7456 pw.println("-------------------------------------------------------------------------------");
7457 pw.println("Services in Current Activity Manager State:");
7458 }
7459 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7460 if (needSep) {
7461 pw.println(" ");
7462 }
7463 if (dumpAll) {
7464 pw.println("-------------------------------------------------------------------------------");
7465 pw.println("PendingIntents in Current Activity Manager State:");
7466 }
7467 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7468 if (needSep) {
7469 pw.println(" ");
7470 }
7471 if (dumpAll) {
7472 pw.println("-------------------------------------------------------------------------------");
7473 pw.println("Activities in Current Activity Manager State:");
7474 }
7475 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7476 if (needSep) {
7477 pw.println(" ");
7478 }
7479 if (dumpAll) {
7480 pw.println("-------------------------------------------------------------------------------");
7481 pw.println("Processes in Current Activity Manager State:");
7482 }
7483 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7484 }
7485 }
7486
7487 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7488 int opti, boolean dumpAll, boolean needHeader) {
7489 if (needHeader) {
7490 pw.println(" Activity stack:");
7491 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007492 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007493 pw.println(" ");
7494 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007495 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7496 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007497 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007498 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007499 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007500 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007501 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007503 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007504 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007505 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007506 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007507 pw.println(" ");
7508 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007509 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007511
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007512 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007513 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7514 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007515 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007516 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007518 if (dumpAll && mRecentTasks.size() > 0) {
7519 pw.println(" ");
7520 pw.println("Recent tasks in Current Activity Manager State:");
7521
7522 final int N = mRecentTasks.size();
7523 for (int i=0; i<N; i++) {
7524 TaskRecord tr = mRecentTasks.get(i);
7525 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7526 pw.println(tr);
7527 mRecentTasks.get(i).dump(pw, " ");
7528 }
7529 }
7530
7531 pw.println(" ");
7532 pw.println(" mCurTask: " + mCurTask);
7533
7534 return true;
7535 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007536
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007537 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7538 int opti, boolean dumpAll) {
7539 boolean needSep = false;
7540 int numPers = 0;
7541
7542 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007543 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7544 final int NA = procs.size();
7545 for (int ia=0; ia<NA; ia++) {
7546 if (!needSep) {
7547 pw.println(" All known processes:");
7548 needSep = true;
7549 }
7550 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007551 pw.print(r.persistent ? " *PERS*" : " *APP*");
7552 pw.print(" UID "); pw.print(procs.keyAt(ia));
7553 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554 r.dump(pw, " ");
7555 if (r.persistent) {
7556 numPers++;
7557 }
7558 }
7559 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007560 }
7561
7562 if (mLruProcesses.size() > 0) {
7563 if (needSep) pw.println(" ");
7564 needSep = true;
7565 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007566 dumpProcessOomList(pw, this, mLruProcesses, " ",
7567 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007568 needSep = true;
7569 }
7570
7571 synchronized (mPidsSelfLocked) {
7572 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 if (needSep) pw.println(" ");
7574 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007575 pw.println(" PID mappings:");
7576 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7577 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7578 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 }
7580 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007581 }
7582
7583 if (mForegroundProcesses.size() > 0) {
7584 if (needSep) pw.println(" ");
7585 needSep = true;
7586 pw.println(" Foreground Processes:");
7587 for (int i=0; i<mForegroundProcesses.size(); i++) {
7588 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7589 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007591 }
7592
7593 if (mPersistentStartingProcesses.size() > 0) {
7594 if (needSep) pw.println(" ");
7595 needSep = true;
7596 pw.println(" Persisent processes that are starting:");
7597 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007598 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007599 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007600
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007601 if (mStartingProcesses.size() > 0) {
7602 if (needSep) pw.println(" ");
7603 needSep = true;
7604 pw.println(" Processes that are starting:");
7605 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007606 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007609 if (mRemovedProcesses.size() > 0) {
7610 if (needSep) pw.println(" ");
7611 needSep = true;
7612 pw.println(" Processes that are being removed:");
7613 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007614 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007615 }
7616
7617 if (mProcessesOnHold.size() > 0) {
7618 if (needSep) pw.println(" ");
7619 needSep = true;
7620 pw.println(" Processes that are on old until the system is ready:");
7621 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007622 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007624
Dianne Hackborn287952c2010-09-22 22:34:31 -07007625 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007626
7627 if (mProcessCrashTimes.getMap().size() > 0) {
7628 if (needSep) pw.println(" ");
7629 needSep = true;
7630 pw.println(" Time since processes crashed:");
7631 long now = SystemClock.uptimeMillis();
7632 for (Map.Entry<String, SparseArray<Long>> procs
7633 : mProcessCrashTimes.getMap().entrySet()) {
7634 SparseArray<Long> uids = procs.getValue();
7635 final int N = uids.size();
7636 for (int i=0; i<N; i++) {
7637 pw.print(" Process "); pw.print(procs.getKey());
7638 pw.print(" uid "); pw.print(uids.keyAt(i));
7639 pw.print(": last crashed ");
7640 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007641 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007642 }
7643 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007644 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007645
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007646 if (mBadProcesses.getMap().size() > 0) {
7647 if (needSep) pw.println(" ");
7648 needSep = true;
7649 pw.println(" Bad processes:");
7650 for (Map.Entry<String, SparseArray<Long>> procs
7651 : mBadProcesses.getMap().entrySet()) {
7652 SparseArray<Long> uids = procs.getValue();
7653 final int N = uids.size();
7654 for (int i=0; i<N; i++) {
7655 pw.print(" Bad process "); pw.print(procs.getKey());
7656 pw.print(" uid "); pw.print(uids.keyAt(i));
7657 pw.print(": crashed at time ");
7658 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007659 }
7660 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007661 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007662
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007663 pw.println(" ");
7664 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007665 if (mHeavyWeightProcess != null) {
7666 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7667 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007668 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007669 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007670 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7671 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7672 || mOrigWaitForDebugger) {
7673 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7674 + " mDebugTransient=" + mDebugTransient
7675 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7676 }
7677 if (mAlwaysFinishActivities || mController != null) {
7678 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7679 + " mController=" + mController);
7680 }
7681 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007684 + " mProcessesReady=" + mProcessesReady
7685 + " mSystemReady=" + mSystemReady);
7686 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687 + " mBooted=" + mBooted
7688 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007689 pw.print(" mLastPowerCheckRealtime=");
7690 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7691 pw.println("");
7692 pw.print(" mLastPowerCheckUptime=");
7693 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7694 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007695 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7696 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007697 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007699
7700 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 }
7702
Dianne Hackborn287952c2010-09-22 22:34:31 -07007703 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7704 int opti, boolean needSep, boolean dumpAll) {
7705 if (mProcessesToGc.size() > 0) {
7706 if (needSep) pw.println(" ");
7707 needSep = true;
7708 pw.println(" Processes that are waiting to GC:");
7709 long now = SystemClock.uptimeMillis();
7710 for (int i=0; i<mProcessesToGc.size(); i++) {
7711 ProcessRecord proc = mProcessesToGc.get(i);
7712 pw.print(" Process "); pw.println(proc);
7713 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7714 pw.print(", last gced=");
7715 pw.print(now-proc.lastRequestedGc);
7716 pw.print(" ms ago, last lowMem=");
7717 pw.print(now-proc.lastLowMemory);
7718 pw.println(" ms ago");
7719
7720 }
7721 }
7722 return needSep;
7723 }
7724
7725 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7726 int opti, boolean dumpAll) {
7727 boolean needSep = false;
7728
7729 if (mLruProcesses.size() > 0) {
7730 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7731
7732 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7733 @Override
7734 public int compare(ProcessRecord object1, ProcessRecord object2) {
7735 if (object1.setAdj != object2.setAdj) {
7736 return object1.setAdj > object2.setAdj ? -1 : 1;
7737 }
7738 if (object1.setSchedGroup != object2.setSchedGroup) {
7739 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7740 }
7741 if (object1.keeping != object2.keeping) {
7742 return object1.keeping ? -1 : 1;
7743 }
7744 if (object1.pid != object2.pid) {
7745 return object1.pid > object2.pid ? -1 : 1;
7746 }
7747 return 0;
7748 }
7749 };
7750
7751 Collections.sort(procs, comparator);
7752
7753 if (needSep) pw.println(" ");
7754 needSep = true;
7755 pw.println(" Process OOM control:");
7756 dumpProcessOomList(pw, this, procs, " ",
7757 "Proc", "PERS", true);
7758 needSep = true;
7759 }
7760
7761 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7762
7763 pw.println(" ");
7764 pw.println(" mHomeProcess: " + mHomeProcess);
7765 if (mHeavyWeightProcess != null) {
7766 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7767 }
7768
7769 return true;
7770 }
7771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007772 /**
7773 * There are three ways to call this:
7774 * - no service specified: dump all the services
7775 * - a flattened component name that matched an existing service was specified as the
7776 * first arg: dump that one service
7777 * - the first arg isn't the flattened component name of an existing service:
7778 * dump all services whose component contains the first arg as a substring
7779 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007780 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007781 String[] newArgs;
7782 String componentNameString;
7783 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007784 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 componentNameString = null;
7786 newArgs = EMPTY_STRING_ARRAY;
7787 r = null;
7788 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007789 componentNameString = args[opti];
7790 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007791 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007792 synchronized (this) {
7793 r = componentName != null ? mServices.get(componentName) : null;
7794 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007795 newArgs = new String[args.length - opti];
7796 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 }
7798
7799 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007800 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007801 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007802 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7803 synchronized (this) {
7804 for (ServiceRecord r1 : mServices.values()) {
7805 if (componentNameString == null
7806 || r1.name.flattenToString().contains(componentNameString)) {
7807 services.add(r1);
7808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007809 }
7810 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007811 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007812 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814 }
7815 }
7816
7817 /**
7818 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7819 * there is a thread associated with the service.
7820 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007821 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7822 pw.println("------------------------------------------------------------"
7823 + "-------------------");
7824 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 if (r.app != null && r.app.thread != null) {
7826 try {
7827 // flush anything that is already in the PrintWriter since the thread is going
7828 // to write to the file descriptor directly
7829 pw.flush();
7830 r.app.thread.dumpService(fd, r, args);
7831 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007832 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833 } catch (RemoteException e) {
7834 pw.println("got a RemoteException while dumping the service");
7835 }
7836 }
7837 }
7838
Dianne Hackborn625ac272010-09-17 18:29:22 -07007839 /**
7840 * There are three things that cmd can be:
7841 * - a flattened component name that matched an existing activity
7842 * - the cmd arg isn't the flattened component name of an existing activity:
7843 * dump all activity whose component contains the cmd as a substring
7844 * - A hex number of the ActivityRecord object instance.
7845 */
7846 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7847 int opti, boolean dumpAll) {
7848 String[] newArgs;
7849 ComponentName componentName = ComponentName.unflattenFromString(name);
7850 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007851 if (componentName == null) {
7852 // Not a '/' separated full component name; maybe an object ID?
7853 try {
7854 objectId = Integer.parseInt(name, 16);
7855 name = null;
7856 componentName = null;
7857 } catch (RuntimeException e) {
7858 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007859 }
7860 newArgs = new String[args.length - opti];
7861 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7862
7863 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7864 synchronized (this) {
7865 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7866 if (componentName != null) {
7867 if (r1.intent.getComponent().equals(componentName)) {
7868 activities.add(r1);
7869 }
7870 } else if (name != null) {
7871 if (r1.intent.getComponent().flattenToString().contains(name)) {
7872 activities.add(r1);
7873 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007874 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007875 activities.add(r1);
7876 }
7877 }
7878 }
7879
7880 if (activities.size() <= 0) {
7881 return false;
7882 }
7883
Dianne Hackborn30d71892010-12-11 10:37:55 -08007884 TaskRecord lastTask = null;
7885 for (int i=activities.size()-1; i>=0; i--) {
7886 ActivityRecord r = (ActivityRecord)activities.get(i);
7887 if (lastTask != r.task) {
7888 lastTask = r.task;
7889 pw.print("* Task "); pw.print(lastTask.affinity);
7890 pw.print(" id="); pw.println(lastTask.taskId);
7891 if (dumpAll) {
7892 lastTask.dump(pw, " ");
7893 }
7894 }
7895 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007896 }
7897 return true;
7898 }
7899
7900 /**
7901 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
7902 * there is a thread associated with the activity.
7903 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08007904 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
7905 ActivityRecord r, String[] args, boolean dumpAll) {
7906 synchronized (this) {
7907 pw.print(prefix); pw.print("* Activity ");
7908 pw.print(Integer.toHexString(System.identityHashCode(r)));
7909 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
7910 if (r.app != null) pw.println(r.app.pid);
7911 else pw.println("(not running)");
7912 if (dumpAll) {
7913 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007914 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007915 }
7916 if (r.app != null && r.app.thread != null) {
7917 try {
7918 // flush anything that is already in the PrintWriter since the thread is going
7919 // to write to the file descriptor directly
7920 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08007921 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007922 pw.flush();
7923 } catch (RemoteException e) {
7924 pw.println("got a RemoteException while dumping the activity");
7925 }
7926 }
7927 }
7928
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007929 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7930 int opti, boolean dumpAll) {
7931 boolean needSep = false;
7932
7933 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007934 if (mRegisteredReceivers.size() > 0) {
7935 pw.println(" ");
7936 pw.println(" Registered Receivers:");
7937 Iterator it = mRegisteredReceivers.values().iterator();
7938 while (it.hasNext()) {
7939 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007940 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941 r.dump(pw, " ");
7942 }
7943 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 pw.println(" ");
7946 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007947 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007948 needSep = true;
7949 }
7950
7951 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7952 || mPendingBroadcast != null) {
7953 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007954 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007955 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007956 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007957 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7958 pw.println(" Broadcast #" + i + ":");
7959 mParallelBroadcasts.get(i).dump(pw, " ");
7960 }
7961 if (mOrderedBroadcasts.size() > 0) {
7962 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007963 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007964 }
7965 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7966 pw.println(" Serialized Broadcast #" + i + ":");
7967 mOrderedBroadcasts.get(i).dump(pw, " ");
7968 }
7969 pw.println(" ");
7970 pw.println(" Pending broadcast:");
7971 if (mPendingBroadcast != null) {
7972 mPendingBroadcast.dump(pw, " ");
7973 } else {
7974 pw.println(" (null)");
7975 }
7976 needSep = true;
7977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007978
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007979 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007981 pw.println(" Historical broadcasts:");
7982 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7983 BroadcastRecord r = mBroadcastHistory[i];
7984 if (r == null) {
7985 break;
7986 }
7987 pw.println(" Historical Broadcast #" + i + ":");
7988 r.dump(pw, " ");
7989 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007990 needSep = true;
7991 }
7992
7993 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007994 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007995 pw.println(" Sticky broadcasts:");
7996 StringBuilder sb = new StringBuilder(128);
7997 for (Map.Entry<String, ArrayList<Intent>> ent
7998 : mStickyBroadcasts.entrySet()) {
7999 pw.print(" * Sticky action "); pw.print(ent.getKey());
8000 pw.println(":");
8001 ArrayList<Intent> intents = ent.getValue();
8002 final int N = intents.size();
8003 for (int i=0; i<N; i++) {
8004 sb.setLength(0);
8005 sb.append(" Intent: ");
8006 intents.get(i).toShortString(sb, true, false);
8007 pw.println(sb.toString());
8008 Bundle bundle = intents.get(i).getExtras();
8009 if (bundle != null) {
8010 pw.print(" ");
8011 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008012 }
8013 }
8014 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008015 needSep = true;
8016 }
8017
8018 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008019 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008020 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 pw.println(" mHandler:");
8022 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008023 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008025
8026 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008027 }
8028
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008029 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8030 int opti, boolean dumpAll) {
8031 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008033 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008034 if (mServices.size() > 0) {
8035 pw.println(" Active services:");
8036 Iterator<ServiceRecord> it = mServices.values().iterator();
8037 while (it.hasNext()) {
8038 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008039 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008040 r.dump(pw, " ");
8041 }
8042 needSep = true;
8043 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008046 if (mPendingServices.size() > 0) {
8047 if (needSep) pw.println(" ");
8048 pw.println(" Pending services:");
8049 for (int i=0; i<mPendingServices.size(); i++) {
8050 ServiceRecord r = mPendingServices.get(i);
8051 pw.print(" * Pending "); pw.println(r);
8052 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008053 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008054 needSep = true;
8055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008056
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008057 if (mRestartingServices.size() > 0) {
8058 if (needSep) pw.println(" ");
8059 pw.println(" Restarting services:");
8060 for (int i=0; i<mRestartingServices.size(); i++) {
8061 ServiceRecord r = mRestartingServices.get(i);
8062 pw.print(" * Restarting "); pw.println(r);
8063 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008065 needSep = true;
8066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008067
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008068 if (mStoppingServices.size() > 0) {
8069 if (needSep) pw.println(" ");
8070 pw.println(" Stopping services:");
8071 for (int i=0; i<mStoppingServices.size(); i++) {
8072 ServiceRecord r = mStoppingServices.get(i);
8073 pw.print(" * Stopping "); pw.println(r);
8074 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008075 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008076 needSep = true;
8077 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008078
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008079 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008080 if (mServiceConnections.size() > 0) {
8081 if (needSep) pw.println(" ");
8082 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008083 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008084 = mServiceConnections.values().iterator();
8085 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008086 ArrayList<ConnectionRecord> r = it.next();
8087 for (int i=0; i<r.size(); i++) {
8088 pw.print(" * "); pw.println(r.get(i));
8089 r.get(i).dump(pw, " ");
8090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008091 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008092 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008093 }
8094 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008095
8096 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008097 }
8098
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008099 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8100 int opti, boolean dumpAll) {
8101 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008102
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008103 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008104 if (mProvidersByClass.size() > 0) {
8105 if (needSep) pw.println(" ");
8106 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008107 Iterator<Map.Entry<String, ContentProviderRecord>> it
8108 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008110 Map.Entry<String, ContentProviderRecord> e = it.next();
8111 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008112 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113 r.dump(pw, " ");
8114 }
8115 needSep = true;
8116 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008117
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008118 if (mProvidersByName.size() > 0) {
8119 pw.println(" ");
8120 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008121 Iterator<Map.Entry<String, ContentProviderRecord>> it
8122 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008123 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008124 Map.Entry<String, ContentProviderRecord> e = it.next();
8125 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008126 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8127 pw.println(r);
8128 }
8129 needSep = true;
8130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008131 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008132
8133 if (mLaunchingProviders.size() > 0) {
8134 if (needSep) pw.println(" ");
8135 pw.println(" Launching content providers:");
8136 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8137 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8138 pw.println(mLaunchingProviders.get(i));
8139 }
8140 needSep = true;
8141 }
8142
8143 if (mGrantedUriPermissions.size() > 0) {
8144 pw.println();
8145 pw.println("Granted Uri Permissions:");
8146 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8147 int uid = mGrantedUriPermissions.keyAt(i);
8148 HashMap<Uri, UriPermission> perms
8149 = mGrantedUriPermissions.valueAt(i);
8150 pw.print(" * UID "); pw.print(uid);
8151 pw.println(" holds:");
8152 for (UriPermission perm : perms.values()) {
8153 pw.print(" "); pw.println(perm);
8154 perm.dump(pw, " ");
8155 }
8156 }
8157 needSep = true;
8158 }
8159
8160 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008161 }
8162
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008163 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8164 int opti, boolean dumpAll) {
8165 boolean needSep = false;
8166
8167 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008168 if (this.mIntentSenderRecords.size() > 0) {
8169 Iterator<WeakReference<PendingIntentRecord>> it
8170 = mIntentSenderRecords.values().iterator();
8171 while (it.hasNext()) {
8172 WeakReference<PendingIntentRecord> ref = it.next();
8173 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008174 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008176 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008177 rec.dump(pw, " ");
8178 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008179 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008180 }
8181 }
8182 }
8183 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008184
8185 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008186 }
8187
8188 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008189 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 TaskRecord lastTask = null;
8191 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008192 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008193 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008194 if (lastTask != r.task) {
8195 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008196 pw.print(prefix);
8197 pw.print(full ? "* " : " ");
8198 pw.println(lastTask);
8199 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008200 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008203 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8204 pw.print(" #"); pw.print(i); pw.print(": ");
8205 pw.println(r);
8206 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008207 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008208 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008209 }
8210 }
8211
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008212 private static String buildOomTag(String prefix, String space, int val, int base) {
8213 if (val == base) {
8214 if (space == null) return prefix;
8215 return prefix + " ";
8216 }
8217 return prefix + "+" + Integer.toString(val-base);
8218 }
8219
8220 private static final int dumpProcessList(PrintWriter pw,
8221 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008222 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008224 final int N = list.size()-1;
8225 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008226 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008227 pw.println(String.format("%s%s #%2d: %s",
8228 prefix, (r.persistent ? persistentLabel : normalLabel),
8229 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008230 if (r.persistent) {
8231 numPers++;
8232 }
8233 }
8234 return numPers;
8235 }
8236
Dianne Hackborn287952c2010-09-22 22:34:31 -07008237 private static final void dumpProcessOomList(PrintWriter pw,
8238 ActivityManagerService service, List<ProcessRecord> list,
8239 String prefix, String normalLabel, String persistentLabel,
8240 boolean inclDetails) {
8241
8242 final long curRealtime = SystemClock.elapsedRealtime();
8243 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8244 final long curUptime = SystemClock.uptimeMillis();
8245 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8246
8247 final int N = list.size()-1;
8248 for (int i=N; i>=0; i--) {
8249 ProcessRecord r = list.get(i);
8250 String oomAdj;
8251 if (r.setAdj >= EMPTY_APP_ADJ) {
8252 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8253 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8254 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8255 } else if (r.setAdj >= HOME_APP_ADJ) {
8256 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8257 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8258 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8259 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8260 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8261 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8262 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8263 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8264 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8265 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8266 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8267 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8268 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8269 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8270 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8271 } else if (r.setAdj >= SYSTEM_ADJ) {
8272 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8273 } else {
8274 oomAdj = Integer.toString(r.setAdj);
8275 }
8276 String schedGroup;
8277 switch (r.setSchedGroup) {
8278 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8279 schedGroup = "B";
8280 break;
8281 case Process.THREAD_GROUP_DEFAULT:
8282 schedGroup = "F";
8283 break;
8284 default:
8285 schedGroup = Integer.toString(r.setSchedGroup);
8286 break;
8287 }
8288 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8289 prefix, (r.persistent ? persistentLabel : normalLabel),
8290 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8291 if (r.adjSource != null || r.adjTarget != null) {
8292 pw.print(prefix);
8293 pw.print(" ");
8294 if (r.adjTarget instanceof ComponentName) {
8295 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8296 } else if (r.adjTarget != null) {
8297 pw.print(r.adjTarget.toString());
8298 } else {
8299 pw.print("{null}");
8300 }
8301 pw.print("<=");
8302 if (r.adjSource instanceof ProcessRecord) {
8303 pw.print("Proc{");
8304 pw.print(((ProcessRecord)r.adjSource).toShortString());
8305 pw.println("}");
8306 } else if (r.adjSource != null) {
8307 pw.println(r.adjSource.toString());
8308 } else {
8309 pw.println("{null}");
8310 }
8311 }
8312 if (inclDetails) {
8313 pw.print(prefix);
8314 pw.print(" ");
8315 pw.print("oom: max="); pw.print(r.maxAdj);
8316 pw.print(" hidden="); pw.print(r.hiddenAdj);
8317 pw.print(" curRaw="); pw.print(r.curRawAdj);
8318 pw.print(" setRaw="); pw.print(r.setRawAdj);
8319 pw.print(" cur="); pw.print(r.curAdj);
8320 pw.print(" set="); pw.println(r.setAdj);
8321 pw.print(prefix);
8322 pw.print(" ");
8323 pw.print("keeping="); pw.print(r.keeping);
8324 pw.print(" hidden="); pw.print(r.hidden);
8325 pw.print(" empty="); pw.println(r.empty);
8326
8327 if (!r.keeping) {
8328 if (r.lastWakeTime != 0) {
8329 long wtime;
8330 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8331 synchronized (stats) {
8332 wtime = stats.getProcessWakeTime(r.info.uid,
8333 r.pid, curRealtime);
8334 }
8335 long timeUsed = wtime - r.lastWakeTime;
8336 pw.print(prefix);
8337 pw.print(" ");
8338 pw.print("keep awake over ");
8339 TimeUtils.formatDuration(realtimeSince, pw);
8340 pw.print(" used ");
8341 TimeUtils.formatDuration(timeUsed, pw);
8342 pw.print(" (");
8343 pw.print((timeUsed*100)/realtimeSince);
8344 pw.println("%)");
8345 }
8346 if (r.lastCpuTime != 0) {
8347 long timeUsed = r.curCpuTime - r.lastCpuTime;
8348 pw.print(prefix);
8349 pw.print(" ");
8350 pw.print("run cpu over ");
8351 TimeUtils.formatDuration(uptimeSince, pw);
8352 pw.print(" used ");
8353 TimeUtils.formatDuration(timeUsed, pw);
8354 pw.print(" (");
8355 pw.print((timeUsed*100)/uptimeSince);
8356 pw.println("%)");
8357 }
8358 }
8359 }
8360 }
8361 }
8362
Dianne Hackborn472ad872010-04-07 17:31:48 -07008363 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008364 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008365 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008366 long uptime = SystemClock.uptimeMillis();
8367 long realtime = SystemClock.elapsedRealtime();
8368
8369 if (isCheckinRequest) {
8370 // short checkin version
8371 pw.println(uptime + "," + realtime);
8372 pw.flush();
8373 } else {
8374 pw.println("Applications Memory Usage (kB):");
8375 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8376 }
8377 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8378 ProcessRecord r = (ProcessRecord)list.get(i);
8379 if (r.thread != null) {
8380 if (!isCheckinRequest) {
8381 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8382 pw.flush();
8383 }
8384 try {
8385 r.thread.asBinder().dump(fd, args);
8386 } catch (RemoteException e) {
8387 if (!isCheckinRequest) {
8388 pw.println("Got RemoteException!");
8389 pw.flush();
8390 }
8391 }
8392 }
8393 }
8394 }
8395
8396 /**
8397 * Searches array of arguments for the specified string
8398 * @param args array of argument strings
8399 * @param value value to search for
8400 * @return true if the value is contained in the array
8401 */
8402 private static boolean scanArgs(String[] args, String value) {
8403 if (args != null) {
8404 for (String arg : args) {
8405 if (value.equals(arg)) {
8406 return true;
8407 }
8408 }
8409 }
8410 return false;
8411 }
8412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008413 private final void killServicesLocked(ProcessRecord app,
8414 boolean allowRestart) {
8415 // Report disconnected services.
8416 if (false) {
8417 // XXX we are letting the client link to the service for
8418 // death notifications.
8419 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008420 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008421 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008422 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008423 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008424 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 = r.connections.values().iterator();
8426 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008427 ArrayList<ConnectionRecord> cl = jt.next();
8428 for (int i=0; i<cl.size(); i++) {
8429 ConnectionRecord c = cl.get(i);
8430 if (c.binding.client != app) {
8431 try {
8432 //c.conn.connected(r.className, null);
8433 } catch (Exception e) {
8434 // todo: this should be asynchronous!
8435 Slog.w(TAG, "Exception thrown disconnected servce "
8436 + r.shortName
8437 + " from app " + app.processName, e);
8438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008439 }
8440 }
8441 }
8442 }
8443 }
8444 }
8445 }
8446
8447 // Clean up any connections this application has to other services.
8448 if (app.connections.size() > 0) {
8449 Iterator<ConnectionRecord> it = app.connections.iterator();
8450 while (it.hasNext()) {
8451 ConnectionRecord r = it.next();
8452 removeConnectionLocked(r, app, null);
8453 }
8454 }
8455 app.connections.clear();
8456
8457 if (app.services.size() != 0) {
8458 // Any services running in the application need to be placed
8459 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008460 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008462 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 synchronized (sr.stats.getBatteryStats()) {
8464 sr.stats.stopLaunchedLocked();
8465 }
8466 sr.app = null;
8467 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008468 if (mStoppingServices.remove(sr)) {
8469 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8470 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008471
8472 boolean hasClients = sr.bindings.size() > 0;
8473 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008474 Iterator<IntentBindRecord> bindings
8475 = sr.bindings.values().iterator();
8476 while (bindings.hasNext()) {
8477 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008478 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008479 + ": shouldUnbind=" + b.hasBound);
8480 b.binder = null;
8481 b.requested = b.received = b.hasBound = false;
8482 }
8483 }
8484
Dianne Hackborn070783f2010-12-29 16:46:28 -08008485 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8486 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008487 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008488 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008489 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008490 sr.crashCount, sr.shortName, app.pid);
8491 bringDownServiceLocked(sr, true);
8492 } else if (!allowRestart) {
8493 bringDownServiceLocked(sr, true);
8494 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008495 boolean canceled = scheduleServiceRestartLocked(sr, true);
8496
8497 // Should the service remain running? Note that in the
8498 // extreme case of so many attempts to deliver a command
8499 // that it failed, that we also will stop it here.
8500 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8501 if (sr.pendingStarts.size() == 0) {
8502 sr.startRequested = false;
8503 if (!hasClients) {
8504 // Whoops, no reason to restart!
8505 bringDownServiceLocked(sr, true);
8506 }
8507 }
8508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 }
8510 }
8511
8512 if (!allowRestart) {
8513 app.services.clear();
8514 }
8515 }
8516
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008517 // Make sure we have no more records on the stopping list.
8518 int i = mStoppingServices.size();
8519 while (i > 0) {
8520 i--;
8521 ServiceRecord sr = mStoppingServices.get(i);
8522 if (sr.app == app) {
8523 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008524 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008525 }
8526 }
8527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 app.executingServices.clear();
8529 }
8530
8531 private final void removeDyingProviderLocked(ProcessRecord proc,
8532 ContentProviderRecord cpr) {
8533 synchronized (cpr) {
8534 cpr.launchingApp = null;
8535 cpr.notifyAll();
8536 }
8537
8538 mProvidersByClass.remove(cpr.info.name);
8539 String names[] = cpr.info.authority.split(";");
8540 for (int j = 0; j < names.length; j++) {
8541 mProvidersByName.remove(names[j]);
8542 }
8543
8544 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8545 while (cit.hasNext()) {
8546 ProcessRecord capp = cit.next();
8547 if (!capp.persistent && capp.thread != null
8548 && capp.pid != 0
8549 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008550 Slog.i(TAG, "Kill " + capp.processName
8551 + " (pid " + capp.pid + "): provider " + cpr.info.name
8552 + " in dying process " + proc.processName);
8553 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8554 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 Process.killProcess(capp.pid);
8556 }
8557 }
8558
8559 mLaunchingProviders.remove(cpr);
8560 }
8561
8562 /**
8563 * Main code for cleaning up a process when it has gone away. This is
8564 * called both as a result of the process dying, or directly when stopping
8565 * a process when running in single process mode.
8566 */
8567 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8568 boolean restarting, int index) {
8569 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008570 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008571 }
8572
Dianne Hackborn36124872009-10-08 16:22:03 -07008573 mProcessesToGc.remove(app);
8574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 // Dismiss any open dialogs.
8576 if (app.crashDialog != null) {
8577 app.crashDialog.dismiss();
8578 app.crashDialog = null;
8579 }
8580 if (app.anrDialog != null) {
8581 app.anrDialog.dismiss();
8582 app.anrDialog = null;
8583 }
8584 if (app.waitDialog != null) {
8585 app.waitDialog.dismiss();
8586 app.waitDialog = null;
8587 }
8588
8589 app.crashing = false;
8590 app.notResponding = false;
8591
8592 app.resetPackageList();
8593 app.thread = null;
8594 app.forcingToForeground = null;
8595 app.foregroundServices = false;
8596
8597 killServicesLocked(app, true);
8598
8599 boolean restart = false;
8600
8601 int NL = mLaunchingProviders.size();
8602
8603 // Remove published content providers.
8604 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008605 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008606 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008607 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008608 cpr.provider = null;
8609 cpr.app = null;
8610
8611 // See if someone is waiting for this provider... in which
8612 // case we don't remove it, but just let it restart.
8613 int i = 0;
8614 if (!app.bad) {
8615 for (; i<NL; i++) {
8616 if (mLaunchingProviders.get(i) == cpr) {
8617 restart = true;
8618 break;
8619 }
8620 }
8621 } else {
8622 i = NL;
8623 }
8624
8625 if (i >= NL) {
8626 removeDyingProviderLocked(app, cpr);
8627 NL = mLaunchingProviders.size();
8628 }
8629 }
8630 app.pubProviders.clear();
8631 }
8632
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008633 // Take care of any launching providers waiting for this process.
8634 if (checkAppInLaunchingProvidersLocked(app, false)) {
8635 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008638 // Unregister from connected content providers.
8639 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008640 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008641 while (it.hasNext()) {
8642 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8643 cpr.clients.remove(app);
8644 }
8645 app.conProviders.clear();
8646 }
8647
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008648 // At this point there may be remaining entries in mLaunchingProviders
8649 // where we were the only one waiting, so they are no longer of use.
8650 // Look for these and clean up if found.
8651 // XXX Commented out for now. Trying to figure out a way to reproduce
8652 // the actual situation to identify what is actually going on.
8653 if (false) {
8654 for (int i=0; i<NL; i++) {
8655 ContentProviderRecord cpr = (ContentProviderRecord)
8656 mLaunchingProviders.get(i);
8657 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8658 synchronized (cpr) {
8659 cpr.launchingApp = null;
8660 cpr.notifyAll();
8661 }
8662 }
8663 }
8664 }
8665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008666 skipCurrentReceiverLocked(app);
8667
8668 // Unregister any receivers.
8669 if (app.receivers.size() > 0) {
8670 Iterator<ReceiverList> it = app.receivers.iterator();
8671 while (it.hasNext()) {
8672 removeReceiverLocked(it.next());
8673 }
8674 app.receivers.clear();
8675 }
8676
Christopher Tate181fafa2009-05-14 11:12:14 -07008677 // If the app is undergoing backup, tell the backup manager about it
8678 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008679 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008680 try {
8681 IBackupManager bm = IBackupManager.Stub.asInterface(
8682 ServiceManager.getService(Context.BACKUP_SERVICE));
8683 bm.agentDisconnected(app.info.packageName);
8684 } catch (RemoteException e) {
8685 // can't happen; backup manager is local
8686 }
8687 }
8688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 // If the caller is restarting this app, then leave it in its
8690 // current lists and let the caller take care of it.
8691 if (restarting) {
8692 return;
8693 }
8694
8695 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008696 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 "Removing non-persistent process during cleanup: " + app);
8698 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008699 if (mHeavyWeightProcess == app) {
8700 mHeavyWeightProcess = null;
8701 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008703 } else if (!app.removed) {
8704 // This app is persistent, so we need to keep its record around.
8705 // If it is not already on the pending app list, add it there
8706 // and start a new process for it.
8707 app.thread = null;
8708 app.forcingToForeground = null;
8709 app.foregroundServices = false;
8710 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8711 mPersistentStartingProcesses.add(app);
8712 restart = true;
8713 }
8714 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008715 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8716 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 mProcessesOnHold.remove(app);
8718
The Android Open Source Project4df24232009-03-05 14:34:35 -08008719 if (app == mHomeProcess) {
8720 mHomeProcess = null;
8721 }
8722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 if (restart) {
8724 // We have components that still need to be running in the
8725 // process, so re-launch it.
8726 mProcessNames.put(app.processName, app.info.uid, app);
8727 startProcessLocked(app, "restart", app.processName);
8728 } else if (app.pid > 0 && app.pid != MY_PID) {
8729 // Goodbye!
8730 synchronized (mPidsSelfLocked) {
8731 mPidsSelfLocked.remove(app.pid);
8732 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8733 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008734 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008735 }
8736 }
8737
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008738 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8739 // Look through the content providers we are waiting to have launched,
8740 // and if any run in this process then either schedule a restart of
8741 // the process or kill the client waiting for it if this process has
8742 // gone bad.
8743 int NL = mLaunchingProviders.size();
8744 boolean restart = false;
8745 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008746 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008747 if (cpr.launchingApp == app) {
8748 if (!alwaysBad && !app.bad) {
8749 restart = true;
8750 } else {
8751 removeDyingProviderLocked(app, cpr);
8752 NL = mLaunchingProviders.size();
8753 }
8754 }
8755 }
8756 return restart;
8757 }
8758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 // =========================================================
8760 // SERVICES
8761 // =========================================================
8762
8763 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8764 ActivityManager.RunningServiceInfo info =
8765 new ActivityManager.RunningServiceInfo();
8766 info.service = r.name;
8767 if (r.app != null) {
8768 info.pid = r.app.pid;
8769 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008770 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008771 info.process = r.processName;
8772 info.foreground = r.isForeground;
8773 info.activeSince = r.createTime;
8774 info.started = r.startRequested;
8775 info.clientCount = r.connections.size();
8776 info.crashCount = r.crashCount;
8777 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008778 if (r.isForeground) {
8779 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8780 }
8781 if (r.startRequested) {
8782 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8783 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008784 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008785 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8786 }
8787 if (r.app != null && r.app.persistent) {
8788 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8789 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008790
8791 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8792 for (int i=0; i<connl.size(); i++) {
8793 ConnectionRecord conn = connl.get(i);
8794 if (conn.clientLabel != 0) {
8795 info.clientPackage = conn.binding.client.info.packageName;
8796 info.clientLabel = conn.clientLabel;
8797 return info;
8798 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008799 }
8800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 return info;
8802 }
8803
8804 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8805 int flags) {
8806 synchronized (this) {
8807 ArrayList<ActivityManager.RunningServiceInfo> res
8808 = new ArrayList<ActivityManager.RunningServiceInfo>();
8809
8810 if (mServices.size() > 0) {
8811 Iterator<ServiceRecord> it = mServices.values().iterator();
8812 while (it.hasNext() && res.size() < maxNum) {
8813 res.add(makeRunningServiceInfoLocked(it.next()));
8814 }
8815 }
8816
8817 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8818 ServiceRecord r = mRestartingServices.get(i);
8819 ActivityManager.RunningServiceInfo info =
8820 makeRunningServiceInfoLocked(r);
8821 info.restarting = r.nextRestartTime;
8822 res.add(info);
8823 }
8824
8825 return res;
8826 }
8827 }
8828
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008829 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8830 synchronized (this) {
8831 ServiceRecord r = mServices.get(name);
8832 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008833 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8834 for (int i=0; i<conn.size(); i++) {
8835 if (conn.get(i).clientIntent != null) {
8836 return conn.get(i).clientIntent;
8837 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008838 }
8839 }
8840 }
8841 }
8842 return null;
8843 }
8844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008845 private final ServiceRecord findServiceLocked(ComponentName name,
8846 IBinder token) {
8847 ServiceRecord r = mServices.get(name);
8848 return r == token ? r : null;
8849 }
8850
8851 private final class ServiceLookupResult {
8852 final ServiceRecord record;
8853 final String permission;
8854
8855 ServiceLookupResult(ServiceRecord _record, String _permission) {
8856 record = _record;
8857 permission = _permission;
8858 }
8859 };
8860
8861 private ServiceLookupResult findServiceLocked(Intent service,
8862 String resolvedType) {
8863 ServiceRecord r = null;
8864 if (service.getComponent() != null) {
8865 r = mServices.get(service.getComponent());
8866 }
8867 if (r == null) {
8868 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8869 r = mServicesByIntent.get(filter);
8870 }
8871
8872 if (r == null) {
8873 try {
8874 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008875 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008876 service, resolvedType, 0);
8877 ServiceInfo sInfo =
8878 rInfo != null ? rInfo.serviceInfo : null;
8879 if (sInfo == null) {
8880 return null;
8881 }
8882
8883 ComponentName name = new ComponentName(
8884 sInfo.applicationInfo.packageName, sInfo.name);
8885 r = mServices.get(name);
8886 } catch (RemoteException ex) {
8887 // pm is in same process, this will never happen.
8888 }
8889 }
8890 if (r != null) {
8891 int callingPid = Binder.getCallingPid();
8892 int callingUid = Binder.getCallingUid();
8893 if (checkComponentPermission(r.permission,
8894 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8895 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008896 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008897 + " from pid=" + callingPid
8898 + ", uid=" + callingUid
8899 + " requires " + r.permission);
8900 return new ServiceLookupResult(null, r.permission);
8901 }
8902 return new ServiceLookupResult(r, null);
8903 }
8904 return null;
8905 }
8906
8907 private class ServiceRestarter implements Runnable {
8908 private ServiceRecord mService;
8909
8910 void setService(ServiceRecord service) {
8911 mService = service;
8912 }
8913
8914 public void run() {
8915 synchronized(ActivityManagerService.this) {
8916 performServiceRestartLocked(mService);
8917 }
8918 }
8919 }
8920
8921 private ServiceLookupResult retrieveServiceLocked(Intent service,
8922 String resolvedType, int callingPid, int callingUid) {
8923 ServiceRecord r = null;
8924 if (service.getComponent() != null) {
8925 r = mServices.get(service.getComponent());
8926 }
8927 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8928 r = mServicesByIntent.get(filter);
8929 if (r == null) {
8930 try {
8931 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008932 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008933 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008934 ServiceInfo sInfo =
8935 rInfo != null ? rInfo.serviceInfo : null;
8936 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008937 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008938 ": not found");
8939 return null;
8940 }
8941
8942 ComponentName name = new ComponentName(
8943 sInfo.applicationInfo.packageName, sInfo.name);
8944 r = mServices.get(name);
8945 if (r == null) {
8946 filter = new Intent.FilterComparison(service.cloneFilter());
8947 ServiceRestarter res = new ServiceRestarter();
8948 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8949 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8950 synchronized (stats) {
8951 ss = stats.getServiceStatsLocked(
8952 sInfo.applicationInfo.uid, sInfo.packageName,
8953 sInfo.name);
8954 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008955 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008956 res.setService(r);
8957 mServices.put(name, r);
8958 mServicesByIntent.put(filter, r);
8959
8960 // Make sure this component isn't in the pending list.
8961 int N = mPendingServices.size();
8962 for (int i=0; i<N; i++) {
8963 ServiceRecord pr = mPendingServices.get(i);
8964 if (pr.name.equals(name)) {
8965 mPendingServices.remove(i);
8966 i--;
8967 N--;
8968 }
8969 }
8970 }
8971 } catch (RemoteException ex) {
8972 // pm is in same process, this will never happen.
8973 }
8974 }
8975 if (r != null) {
8976 if (checkComponentPermission(r.permission,
8977 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8978 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008979 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008980 + " from pid=" + Binder.getCallingPid()
8981 + ", uid=" + Binder.getCallingUid()
8982 + " requires " + r.permission);
8983 return new ServiceLookupResult(null, r.permission);
8984 }
8985 return new ServiceLookupResult(r, null);
8986 }
8987 return null;
8988 }
8989
Dianne Hackborn287952c2010-09-22 22:34:31 -07008990 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8991 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8992 + why + " of " + r + " in app " + r.app);
8993 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8994 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008995 long now = SystemClock.uptimeMillis();
8996 if (r.executeNesting == 0 && r.app != null) {
8997 if (r.app.executingServices.size() == 0) {
8998 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8999 msg.obj = r.app;
9000 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9001 }
9002 r.app.executingServices.add(r);
9003 }
9004 r.executeNesting++;
9005 r.executingStart = now;
9006 }
9007
9008 private final void sendServiceArgsLocked(ServiceRecord r,
9009 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009010 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009011 if (N == 0) {
9012 return;
9013 }
9014
Dianne Hackborn39792d22010-08-19 18:01:52 -07009015 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009016 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009017 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009018 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9019 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009020 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009021 // If somehow we got a dummy start at the front, then
9022 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009023 continue;
9024 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009025 si.deliveredTime = SystemClock.uptimeMillis();
9026 r.deliveredStarts.add(si);
9027 si.deliveryCount++;
9028 if (si.targetPermissionUid >= 0) {
9029 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009030 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009031 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009032 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009033 if (!oomAdjusted) {
9034 oomAdjusted = true;
9035 updateOomAdjLocked(r.app);
9036 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009037 int flags = 0;
9038 if (si.deliveryCount > 0) {
9039 flags |= Service.START_FLAG_RETRY;
9040 }
9041 if (si.doneExecutingCount > 0) {
9042 flags |= Service.START_FLAG_REDELIVERY;
9043 }
9044 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009045 } catch (RemoteException e) {
9046 // Remote process gone... we'll let the normal cleanup take
9047 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009048 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009049 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009051 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009052 break;
9053 }
9054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 }
9056
9057 private final boolean requestServiceBindingLocked(ServiceRecord r,
9058 IntentBindRecord i, boolean rebind) {
9059 if (r.app == null || r.app.thread == null) {
9060 // If service is not currently running, can't yet bind.
9061 return false;
9062 }
9063 if ((!i.requested || rebind) && i.apps.size() > 0) {
9064 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009065 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009066 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9067 if (!rebind) {
9068 i.requested = true;
9069 }
9070 i.hasBound = true;
9071 i.doRebind = false;
9072 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009073 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 return false;
9075 }
9076 }
9077 return true;
9078 }
9079
9080 private final void requestServiceBindingsLocked(ServiceRecord r) {
9081 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9082 while (bindings.hasNext()) {
9083 IntentBindRecord i = bindings.next();
9084 if (!requestServiceBindingLocked(r, i, false)) {
9085 break;
9086 }
9087 }
9088 }
9089
9090 private final void realStartServiceLocked(ServiceRecord r,
9091 ProcessRecord app) throws RemoteException {
9092 if (app.thread == null) {
9093 throw new RemoteException();
9094 }
9095
9096 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009097 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098
9099 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009100 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009101 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102
9103 boolean created = false;
9104 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009105 mStringBuilder.setLength(0);
9106 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009107 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009109 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009110 synchronized (r.stats.getBatteryStats()) {
9111 r.stats.startLaunchedLocked();
9112 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009113 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009114 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009115 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009116 created = true;
9117 } finally {
9118 if (!created) {
9119 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009120 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009121 }
9122 }
9123
9124 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009125
9126 // If the service is in the started state, and there are no
9127 // pending arguments, then fake up one so its onStartCommand() will
9128 // be called.
9129 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9130 r.lastStartId++;
9131 if (r.lastStartId < 1) {
9132 r.lastStartId = 1;
9133 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009134 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009135 }
9136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009137 sendServiceArgsLocked(r, true);
9138 }
9139
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009140 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9141 boolean allowCancel) {
9142 boolean canceled = false;
9143
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009144 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009145 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009146 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009147
Dianne Hackborn070783f2010-12-29 16:46:28 -08009148 if ((r.serviceInfo.applicationInfo.flags
9149 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9150 minDuration /= 4;
9151 }
9152
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009153 // Any delivered but not yet finished starts should be put back
9154 // on the pending list.
9155 final int N = r.deliveredStarts.size();
9156 if (N > 0) {
9157 for (int i=N-1; i>=0; i--) {
9158 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009159 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009160 if (si.intent == null) {
9161 // We'll generate this again if needed.
9162 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9163 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9164 r.pendingStarts.add(0, si);
9165 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9166 dur *= 2;
9167 if (minDuration < dur) minDuration = dur;
9168 if (resetTime < dur) resetTime = dur;
9169 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009170 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009171 + r.name);
9172 canceled = true;
9173 }
9174 }
9175 r.deliveredStarts.clear();
9176 }
9177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 r.totalRestartCount++;
9179 if (r.restartDelay == 0) {
9180 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009181 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 } else {
9183 // If it has been a "reasonably long time" since the service
9184 // was started, then reset our restart duration back to
9185 // the beginning, so we don't infinitely increase the duration
9186 // on a service that just occasionally gets killed (which is
9187 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009188 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009190 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009191 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009192 if ((r.serviceInfo.applicationInfo.flags
9193 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9194 // Services in peristent processes will restart much more
9195 // quickly, since they are pretty important. (Think SystemUI).
9196 r.restartDelay += minDuration/2;
9197 } else {
9198 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9199 if (r.restartDelay < minDuration) {
9200 r.restartDelay = minDuration;
9201 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203 }
9204 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009205
9206 r.nextRestartTime = now + r.restartDelay;
9207
9208 // Make sure that we don't end up restarting a bunch of services
9209 // all at the same time.
9210 boolean repeat;
9211 do {
9212 repeat = false;
9213 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9214 ServiceRecord r2 = mRestartingServices.get(i);
9215 if (r2 != r && r.nextRestartTime
9216 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9217 && r.nextRestartTime
9218 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9219 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9220 r.restartDelay = r.nextRestartTime - now;
9221 repeat = true;
9222 break;
9223 }
9224 }
9225 } while (repeat);
9226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009227 if (!mRestartingServices.contains(r)) {
9228 mRestartingServices.add(r);
9229 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009230
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009231 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009233 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009234 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009235 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009236 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009237 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009238 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009239 r.shortName, r.restartDelay);
9240
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009241 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009242 }
9243
9244 final void performServiceRestartLocked(ServiceRecord r) {
9245 if (!mRestartingServices.contains(r)) {
9246 return;
9247 }
9248 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9249 }
9250
9251 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9252 if (r.restartDelay == 0) {
9253 return false;
9254 }
9255 r.resetRestartCounter();
9256 mRestartingServices.remove(r);
9257 mHandler.removeCallbacks(r.restarter);
9258 return true;
9259 }
9260
9261 private final boolean bringUpServiceLocked(ServiceRecord r,
9262 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009263 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 //r.dump(" ");
9265
Dianne Hackborn36124872009-10-08 16:22:03 -07009266 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009267 sendServiceArgsLocked(r, false);
9268 return true;
9269 }
9270
9271 if (!whileRestarting && r.restartDelay > 0) {
9272 // If waiting for a restart, then do nothing.
9273 return true;
9274 }
9275
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009276 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009277
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009278 // We are now bringing the service up, so no longer in the
9279 // restarting state.
9280 mRestartingServices.remove(r);
9281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009282 final String appName = r.processName;
9283 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9284 if (app != null && app.thread != null) {
9285 try {
9286 realStartServiceLocked(r, app);
9287 return true;
9288 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009289 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290 }
9291
9292 // If a dead object exception was thrown -- fall through to
9293 // restart the application.
9294 }
9295
Dianne Hackborn36124872009-10-08 16:22:03 -07009296 // Not running -- get it started, and enqueue this service record
9297 // to be executed when the app comes up.
9298 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9299 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009300 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009301 + r.appInfo.packageName + "/"
9302 + r.appInfo.uid + " for service "
9303 + r.intent.getIntent() + ": process is bad");
9304 bringDownServiceLocked(r, true);
9305 return false;
9306 }
9307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 mPendingServices.add(r);
9310 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 return true;
9313 }
9314
9315 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009316 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009317 //r.dump(" ");
9318
9319 // Does it still need to run?
9320 if (!force && r.startRequested) {
9321 return;
9322 }
9323 if (r.connections.size() > 0) {
9324 if (!force) {
9325 // XXX should probably keep a count of the number of auto-create
9326 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009327 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009328 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009329 ArrayList<ConnectionRecord> cr = it.next();
9330 for (int i=0; i<cr.size(); i++) {
9331 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9332 return;
9333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 }
9335 }
9336 }
9337
9338 // Report to all of the connections that the service is no longer
9339 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009340 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009341 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009342 ArrayList<ConnectionRecord> c = it.next();
9343 for (int i=0; i<c.size(); i++) {
9344 try {
9345 c.get(i).conn.connected(r.name, null);
9346 } catch (Exception e) {
9347 Slog.w(TAG, "Failure disconnecting service " + r.name +
9348 " to connection " + c.get(i).conn.asBinder() +
9349 " (in " + c.get(i).binding.client.processName + ")", e);
9350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009351 }
9352 }
9353 }
9354
9355 // Tell the service that it has been unbound.
9356 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9357 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9358 while (it.hasNext()) {
9359 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009360 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009361 + ": hasBound=" + ibr.hasBound);
9362 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9363 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009364 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365 updateOomAdjLocked(r.app);
9366 ibr.hasBound = false;
9367 r.app.thread.scheduleUnbindService(r,
9368 ibr.intent.getIntent());
9369 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009370 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009371 + r.shortName, e);
9372 serviceDoneExecutingLocked(r, true);
9373 }
9374 }
9375 }
9376 }
9377
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009378 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009379 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009380 System.identityHashCode(r), r.shortName,
9381 (r.app != null) ? r.app.pid : -1);
9382
9383 mServices.remove(r.name);
9384 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 r.totalRestartCount = 0;
9386 unscheduleServiceRestartLocked(r);
9387
9388 // Also make sure it is not on the pending list.
9389 int N = mPendingServices.size();
9390 for (int i=0; i<N; i++) {
9391 if (mPendingServices.get(i) == r) {
9392 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009393 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 i--;
9395 N--;
9396 }
9397 }
9398
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009399 r.cancelNotification();
9400 r.isForeground = false;
9401 r.foregroundId = 0;
9402 r.foregroundNoti = null;
9403
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009404 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009405 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009406 r.pendingStarts.clear();
9407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009408 if (r.app != null) {
9409 synchronized (r.stats.getBatteryStats()) {
9410 r.stats.stopLaunchedLocked();
9411 }
9412 r.app.services.remove(r);
9413 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009414 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009415 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009416 mStoppingServices.add(r);
9417 updateOomAdjLocked(r.app);
9418 r.app.thread.scheduleStopService(r);
9419 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009420 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009421 + r.shortName, e);
9422 serviceDoneExecutingLocked(r, true);
9423 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009424 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009425 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009426 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009427 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009428 }
9429 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009430 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009431 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009432 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009433
9434 if (r.bindings.size() > 0) {
9435 r.bindings.clear();
9436 }
9437
9438 if (r.restarter instanceof ServiceRestarter) {
9439 ((ServiceRestarter)r.restarter).setService(null);
9440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009441 }
9442
9443 ComponentName startServiceLocked(IApplicationThread caller,
9444 Intent service, String resolvedType,
9445 int callingPid, int callingUid) {
9446 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009447 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009448 + " type=" + resolvedType + " args=" + service.getExtras());
9449
9450 if (caller != null) {
9451 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9452 if (callerApp == null) {
9453 throw new SecurityException(
9454 "Unable to find app for caller " + caller
9455 + " (pid=" + Binder.getCallingPid()
9456 + ") when starting service " + service);
9457 }
9458 }
9459
9460 ServiceLookupResult res =
9461 retrieveServiceLocked(service, resolvedType,
9462 callingPid, callingUid);
9463 if (res == null) {
9464 return null;
9465 }
9466 if (res.record == null) {
9467 return new ComponentName("!", res.permission != null
9468 ? res.permission : "private to package");
9469 }
9470 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009471 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9472 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009473 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009474 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009475 }
9476 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009477 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009478 r.lastStartId++;
9479 if (r.lastStartId < 1) {
9480 r.lastStartId = 1;
9481 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009482 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9483 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 r.lastActivity = SystemClock.uptimeMillis();
9485 synchronized (r.stats.getBatteryStats()) {
9486 r.stats.startRunningLocked();
9487 }
9488 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9489 return new ComponentName("!", "Service process is bad");
9490 }
9491 return r.name;
9492 }
9493 }
9494
9495 public ComponentName startService(IApplicationThread caller, Intent service,
9496 String resolvedType) {
9497 // Refuse possible leaked file descriptors
9498 if (service != null && service.hasFileDescriptors() == true) {
9499 throw new IllegalArgumentException("File descriptors passed in Intent");
9500 }
9501
9502 synchronized(this) {
9503 final int callingPid = Binder.getCallingPid();
9504 final int callingUid = Binder.getCallingUid();
9505 final long origId = Binder.clearCallingIdentity();
9506 ComponentName res = startServiceLocked(caller, service,
9507 resolvedType, callingPid, callingUid);
9508 Binder.restoreCallingIdentity(origId);
9509 return res;
9510 }
9511 }
9512
9513 ComponentName startServiceInPackage(int uid,
9514 Intent service, String resolvedType) {
9515 synchronized(this) {
9516 final long origId = Binder.clearCallingIdentity();
9517 ComponentName res = startServiceLocked(null, service,
9518 resolvedType, -1, uid);
9519 Binder.restoreCallingIdentity(origId);
9520 return res;
9521 }
9522 }
9523
9524 public int stopService(IApplicationThread caller, Intent service,
9525 String resolvedType) {
9526 // Refuse possible leaked file descriptors
9527 if (service != null && service.hasFileDescriptors() == true) {
9528 throw new IllegalArgumentException("File descriptors passed in Intent");
9529 }
9530
9531 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009532 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009533 + " type=" + resolvedType);
9534
9535 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9536 if (caller != null && callerApp == null) {
9537 throw new SecurityException(
9538 "Unable to find app for caller " + caller
9539 + " (pid=" + Binder.getCallingPid()
9540 + ") when stopping service " + service);
9541 }
9542
9543 // If this service is active, make sure it is stopped.
9544 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9545 if (r != null) {
9546 if (r.record != null) {
9547 synchronized (r.record.stats.getBatteryStats()) {
9548 r.record.stats.stopRunningLocked();
9549 }
9550 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009551 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552 final long origId = Binder.clearCallingIdentity();
9553 bringDownServiceLocked(r.record, false);
9554 Binder.restoreCallingIdentity(origId);
9555 return 1;
9556 }
9557 return -1;
9558 }
9559 }
9560
9561 return 0;
9562 }
9563
9564 public IBinder peekService(Intent service, String resolvedType) {
9565 // Refuse possible leaked file descriptors
9566 if (service != null && service.hasFileDescriptors() == true) {
9567 throw new IllegalArgumentException("File descriptors passed in Intent");
9568 }
9569
9570 IBinder ret = null;
9571
9572 synchronized(this) {
9573 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9574
9575 if (r != null) {
9576 // r.record is null if findServiceLocked() failed the caller permission check
9577 if (r.record == null) {
9578 throw new SecurityException(
lge-aospea278a92011-01-07 13:45:37 +09009579 "Permission Denial: Accessing service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 + " from pid=" + Binder.getCallingPid()
9581 + ", uid=" + Binder.getCallingUid()
9582 + " requires " + r.permission);
9583 }
9584 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9585 if (ib != null) {
9586 ret = ib.binder;
9587 }
9588 }
9589 }
9590
9591 return ret;
9592 }
9593
9594 public boolean stopServiceToken(ComponentName className, IBinder token,
9595 int startId) {
9596 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009597 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598 + " " + token + " startId=" + startId);
9599 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009600 if (r != null) {
9601 if (startId >= 0) {
9602 // Asked to only stop if done with all work. Note that
9603 // to avoid leaks, we will take this as dropping all
9604 // start items up to and including this one.
9605 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9606 if (si != null) {
9607 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009608 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9609 cur.removeUriPermissionsLocked();
9610 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009611 break;
9612 }
9613 }
9614 }
9615
9616 if (r.lastStartId != startId) {
9617 return false;
9618 }
9619
9620 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009621 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009622 + " is last, but have " + r.deliveredStarts.size()
9623 + " remaining args");
9624 }
9625 }
9626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009627 synchronized (r.stats.getBatteryStats()) {
9628 r.stats.stopRunningLocked();
9629 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009630 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009631 }
9632 final long origId = Binder.clearCallingIdentity();
9633 bringDownServiceLocked(r, false);
9634 Binder.restoreCallingIdentity(origId);
9635 return true;
9636 }
9637 }
9638 return false;
9639 }
9640
9641 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009642 int id, Notification notification, boolean removeNotification) {
9643 final long origId = Binder.clearCallingIdentity();
9644 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 synchronized(this) {
9646 ServiceRecord r = findServiceLocked(className, token);
9647 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009648 if (id != 0) {
9649 if (notification == null) {
9650 throw new IllegalArgumentException("null notification");
9651 }
9652 if (r.foregroundId != id) {
9653 r.cancelNotification();
9654 r.foregroundId = id;
9655 }
9656 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9657 r.foregroundNoti = notification;
9658 r.isForeground = true;
9659 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009660 if (r.app != null) {
9661 updateServiceForegroundLocked(r.app, true);
9662 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009663 } else {
9664 if (r.isForeground) {
9665 r.isForeground = false;
9666 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009667 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009668 updateServiceForegroundLocked(r.app, true);
9669 }
9670 }
9671 if (removeNotification) {
9672 r.cancelNotification();
9673 r.foregroundId = 0;
9674 r.foregroundNoti = null;
9675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676 }
9677 }
9678 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009679 } finally {
9680 Binder.restoreCallingIdentity(origId);
9681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009682 }
9683
9684 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9685 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009686 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687 if (sr.isForeground) {
9688 anyForeground = true;
9689 break;
9690 }
9691 }
9692 if (anyForeground != proc.foregroundServices) {
9693 proc.foregroundServices = anyForeground;
9694 if (oomAdj) {
9695 updateOomAdjLocked();
9696 }
9697 }
9698 }
9699
9700 public int bindService(IApplicationThread caller, IBinder token,
9701 Intent service, String resolvedType,
9702 IServiceConnection connection, int flags) {
9703 // Refuse possible leaked file descriptors
9704 if (service != null && service.hasFileDescriptors() == true) {
9705 throw new IllegalArgumentException("File descriptors passed in Intent");
9706 }
9707
9708 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009709 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009710 + " type=" + resolvedType + " conn=" + connection.asBinder()
9711 + " flags=0x" + Integer.toHexString(flags));
9712 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9713 if (callerApp == null) {
9714 throw new SecurityException(
9715 "Unable to find app for caller " + caller
9716 + " (pid=" + Binder.getCallingPid()
9717 + ") when binding service " + service);
9718 }
9719
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009720 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009722 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009723 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009724 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009725 return 0;
9726 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009727 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 }
9729
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009730 int clientLabel = 0;
9731 PendingIntent clientIntent = null;
9732
9733 if (callerApp.info.uid == Process.SYSTEM_UID) {
9734 // Hacky kind of thing -- allow system stuff to tell us
9735 // what they are, so we can report this elsewhere for
9736 // others to know why certain services are running.
9737 try {
9738 clientIntent = (PendingIntent)service.getParcelableExtra(
9739 Intent.EXTRA_CLIENT_INTENT);
9740 } catch (RuntimeException e) {
9741 }
9742 if (clientIntent != null) {
9743 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9744 if (clientLabel != 0) {
9745 // There are no useful extras in the intent, trash them.
9746 // System code calling with this stuff just needs to know
9747 // this will happen.
9748 service = service.cloneFilter();
9749 }
9750 }
9751 }
9752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753 ServiceLookupResult res =
9754 retrieveServiceLocked(service, resolvedType,
9755 Binder.getCallingPid(), Binder.getCallingUid());
9756 if (res == null) {
9757 return 0;
9758 }
9759 if (res.record == null) {
9760 return -1;
9761 }
9762 ServiceRecord s = res.record;
9763
9764 final long origId = Binder.clearCallingIdentity();
9765
9766 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009767 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009768 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009769 }
9770
9771 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9772 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009773 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009774
9775 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009776 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9777 if (clist == null) {
9778 clist = new ArrayList<ConnectionRecord>();
9779 s.connections.put(binder, clist);
9780 }
9781 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782 b.connections.add(c);
9783 if (activity != null) {
9784 if (activity.connections == null) {
9785 activity.connections = new HashSet<ConnectionRecord>();
9786 }
9787 activity.connections.add(c);
9788 }
9789 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009790 clist = mServiceConnections.get(binder);
9791 if (clist == null) {
9792 clist = new ArrayList<ConnectionRecord>();
9793 mServiceConnections.put(binder, clist);
9794 }
9795 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796
9797 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9798 s.lastActivity = SystemClock.uptimeMillis();
9799 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9800 return 0;
9801 }
9802 }
9803
9804 if (s.app != null) {
9805 // This could have made the service more important.
9806 updateOomAdjLocked(s.app);
9807 }
9808
Joe Onorato8a9b2202010-02-26 18:56:32 -08009809 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009810 + ": received=" + b.intent.received
9811 + " apps=" + b.intent.apps.size()
9812 + " doRebind=" + b.intent.doRebind);
9813
9814 if (s.app != null && b.intent.received) {
9815 // Service is already running, so we can immediately
9816 // publish the connection.
9817 try {
9818 c.conn.connected(s.name, b.intent.binder);
9819 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009820 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 + " to connection " + c.conn.asBinder()
9822 + " (in " + c.binding.client.processName + ")", e);
9823 }
9824
9825 // If this is the first app connected back to this binding,
9826 // and the service had previously asked to be told when
9827 // rebound, then do so.
9828 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9829 requestServiceBindingLocked(s, b.intent, true);
9830 }
9831 } else if (!b.intent.requested) {
9832 requestServiceBindingLocked(s, b.intent, false);
9833 }
9834
9835 Binder.restoreCallingIdentity(origId);
9836 }
9837
9838 return 1;
9839 }
9840
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009841 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009842 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009843 IBinder binder = c.conn.asBinder();
9844 AppBindRecord b = c.binding;
9845 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009846 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9847 if (clist != null) {
9848 clist.remove(c);
9849 if (clist.size() == 0) {
9850 s.connections.remove(binder);
9851 }
9852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009853 b.connections.remove(c);
9854 if (c.activity != null && c.activity != skipAct) {
9855 if (c.activity.connections != null) {
9856 c.activity.connections.remove(c);
9857 }
9858 }
9859 if (b.client != skipApp) {
9860 b.client.connections.remove(c);
9861 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009862 clist = mServiceConnections.get(binder);
9863 if (clist != null) {
9864 clist.remove(c);
9865 if (clist.size() == 0) {
9866 mServiceConnections.remove(binder);
9867 }
9868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009869
9870 if (b.connections.size() == 0) {
9871 b.intent.apps.remove(b.client);
9872 }
9873
Joe Onorato8a9b2202010-02-26 18:56:32 -08009874 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009875 + ": shouldUnbind=" + b.intent.hasBound);
9876 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9877 && b.intent.hasBound) {
9878 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009879 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009880 updateOomAdjLocked(s.app);
9881 b.intent.hasBound = false;
9882 // Assume the client doesn't want to know about a rebind;
9883 // we will deal with that later if it asks for one.
9884 b.intent.doRebind = false;
9885 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9886 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009887 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009888 serviceDoneExecutingLocked(s, true);
9889 }
9890 }
9891
9892 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9893 bringDownServiceLocked(s, false);
9894 }
9895 }
9896
9897 public boolean unbindService(IServiceConnection connection) {
9898 synchronized (this) {
9899 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009900 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009901 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9902 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009903 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009904 + connection.asBinder());
9905 return false;
9906 }
9907
9908 final long origId = Binder.clearCallingIdentity();
9909
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009910 while (clist.size() > 0) {
9911 ConnectionRecord r = clist.get(0);
9912 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009913
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009914 if (r.binding.service.app != null) {
9915 // This could have made the service less important.
9916 updateOomAdjLocked(r.binding.service.app);
9917 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009918 }
9919
9920 Binder.restoreCallingIdentity(origId);
9921 }
9922
9923 return true;
9924 }
9925
9926 public void publishService(IBinder token, Intent intent, IBinder service) {
9927 // Refuse possible leaked file descriptors
9928 if (intent != null && intent.hasFileDescriptors() == true) {
9929 throw new IllegalArgumentException("File descriptors passed in Intent");
9930 }
9931
9932 synchronized(this) {
9933 if (!(token instanceof ServiceRecord)) {
9934 throw new IllegalArgumentException("Invalid service token");
9935 }
9936 ServiceRecord r = (ServiceRecord)token;
9937
9938 final long origId = Binder.clearCallingIdentity();
9939
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009940 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009941 + " " + intent + ": " + service);
9942 if (r != null) {
9943 Intent.FilterComparison filter
9944 = new Intent.FilterComparison(intent);
9945 IntentBindRecord b = r.bindings.get(filter);
9946 if (b != null && !b.received) {
9947 b.binder = service;
9948 b.requested = true;
9949 b.received = true;
9950 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009951 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009952 = r.connections.values().iterator();
9953 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009954 ArrayList<ConnectionRecord> clist = it.next();
9955 for (int i=0; i<clist.size(); i++) {
9956 ConnectionRecord c = clist.get(i);
9957 if (!filter.equals(c.binding.intent.intent)) {
9958 if (DEBUG_SERVICE) Slog.v(
9959 TAG, "Not publishing to: " + c);
9960 if (DEBUG_SERVICE) Slog.v(
9961 TAG, "Bound intent: " + c.binding.intent.intent);
9962 if (DEBUG_SERVICE) Slog.v(
9963 TAG, "Published intent: " + intent);
9964 continue;
9965 }
9966 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9967 try {
9968 c.conn.connected(r.name, service);
9969 } catch (Exception e) {
9970 Slog.w(TAG, "Failure sending service " + r.name +
9971 " to connection " + c.conn.asBinder() +
9972 " (in " + c.binding.client.processName + ")", e);
9973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009974 }
9975 }
9976 }
9977 }
9978
9979 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9980
9981 Binder.restoreCallingIdentity(origId);
9982 }
9983 }
9984 }
9985
9986 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9987 // Refuse possible leaked file descriptors
9988 if (intent != null && intent.hasFileDescriptors() == true) {
9989 throw new IllegalArgumentException("File descriptors passed in Intent");
9990 }
9991
9992 synchronized(this) {
9993 if (!(token instanceof ServiceRecord)) {
9994 throw new IllegalArgumentException("Invalid service token");
9995 }
9996 ServiceRecord r = (ServiceRecord)token;
9997
9998 final long origId = Binder.clearCallingIdentity();
9999
10000 if (r != null) {
10001 Intent.FilterComparison filter
10002 = new Intent.FilterComparison(intent);
10003 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010004 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010005 + " at " + b + ": apps="
10006 + (b != null ? b.apps.size() : 0));
10007 if (b != null) {
10008 if (b.apps.size() > 0) {
10009 // Applications have already bound since the last
10010 // unbind, so just rebind right here.
10011 requestServiceBindingLocked(r, b, true);
10012 } else {
10013 // Note to tell the service the next time there is
10014 // a new client.
10015 b.doRebind = true;
10016 }
10017 }
10018
10019 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10020
10021 Binder.restoreCallingIdentity(origId);
10022 }
10023 }
10024 }
10025
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010026 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010027 synchronized(this) {
10028 if (!(token instanceof ServiceRecord)) {
10029 throw new IllegalArgumentException("Invalid service token");
10030 }
10031 ServiceRecord r = (ServiceRecord)token;
10032 boolean inStopping = mStoppingServices.contains(token);
10033 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010034 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010035 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010036 + " with incorrect token: given " + token
10037 + ", expected " + r);
10038 return;
10039 }
10040
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010041 if (type == 1) {
10042 // This is a call from a service start... take care of
10043 // book-keeping.
10044 r.callStart = true;
10045 switch (res) {
10046 case Service.START_STICKY_COMPATIBILITY:
10047 case Service.START_STICKY: {
10048 // We are done with the associated start arguments.
10049 r.findDeliveredStart(startId, true);
10050 // Don't stop if killed.
10051 r.stopIfKilled = false;
10052 break;
10053 }
10054 case Service.START_NOT_STICKY: {
10055 // We are done with the associated start arguments.
10056 r.findDeliveredStart(startId, true);
10057 if (r.lastStartId == startId) {
10058 // There is no more work, and this service
10059 // doesn't want to hang around if killed.
10060 r.stopIfKilled = true;
10061 }
10062 break;
10063 }
10064 case Service.START_REDELIVER_INTENT: {
10065 // We'll keep this item until they explicitly
10066 // call stop for it, but keep track of the fact
10067 // that it was delivered.
10068 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10069 if (si != null) {
10070 si.deliveryCount = 0;
10071 si.doneExecutingCount++;
10072 // Don't stop if killed.
10073 r.stopIfKilled = true;
10074 }
10075 break;
10076 }
10077 default:
10078 throw new IllegalArgumentException(
10079 "Unknown service start result: " + res);
10080 }
10081 if (res == Service.START_STICKY_COMPATIBILITY) {
10082 r.callStart = false;
10083 }
10084 }
10085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010086 final long origId = Binder.clearCallingIdentity();
10087 serviceDoneExecutingLocked(r, inStopping);
10088 Binder.restoreCallingIdentity(origId);
10089 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010090 Slog.w(TAG, "Done executing unknown service from pid "
10091 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010092 }
10093 }
10094 }
10095
10096 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010097 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10098 + ": nesting=" + r.executeNesting
10099 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010100 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010101 r.executeNesting--;
10102 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010103 if (DEBUG_SERVICE) Slog.v(TAG,
10104 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010105 r.app.executingServices.remove(r);
10106 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010107 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10108 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010109 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10110 }
10111 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010112 if (DEBUG_SERVICE) Slog.v(TAG,
10113 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010115 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010116 }
10117 updateOomAdjLocked(r.app);
10118 }
10119 }
10120
10121 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010122 String anrMessage = null;
10123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010124 synchronized(this) {
10125 if (proc.executingServices.size() == 0 || proc.thread == null) {
10126 return;
10127 }
10128 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10129 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10130 ServiceRecord timeout = null;
10131 long nextTime = 0;
10132 while (it.hasNext()) {
10133 ServiceRecord sr = it.next();
10134 if (sr.executingStart < maxTime) {
10135 timeout = sr;
10136 break;
10137 }
10138 if (sr.executingStart > nextTime) {
10139 nextTime = sr.executingStart;
10140 }
10141 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010142 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010143 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010144 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010145 } else {
10146 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10147 msg.obj = proc;
10148 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10149 }
10150 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010151
10152 if (anrMessage != null) {
10153 appNotResponding(proc, null, null, anrMessage);
10154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 }
10156
10157 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010158 // BACKUP AND RESTORE
10159 // =========================================================
10160
10161 // Cause the target app to be launched if necessary and its backup agent
10162 // instantiated. The backup agent will invoke backupAgentCreated() on the
10163 // activity manager to announce its creation.
10164 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010165 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010166 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10167
10168 synchronized(this) {
10169 // !!! TODO: currently no check here that we're already bound
10170 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10171 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10172 synchronized (stats) {
10173 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10174 }
10175
10176 BackupRecord r = new BackupRecord(ss, app, backupMode);
10177 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10178 // startProcessLocked() returns existing proc's record if it's already running
10179 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010180 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010181 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010182 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010183 return false;
10184 }
10185
10186 r.app = proc;
10187 mBackupTarget = r;
10188 mBackupAppName = app.packageName;
10189
Christopher Tate6fa95972009-06-05 18:43:55 -070010190 // Try not to kill the process during backup
10191 updateOomAdjLocked(proc);
10192
Christopher Tate181fafa2009-05-14 11:12:14 -070010193 // If the process is already attached, schedule the creation of the backup agent now.
10194 // If it is not yet live, this will be done when it attaches to the framework.
10195 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010196 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010197 try {
10198 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10199 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010200 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010201 }
10202 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010203 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010204 }
10205 // Invariants: at this point, the target app process exists and the application
10206 // is either already running or in the process of coming up. mBackupTarget and
10207 // mBackupAppName describe the app, so that when it binds back to the AM we
10208 // know that it's scheduled for a backup-agent operation.
10209 }
10210
10211 return true;
10212 }
10213
10214 // A backup agent has just come up
10215 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010216 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010217 + " = " + agent);
10218
10219 synchronized(this) {
10220 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010221 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010222 return;
10223 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010224 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010225
Dianne Hackborn06740692010-09-22 22:46:21 -070010226 long oldIdent = Binder.clearCallingIdentity();
10227 try {
10228 IBackupManager bm = IBackupManager.Stub.asInterface(
10229 ServiceManager.getService(Context.BACKUP_SERVICE));
10230 bm.agentConnected(agentPackageName, agent);
10231 } catch (RemoteException e) {
10232 // can't happen; the backup manager service is local
10233 } catch (Exception e) {
10234 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10235 e.printStackTrace();
10236 } finally {
10237 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010238 }
10239 }
10240
10241 // done with this agent
10242 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010243 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010244 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010245 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010246 return;
10247 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010248
10249 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010250 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010251 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010252 return;
10253 }
10254
Christopher Tate181fafa2009-05-14 11:12:14 -070010255 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010256 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010257 return;
10258 }
10259
Christopher Tate6fa95972009-06-05 18:43:55 -070010260 ProcessRecord proc = mBackupTarget.app;
10261 mBackupTarget = null;
10262 mBackupAppName = null;
10263
10264 // Not backing this app up any more; reset its OOM adjustment
10265 updateOomAdjLocked(proc);
10266
Christopher Tatec7b31e32009-06-10 15:49:30 -070010267 // If the app crashed during backup, 'thread' will be null here
10268 if (proc.thread != null) {
10269 try {
10270 proc.thread.scheduleDestroyBackupAgent(appInfo);
10271 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010272 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010273 e.printStackTrace();
10274 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010275 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010276 }
10277 }
10278 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010279 // BROADCASTS
10280 // =========================================================
10281
Josh Bartel7f208742010-02-25 11:01:44 -060010282 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010283 List cur) {
10284 final ContentResolver resolver = mContext.getContentResolver();
10285 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10286 if (list == null) {
10287 return cur;
10288 }
10289 int N = list.size();
10290 for (int i=0; i<N; i++) {
10291 Intent intent = list.get(i);
10292 if (filter.match(resolver, intent, true, TAG) >= 0) {
10293 if (cur == null) {
10294 cur = new ArrayList<Intent>();
10295 }
10296 cur.add(intent);
10297 }
10298 }
10299 return cur;
10300 }
10301
10302 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010303 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 + mBroadcastsScheduled);
10305
10306 if (mBroadcastsScheduled) {
10307 return;
10308 }
10309 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10310 mBroadcastsScheduled = true;
10311 }
10312
10313 public Intent registerReceiver(IApplicationThread caller,
10314 IIntentReceiver receiver, IntentFilter filter, String permission) {
10315 synchronized(this) {
10316 ProcessRecord callerApp = null;
10317 if (caller != null) {
10318 callerApp = getRecordForAppLocked(caller);
10319 if (callerApp == null) {
10320 throw new SecurityException(
10321 "Unable to find app for caller " + caller
10322 + " (pid=" + Binder.getCallingPid()
10323 + ") when registering receiver " + receiver);
10324 }
10325 }
10326
10327 List allSticky = null;
10328
10329 // Look for any matching sticky broadcasts...
10330 Iterator actions = filter.actionsIterator();
10331 if (actions != null) {
10332 while (actions.hasNext()) {
10333 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010334 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010335 }
10336 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010337 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 }
10339
10340 // The first sticky in the list is returned directly back to
10341 // the client.
10342 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10343
Joe Onorato8a9b2202010-02-26 18:56:32 -080010344 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010345 + ": " + sticky);
10346
10347 if (receiver == null) {
10348 return sticky;
10349 }
10350
10351 ReceiverList rl
10352 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10353 if (rl == null) {
10354 rl = new ReceiverList(this, callerApp,
10355 Binder.getCallingPid(),
10356 Binder.getCallingUid(), receiver);
10357 if (rl.app != null) {
10358 rl.app.receivers.add(rl);
10359 } else {
10360 try {
10361 receiver.asBinder().linkToDeath(rl, 0);
10362 } catch (RemoteException e) {
10363 return sticky;
10364 }
10365 rl.linkedToDeath = true;
10366 }
10367 mRegisteredReceivers.put(receiver.asBinder(), rl);
10368 }
10369 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10370 rl.add(bf);
10371 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010372 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 }
10374 mReceiverResolver.addFilter(bf);
10375
10376 // Enqueue broadcasts for all existing stickies that match
10377 // this filter.
10378 if (allSticky != null) {
10379 ArrayList receivers = new ArrayList();
10380 receivers.add(bf);
10381
10382 int N = allSticky.size();
10383 for (int i=0; i<N; i++) {
10384 Intent intent = (Intent)allSticky.get(i);
10385 BroadcastRecord r = new BroadcastRecord(intent, null,
10386 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010387 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 if (mParallelBroadcasts.size() == 0) {
10389 scheduleBroadcastsLocked();
10390 }
10391 mParallelBroadcasts.add(r);
10392 }
10393 }
10394
10395 return sticky;
10396 }
10397 }
10398
10399 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010400 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010401
10402 boolean doNext = false;
10403
10404 synchronized(this) {
10405 ReceiverList rl
10406 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10407 if (rl != null) {
10408 if (rl.curBroadcast != null) {
10409 BroadcastRecord r = rl.curBroadcast;
10410 doNext = finishReceiverLocked(
10411 receiver.asBinder(), r.resultCode, r.resultData,
10412 r.resultExtras, r.resultAbort, true);
10413 }
10414
10415 if (rl.app != null) {
10416 rl.app.receivers.remove(rl);
10417 }
10418 removeReceiverLocked(rl);
10419 if (rl.linkedToDeath) {
10420 rl.linkedToDeath = false;
10421 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10422 }
10423 }
10424 }
10425
10426 if (!doNext) {
10427 return;
10428 }
10429
10430 final long origId = Binder.clearCallingIdentity();
10431 processNextBroadcast(false);
10432 trimApplications();
10433 Binder.restoreCallingIdentity(origId);
10434 }
10435
10436 void removeReceiverLocked(ReceiverList rl) {
10437 mRegisteredReceivers.remove(rl.receiver.asBinder());
10438 int N = rl.size();
10439 for (int i=0; i<N; i++) {
10440 mReceiverResolver.removeFilter(rl.get(i));
10441 }
10442 }
10443
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010444 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10445 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10446 ProcessRecord r = mLruProcesses.get(i);
10447 if (r.thread != null) {
10448 try {
10449 r.thread.dispatchPackageBroadcast(cmd, packages);
10450 } catch (RemoteException ex) {
10451 }
10452 }
10453 }
10454 }
10455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 private final int broadcastIntentLocked(ProcessRecord callerApp,
10457 String callerPackage, Intent intent, String resolvedType,
10458 IIntentReceiver resultTo, int resultCode, String resultData,
10459 Bundle map, String requiredPermission,
10460 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10461 intent = new Intent(intent);
10462
Joe Onorato8a9b2202010-02-26 18:56:32 -080010463 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010464 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10465 + " ordered=" + ordered);
10466 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010467 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468 }
10469
10470 // Handle special intents: if this broadcast is from the package
10471 // manager about a package being removed, we need to remove all of
10472 // its activities from the history stack.
10473 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10474 intent.getAction());
10475 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10476 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010477 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010478 || uidRemoved) {
10479 if (checkComponentPermission(
10480 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10481 callingPid, callingUid, -1)
10482 == PackageManager.PERMISSION_GRANTED) {
10483 if (uidRemoved) {
10484 final Bundle intentExtras = intent.getExtras();
10485 final int uid = intentExtras != null
10486 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10487 if (uid >= 0) {
10488 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10489 synchronized (bs) {
10490 bs.removeUidStatsLocked(uid);
10491 }
10492 }
10493 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010494 // If resources are unvailble just force stop all
10495 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010496 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010497 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10498 if (list != null && (list.length > 0)) {
10499 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010500 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010501 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010502 sendPackageBroadcastLocked(
10503 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010504 }
10505 } else {
10506 Uri data = intent.getData();
10507 String ssp;
10508 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10509 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10510 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010511 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010512 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010513 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10514 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10515 new String[] {ssp});
10516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010517 }
10518 }
10519 }
10520 } else {
10521 String msg = "Permission Denial: " + intent.getAction()
10522 + " broadcast from " + callerPackage + " (pid=" + callingPid
10523 + ", uid=" + callingUid + ")"
10524 + " requires "
10525 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010526 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010527 throw new SecurityException(msg);
10528 }
10529 }
10530
10531 /*
10532 * If this is the time zone changed action, queue up a message that will reset the timezone
10533 * of all currently running processes. This message will get queued up before the broadcast
10534 * happens.
10535 */
10536 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10537 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10538 }
10539
Robert Greenwalt03595d02010-11-02 14:08:23 -070010540 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10541 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10542 }
10543
Robert Greenwalt434203a2010-10-11 16:00:27 -070010544 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10545 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10546 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10547 }
10548
Dianne Hackborn854060af2009-07-09 18:14:31 -070010549 /*
10550 * Prevent non-system code (defined here to be non-persistent
10551 * processes) from sending protected broadcasts.
10552 */
10553 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10554 || callingUid == Process.SHELL_UID || callingUid == 0) {
10555 // Always okay.
10556 } else if (callerApp == null || !callerApp.persistent) {
10557 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010558 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010559 intent.getAction())) {
10560 String msg = "Permission Denial: not allowed to send broadcast "
10561 + intent.getAction() + " from pid="
10562 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010563 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010564 throw new SecurityException(msg);
10565 }
10566 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010567 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010568 return BROADCAST_SUCCESS;
10569 }
10570 }
10571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010572 // Add to the sticky list if requested.
10573 if (sticky) {
10574 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10575 callingPid, callingUid)
10576 != PackageManager.PERMISSION_GRANTED) {
10577 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10578 + callingPid + ", uid=" + callingUid
10579 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010580 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 throw new SecurityException(msg);
10582 }
10583 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010584 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 + " and enforce permission " + requiredPermission);
10586 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10587 }
10588 if (intent.getComponent() != null) {
10589 throw new SecurityException(
10590 "Sticky broadcasts can't target a specific component");
10591 }
10592 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10593 if (list == null) {
10594 list = new ArrayList<Intent>();
10595 mStickyBroadcasts.put(intent.getAction(), list);
10596 }
10597 int N = list.size();
10598 int i;
10599 for (i=0; i<N; i++) {
10600 if (intent.filterEquals(list.get(i))) {
10601 // This sticky already exists, replace it.
10602 list.set(i, new Intent(intent));
10603 break;
10604 }
10605 }
10606 if (i >= N) {
10607 list.add(new Intent(intent));
10608 }
10609 }
10610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 // Figure out who all will receive this broadcast.
10612 List receivers = null;
10613 List<BroadcastFilter> registeredReceivers = null;
10614 try {
10615 if (intent.getComponent() != null) {
10616 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010617 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010618 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010619 if (ai != null) {
10620 receivers = new ArrayList();
10621 ResolveInfo ri = new ResolveInfo();
10622 ri.activityInfo = ai;
10623 receivers.add(ri);
10624 }
10625 } else {
10626 // Need to resolve the intent to interested receivers...
10627 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10628 == 0) {
10629 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010630 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010631 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 }
Mihai Preda074edef2009-05-18 17:13:31 +020010633 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010634 }
10635 } catch (RemoteException ex) {
10636 // pm is in same process, this will never happen.
10637 }
10638
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010639 final boolean replacePending =
10640 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10641
Joe Onorato8a9b2202010-02-26 18:56:32 -080010642 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010643 + " replacePending=" + replacePending);
10644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010645 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10646 if (!ordered && NR > 0) {
10647 // If we are not serializing this broadcast, then send the
10648 // registered receivers separately so they don't wait for the
10649 // components to be launched.
10650 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10651 callerPackage, callingPid, callingUid, requiredPermission,
10652 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010653 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010654 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010655 TAG, "Enqueueing parallel broadcast " + r
10656 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010657 boolean replaced = false;
10658 if (replacePending) {
10659 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10660 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010661 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010662 "***** DROPPING PARALLEL: " + intent);
10663 mParallelBroadcasts.set(i, r);
10664 replaced = true;
10665 break;
10666 }
10667 }
10668 }
10669 if (!replaced) {
10670 mParallelBroadcasts.add(r);
10671 scheduleBroadcastsLocked();
10672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673 registeredReceivers = null;
10674 NR = 0;
10675 }
10676
10677 // Merge into one list.
10678 int ir = 0;
10679 if (receivers != null) {
10680 // A special case for PACKAGE_ADDED: do not allow the package
10681 // being added to see this broadcast. This prevents them from
10682 // using this as a back door to get run as soon as they are
10683 // installed. Maybe in the future we want to have a special install
10684 // broadcast or such for apps, but we'd like to deliberately make
10685 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010686 String skipPackages[] = null;
10687 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10688 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10689 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10690 Uri data = intent.getData();
10691 if (data != null) {
10692 String pkgName = data.getSchemeSpecificPart();
10693 if (pkgName != null) {
10694 skipPackages = new String[] { pkgName };
10695 }
10696 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010697 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010698 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010699 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010700 if (skipPackages != null && (skipPackages.length > 0)) {
10701 for (String skipPackage : skipPackages) {
10702 if (skipPackage != null) {
10703 int NT = receivers.size();
10704 for (int it=0; it<NT; it++) {
10705 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10706 if (curt.activityInfo.packageName.equals(skipPackage)) {
10707 receivers.remove(it);
10708 it--;
10709 NT--;
10710 }
10711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010712 }
10713 }
10714 }
10715
10716 int NT = receivers != null ? receivers.size() : 0;
10717 int it = 0;
10718 ResolveInfo curt = null;
10719 BroadcastFilter curr = null;
10720 while (it < NT && ir < NR) {
10721 if (curt == null) {
10722 curt = (ResolveInfo)receivers.get(it);
10723 }
10724 if (curr == null) {
10725 curr = registeredReceivers.get(ir);
10726 }
10727 if (curr.getPriority() >= curt.priority) {
10728 // Insert this broadcast record into the final list.
10729 receivers.add(it, curr);
10730 ir++;
10731 curr = null;
10732 it++;
10733 NT++;
10734 } else {
10735 // Skip to the next ResolveInfo in the final list.
10736 it++;
10737 curt = null;
10738 }
10739 }
10740 }
10741 while (ir < NR) {
10742 if (receivers == null) {
10743 receivers = new ArrayList();
10744 }
10745 receivers.add(registeredReceivers.get(ir));
10746 ir++;
10747 }
10748
10749 if ((receivers != null && receivers.size() > 0)
10750 || resultTo != null) {
10751 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10752 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010753 receivers, resultTo, resultCode, resultData, map, ordered,
10754 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010755 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010756 TAG, "Enqueueing ordered broadcast " + r
10757 + ": prev had " + mOrderedBroadcasts.size());
10758 if (DEBUG_BROADCAST) {
10759 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010760 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010762 boolean replaced = false;
10763 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010764 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010765 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010766 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010767 "***** DROPPING ORDERED: " + intent);
10768 mOrderedBroadcasts.set(i, r);
10769 replaced = true;
10770 break;
10771 }
10772 }
10773 }
10774 if (!replaced) {
10775 mOrderedBroadcasts.add(r);
10776 scheduleBroadcastsLocked();
10777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 }
10779
10780 return BROADCAST_SUCCESS;
10781 }
10782
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010783 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784 // Refuse possible leaked file descriptors
10785 if (intent != null && intent.hasFileDescriptors() == true) {
10786 throw new IllegalArgumentException("File descriptors passed in Intent");
10787 }
10788
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010789 int flags = intent.getFlags();
10790
10791 if (!mProcessesReady) {
10792 // if the caller really truly claims to know what they're doing, go
10793 // ahead and allow the broadcast without launching any receivers
10794 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10795 intent = new Intent(intent);
10796 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10797 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10798 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10799 + " before boot completion");
10800 throw new IllegalStateException("Cannot broadcast before boot completed");
10801 }
10802 }
10803
10804 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10805 throw new IllegalArgumentException(
10806 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10807 }
10808
10809 return intent;
10810 }
10811
10812 public final int broadcastIntent(IApplicationThread caller,
10813 Intent intent, String resolvedType, IIntentReceiver resultTo,
10814 int resultCode, String resultData, Bundle map,
10815 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010816 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010817 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010819 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10820 final int callingPid = Binder.getCallingPid();
10821 final int callingUid = Binder.getCallingUid();
10822 final long origId = Binder.clearCallingIdentity();
10823 int res = broadcastIntentLocked(callerApp,
10824 callerApp != null ? callerApp.info.packageName : null,
10825 intent, resolvedType, resultTo,
10826 resultCode, resultData, map, requiredPermission, serialized,
10827 sticky, callingPid, callingUid);
10828 Binder.restoreCallingIdentity(origId);
10829 return res;
10830 }
10831 }
10832
10833 int broadcastIntentInPackage(String packageName, int uid,
10834 Intent intent, String resolvedType, IIntentReceiver resultTo,
10835 int resultCode, String resultData, Bundle map,
10836 String requiredPermission, boolean serialized, boolean sticky) {
10837 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010838 intent = verifyBroadcastLocked(intent);
10839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010840 final long origId = Binder.clearCallingIdentity();
10841 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10842 resultTo, resultCode, resultData, map, requiredPermission,
10843 serialized, sticky, -1, uid);
10844 Binder.restoreCallingIdentity(origId);
10845 return res;
10846 }
10847 }
10848
10849 public final void unbroadcastIntent(IApplicationThread caller,
10850 Intent intent) {
10851 // Refuse possible leaked file descriptors
10852 if (intent != null && intent.hasFileDescriptors() == true) {
10853 throw new IllegalArgumentException("File descriptors passed in Intent");
10854 }
10855
10856 synchronized(this) {
10857 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10858 != PackageManager.PERMISSION_GRANTED) {
10859 String msg = "Permission Denial: unbroadcastIntent() from pid="
10860 + Binder.getCallingPid()
10861 + ", uid=" + Binder.getCallingUid()
10862 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010863 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 throw new SecurityException(msg);
10865 }
10866 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10867 if (list != null) {
10868 int N = list.size();
10869 int i;
10870 for (i=0; i<N; i++) {
10871 if (intent.filterEquals(list.get(i))) {
10872 list.remove(i);
10873 break;
10874 }
10875 }
10876 }
10877 }
10878 }
10879
10880 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10881 String resultData, Bundle resultExtras, boolean resultAbort,
10882 boolean explicit) {
10883 if (mOrderedBroadcasts.size() == 0) {
10884 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010885 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010886 }
10887 return false;
10888 }
10889 BroadcastRecord r = mOrderedBroadcasts.get(0);
10890 if (r.receiver == null) {
10891 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010892 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 }
10894 return false;
10895 }
10896 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010897 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 return false;
10899 }
10900 int state = r.state;
10901 r.state = r.IDLE;
10902 if (state == r.IDLE) {
10903 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010904 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010905 }
10906 }
10907 r.receiver = null;
10908 r.intent.setComponent(null);
10909 if (r.curApp != null) {
10910 r.curApp.curReceiver = null;
10911 }
10912 if (r.curFilter != null) {
10913 r.curFilter.receiverList.curBroadcast = null;
10914 }
10915 r.curFilter = null;
10916 r.curApp = null;
10917 r.curComponent = null;
10918 r.curReceiver = null;
10919 mPendingBroadcast = null;
10920
10921 r.resultCode = resultCode;
10922 r.resultData = resultData;
10923 r.resultExtras = resultExtras;
10924 r.resultAbort = resultAbort;
10925
10926 // We will process the next receiver right now if this is finishing
10927 // an app receiver (which is always asynchronous) or after we have
10928 // come back from calling a receiver.
10929 return state == BroadcastRecord.APP_RECEIVE
10930 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10931 }
10932
10933 public void finishReceiver(IBinder who, int resultCode, String resultData,
10934 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010935 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936
10937 // Refuse possible leaked file descriptors
10938 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10939 throw new IllegalArgumentException("File descriptors passed in Bundle");
10940 }
10941
10942 boolean doNext;
10943
10944 final long origId = Binder.clearCallingIdentity();
10945
10946 synchronized(this) {
10947 doNext = finishReceiverLocked(
10948 who, resultCode, resultData, resultExtras, resultAbort, true);
10949 }
10950
10951 if (doNext) {
10952 processNextBroadcast(false);
10953 }
10954 trimApplications();
10955
10956 Binder.restoreCallingIdentity(origId);
10957 }
10958
Jeff Brown4d94a762010-09-23 11:33:28 -070010959 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 if (r.nextReceiver > 0) {
10961 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10962 if (curReceiver instanceof BroadcastFilter) {
10963 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010964 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010965 System.identityHashCode(r),
10966 r.intent.getAction(),
10967 r.nextReceiver - 1,
10968 System.identityHashCode(bf));
10969 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010970 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010971 System.identityHashCode(r),
10972 r.intent.getAction(),
10973 r.nextReceiver - 1,
10974 ((ResolveInfo)curReceiver).toString());
10975 }
10976 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010977 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010979 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 System.identityHashCode(r),
10981 r.intent.getAction(),
10982 r.nextReceiver,
10983 "NONE");
10984 }
10985 }
10986
Jeff Brown4d94a762010-09-23 11:33:28 -070010987 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10988 if (! mPendingBroadcastTimeoutMessage) {
10989 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10990 mHandler.sendMessageAtTime(msg, timeoutTime);
10991 mPendingBroadcastTimeoutMessage = true;
10992 }
10993 }
10994
10995 private final void cancelBroadcastTimeoutLocked() {
10996 if (mPendingBroadcastTimeoutMessage) {
10997 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10998 mPendingBroadcastTimeoutMessage = false;
10999 }
11000 }
11001
11002 private final void broadcastTimeoutLocked(boolean fromMsg) {
11003 if (fromMsg) {
11004 mPendingBroadcastTimeoutMessage = false;
11005 }
11006
11007 if (mOrderedBroadcasts.size() == 0) {
11008 return;
11009 }
11010
11011 long now = SystemClock.uptimeMillis();
11012 BroadcastRecord r = mOrderedBroadcasts.get(0);
11013 if (fromMsg) {
11014 if (mDidDexOpt) {
11015 // Delay timeouts until dexopt finishes.
11016 mDidDexOpt = false;
11017 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11018 setBroadcastTimeoutLocked(timeoutTime);
11019 return;
11020 }
11021 if (! mProcessesReady) {
11022 // Only process broadcast timeouts if the system is ready. That way
11023 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11024 // to do heavy lifting for system up.
11025 return;
11026 }
11027
11028 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11029 if (timeoutTime > now) {
11030 // We can observe premature timeouts because we do not cancel and reset the
11031 // broadcast timeout message after each receiver finishes. Instead, we set up
11032 // an initial timeout then kick it down the road a little further as needed
11033 // when it expires.
11034 if (DEBUG_BROADCAST) Slog.v(TAG,
11035 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11036 + timeoutTime);
11037 setBroadcastTimeoutLocked(timeoutTime);
11038 return;
11039 }
11040 }
11041
11042 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11043 + ", started " + (now - r.receiverTime) + "ms ago");
11044 r.receiverTime = now;
11045 r.anrCount++;
11046
11047 // Current receiver has passed its expiration date.
11048 if (r.nextReceiver <= 0) {
11049 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11050 return;
11051 }
11052
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011053 ProcessRecord app = null;
11054 String anrMessage = null;
11055
Jeff Brown4d94a762010-09-23 11:33:28 -070011056 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11057 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11058 logBroadcastReceiverDiscardLocked(r);
11059 if (curReceiver instanceof BroadcastFilter) {
11060 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11061 if (bf.receiverList.pid != 0
11062 && bf.receiverList.pid != MY_PID) {
11063 synchronized (this.mPidsSelfLocked) {
11064 app = this.mPidsSelfLocked.get(
11065 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011067 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011068 } else {
11069 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011071
Jeff Brown4d94a762010-09-23 11:33:28 -070011072 if (app != null) {
11073 anrMessage = "Broadcast of " + r.intent.toString();
11074 }
11075
11076 if (mPendingBroadcast == r) {
11077 mPendingBroadcast = null;
11078 }
11079
11080 // Move on to the next receiver.
11081 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11082 r.resultExtras, r.resultAbort, true);
11083 scheduleBroadcastsLocked();
11084
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011085 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011086 // Post the ANR to the handler since we do not want to process ANRs while
11087 // potentially holding our lock.
11088 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011090 }
11091
11092 private final void processCurBroadcastLocked(BroadcastRecord r,
11093 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011094 if (DEBUG_BROADCAST) Slog.v(TAG,
11095 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011096 if (app.thread == null) {
11097 throw new RemoteException();
11098 }
11099 r.receiver = app.thread.asBinder();
11100 r.curApp = app;
11101 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011102 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011103
11104 // Tell the application to launch this receiver.
11105 r.intent.setComponent(r.curComponent);
11106
11107 boolean started = false;
11108 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011109 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 "Delivering to component " + r.curComponent
11111 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011112 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11114 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011115 if (DEBUG_BROADCAST) Slog.v(TAG,
11116 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 started = true;
11118 } finally {
11119 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011120 if (DEBUG_BROADCAST) Slog.v(TAG,
11121 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011122 r.receiver = null;
11123 r.curApp = null;
11124 app.curReceiver = null;
11125 }
11126 }
11127
11128 }
11129
Jeff Brown4d94a762010-09-23 11:33:28 -070011130 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011131 Intent intent, int resultCode, String data, Bundle extras,
11132 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011133 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 if (app != null && app.thread != null) {
11135 // If we have an app thread, do the call through that so it is
11136 // correctly ordered with other one-way calls.
11137 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011138 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011139 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011140 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141 }
11142 }
11143
Jeff Brown4d94a762010-09-23 11:33:28 -070011144 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 BroadcastFilter filter, boolean ordered) {
11146 boolean skip = false;
11147 if (filter.requiredPermission != null) {
11148 int perm = checkComponentPermission(filter.requiredPermission,
11149 r.callingPid, r.callingUid, -1);
11150 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011151 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 + r.intent.toString()
11153 + " from " + r.callerPackage + " (pid="
11154 + r.callingPid + ", uid=" + r.callingUid + ")"
11155 + " requires " + filter.requiredPermission
11156 + " due to registered receiver " + filter);
11157 skip = true;
11158 }
11159 }
11160 if (r.requiredPermission != null) {
11161 int perm = checkComponentPermission(r.requiredPermission,
11162 filter.receiverList.pid, filter.receiverList.uid, -1);
11163 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011164 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 + r.intent.toString()
11166 + " to " + filter.receiverList.app
11167 + " (pid=" + filter.receiverList.pid
11168 + ", uid=" + filter.receiverList.uid + ")"
11169 + " requires " + r.requiredPermission
11170 + " due to sender " + r.callerPackage
11171 + " (uid " + r.callingUid + ")");
11172 skip = true;
11173 }
11174 }
11175
11176 if (!skip) {
11177 // If this is not being sent as an ordered broadcast, then we
11178 // don't want to touch the fields that keep track of the current
11179 // state of ordered broadcasts.
11180 if (ordered) {
11181 r.receiver = filter.receiverList.receiver.asBinder();
11182 r.curFilter = filter;
11183 filter.receiverList.curBroadcast = r;
11184 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011185 if (filter.receiverList.app != null) {
11186 // Bump hosting application to no longer be in background
11187 // scheduling class. Note that we can't do that if there
11188 // isn't an app... but we can only be in that case for
11189 // things that directly call the IActivityManager API, which
11190 // are already core system stuff so don't matter for this.
11191 r.curApp = filter.receiverList.app;
11192 filter.receiverList.app.curReceiver = r;
11193 updateOomAdjLocked();
11194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011195 }
11196 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011197 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011199 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011200 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011201 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011202 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011203 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011204 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011205 if (ordered) {
11206 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11207 }
11208 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011209 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 if (ordered) {
11211 r.receiver = null;
11212 r.curFilter = null;
11213 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011214 if (filter.receiverList.app != null) {
11215 filter.receiverList.app.curReceiver = null;
11216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011217 }
11218 }
11219 }
11220 }
11221
Dianne Hackborn12527f92009-11-11 17:39:50 -080011222 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11223 if (r.callingUid < 0) {
11224 // This was from a registerReceiver() call; ignore it.
11225 return;
11226 }
11227 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11228 MAX_BROADCAST_HISTORY-1);
11229 r.finishTime = SystemClock.uptimeMillis();
11230 mBroadcastHistory[0] = r;
11231 }
11232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 private final void processNextBroadcast(boolean fromMsg) {
11234 synchronized(this) {
11235 BroadcastRecord r;
11236
Joe Onorato8a9b2202010-02-26 18:56:32 -080011237 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011238 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011239 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240
11241 updateCpuStats();
11242
11243 if (fromMsg) {
11244 mBroadcastsScheduled = false;
11245 }
11246
11247 // First, deliver any non-serialized broadcasts right away.
11248 while (mParallelBroadcasts.size() > 0) {
11249 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011250 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011251 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011252 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011253 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254 for (int i=0; i<N; i++) {
11255 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011256 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011257 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011259 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011261 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011262 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011263 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 }
11265
11266 // Now take care of the next serialized one...
11267
11268 // If we are waiting for a process to come up to handle the next
11269 // broadcast, then do nothing at this point. Just in case, we
11270 // check that the process we're waiting for still exists.
11271 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011272 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011273 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011274 + mPendingBroadcast.curApp);
11275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276
11277 boolean isDead;
11278 synchronized (mPidsSelfLocked) {
11279 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11280 }
11281 if (!isDead) {
11282 // It's still alive, so keep waiting
11283 return;
11284 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011285 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011286 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011287 mPendingBroadcast.state = BroadcastRecord.IDLE;
11288 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 mPendingBroadcast = null;
11290 }
11291 }
11292
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011293 boolean looped = false;
11294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 do {
11296 if (mOrderedBroadcasts.size() == 0) {
11297 // No more broadcasts pending, so all done!
11298 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011299 if (looped) {
11300 // If we had finished the last ordered broadcast, then
11301 // make sure all processes have correct oom and sched
11302 // adjustments.
11303 updateOomAdjLocked();
11304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011305 return;
11306 }
11307 r = mOrderedBroadcasts.get(0);
11308 boolean forceReceive = false;
11309
11310 // Ensure that even if something goes awry with the timeout
11311 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011312 // and continue to make progress.
11313 //
11314 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011315 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011316 // one time heavy lifting after system upgrades and can take
11317 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011318 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011319 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011320 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011321 if ((numReceivers > 0) &&
11322 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011323 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011324 + " now=" + now
11325 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011326 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011327 + " intent=" + r.intent
11328 + " numReceivers=" + numReceivers
11329 + " nextReceiver=" + r.nextReceiver
11330 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011331 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011332 forceReceive = true;
11333 r.state = BroadcastRecord.IDLE;
11334 }
11335 }
11336
11337 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011338 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 "processNextBroadcast() called when not idle (state="
11340 + r.state + ")");
11341 return;
11342 }
11343
11344 if (r.receivers == null || r.nextReceiver >= numReceivers
11345 || r.resultAbort || forceReceive) {
11346 // No more receivers for this broadcast! Send the final
11347 // result if requested...
11348 if (r.resultTo != null) {
11349 try {
11350 if (DEBUG_BROADCAST) {
11351 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011352 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011353 + " seq=" + seq + " app=" + r.callerApp);
11354 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011355 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011356 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011357 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011358 // Set this to null so that the reference
11359 // (local and remote) isnt kept in the mBroadcastHistory.
11360 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011362 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011363 }
11364 }
11365
Joe Onorato8a9b2202010-02-26 18:56:32 -080011366 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011367 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011368
Joe Onorato8a9b2202010-02-26 18:56:32 -080011369 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011370 + r);
11371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011372 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011373 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011374 mOrderedBroadcasts.remove(0);
11375 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011376 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011377 continue;
11378 }
11379 } while (r == null);
11380
11381 // Get the next receiver...
11382 int recIdx = r.nextReceiver++;
11383
11384 // Keep track of when this receiver started, and make sure there
11385 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011386 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011388 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011389
Joe Onorato8a9b2202010-02-26 18:56:32 -080011390 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011391 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011392 }
11393 if (! mPendingBroadcastTimeoutMessage) {
11394 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011395 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011396 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11397 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011398 }
11399
11400 Object nextReceiver = r.receivers.get(recIdx);
11401 if (nextReceiver instanceof BroadcastFilter) {
11402 // Simple case: this is a registered receiver who gets
11403 // a direct call.
11404 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011405 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011406 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011407 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011408 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011409 if (r.receiver == null || !r.ordered) {
11410 // The receiver has already finished, so schedule to
11411 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011412 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11413 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 r.state = BroadcastRecord.IDLE;
11415 scheduleBroadcastsLocked();
11416 }
11417 return;
11418 }
11419
11420 // Hard case: need to instantiate the receiver, possibly
11421 // starting its application process to host it.
11422
11423 ResolveInfo info =
11424 (ResolveInfo)nextReceiver;
11425
11426 boolean skip = false;
11427 int perm = checkComponentPermission(info.activityInfo.permission,
11428 r.callingPid, r.callingUid,
11429 info.activityInfo.exported
11430 ? -1 : info.activityInfo.applicationInfo.uid);
11431 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011432 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011433 + r.intent.toString()
11434 + " from " + r.callerPackage + " (pid=" + r.callingPid
11435 + ", uid=" + r.callingUid + ")"
11436 + " requires " + info.activityInfo.permission
11437 + " due to receiver " + info.activityInfo.packageName
11438 + "/" + info.activityInfo.name);
11439 skip = true;
11440 }
11441 if (r.callingUid != Process.SYSTEM_UID &&
11442 r.requiredPermission != null) {
11443 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011444 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 checkPermission(r.requiredPermission,
11446 info.activityInfo.applicationInfo.packageName);
11447 } catch (RemoteException e) {
11448 perm = PackageManager.PERMISSION_DENIED;
11449 }
11450 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011451 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 + r.intent + " to "
11453 + info.activityInfo.applicationInfo.packageName
11454 + " requires " + r.requiredPermission
11455 + " due to sender " + r.callerPackage
11456 + " (uid " + r.callingUid + ")");
11457 skip = true;
11458 }
11459 }
11460 if (r.curApp != null && r.curApp.crashing) {
11461 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011462 if (DEBUG_BROADCAST) Slog.v(TAG,
11463 "Skipping deliver ordered " + r + " to " + r.curApp
11464 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011465 skip = true;
11466 }
11467
11468 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011469 if (DEBUG_BROADCAST) Slog.v(TAG,
11470 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011471 r.receiver = null;
11472 r.curFilter = null;
11473 r.state = BroadcastRecord.IDLE;
11474 scheduleBroadcastsLocked();
11475 return;
11476 }
11477
11478 r.state = BroadcastRecord.APP_RECEIVE;
11479 String targetProcess = info.activityInfo.processName;
11480 r.curComponent = new ComponentName(
11481 info.activityInfo.applicationInfo.packageName,
11482 info.activityInfo.name);
11483 r.curReceiver = info.activityInfo;
11484
11485 // Is this receiver's application already running?
11486 ProcessRecord app = getProcessRecordLocked(targetProcess,
11487 info.activityInfo.applicationInfo.uid);
11488 if (app != null && app.thread != null) {
11489 try {
11490 processCurBroadcastLocked(r, app);
11491 return;
11492 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011493 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011494 + r.curComponent, e);
11495 }
11496
11497 // If a dead object exception was thrown -- fall through to
11498 // restart the application.
11499 }
11500
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011501 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011502 if (DEBUG_BROADCAST) Slog.v(TAG,
11503 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011504 if ((r.curApp=startProcessLocked(targetProcess,
11505 info.activityInfo.applicationInfo, true,
11506 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011507 "broadcast", r.curComponent,
11508 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11509 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011510 // Ah, this recipient is unavailable. Finish it if necessary,
11511 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011512 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 + info.activityInfo.applicationInfo.packageName + "/"
11514 + info.activityInfo.applicationInfo.uid + " for broadcast "
11515 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011516 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011517 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11518 r.resultExtras, r.resultAbort, true);
11519 scheduleBroadcastsLocked();
11520 r.state = BroadcastRecord.IDLE;
11521 return;
11522 }
11523
11524 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011525 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 }
11527 }
11528
11529 // =========================================================
11530 // INSTRUMENTATION
11531 // =========================================================
11532
11533 public boolean startInstrumentation(ComponentName className,
11534 String profileFile, int flags, Bundle arguments,
11535 IInstrumentationWatcher watcher) {
11536 // Refuse possible leaked file descriptors
11537 if (arguments != null && arguments.hasFileDescriptors()) {
11538 throw new IllegalArgumentException("File descriptors passed in Bundle");
11539 }
11540
11541 synchronized(this) {
11542 InstrumentationInfo ii = null;
11543 ApplicationInfo ai = null;
11544 try {
11545 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011546 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011548 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 } catch (PackageManager.NameNotFoundException e) {
11550 }
11551 if (ii == null) {
11552 reportStartInstrumentationFailure(watcher, className,
11553 "Unable to find instrumentation info for: " + className);
11554 return false;
11555 }
11556 if (ai == null) {
11557 reportStartInstrumentationFailure(watcher, className,
11558 "Unable to find instrumentation target package: " + ii.targetPackage);
11559 return false;
11560 }
11561
11562 int match = mContext.getPackageManager().checkSignatures(
11563 ii.targetPackage, ii.packageName);
11564 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11565 String msg = "Permission Denial: starting instrumentation "
11566 + className + " from pid="
11567 + Binder.getCallingPid()
11568 + ", uid=" + Binder.getCallingPid()
11569 + " not allowed because package " + ii.packageName
11570 + " does not have a signature matching the target "
11571 + ii.targetPackage;
11572 reportStartInstrumentationFailure(watcher, className, msg);
11573 throw new SecurityException(msg);
11574 }
11575
11576 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011577 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 ProcessRecord app = addAppLocked(ai);
11579 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011580 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011581 app.instrumentationProfileFile = profileFile;
11582 app.instrumentationArguments = arguments;
11583 app.instrumentationWatcher = watcher;
11584 app.instrumentationResultClass = className;
11585 Binder.restoreCallingIdentity(origId);
11586 }
11587
11588 return true;
11589 }
11590
11591 /**
11592 * Report errors that occur while attempting to start Instrumentation. Always writes the
11593 * error to the logs, but if somebody is watching, send the report there too. This enables
11594 * the "am" command to report errors with more information.
11595 *
11596 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11597 * @param cn The component name of the instrumentation.
11598 * @param report The error report.
11599 */
11600 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11601 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011602 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011603 try {
11604 if (watcher != null) {
11605 Bundle results = new Bundle();
11606 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11607 results.putString("Error", report);
11608 watcher.instrumentationStatus(cn, -1, results);
11609 }
11610 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011611 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 }
11613 }
11614
11615 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11616 if (app.instrumentationWatcher != null) {
11617 try {
11618 // NOTE: IInstrumentationWatcher *must* be oneway here
11619 app.instrumentationWatcher.instrumentationFinished(
11620 app.instrumentationClass,
11621 resultCode,
11622 results);
11623 } catch (RemoteException e) {
11624 }
11625 }
11626 app.instrumentationWatcher = null;
11627 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011628 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011629 app.instrumentationProfileFile = null;
11630 app.instrumentationArguments = null;
11631
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011632 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 }
11634
11635 public void finishInstrumentation(IApplicationThread target,
11636 int resultCode, Bundle results) {
11637 // Refuse possible leaked file descriptors
11638 if (results != null && results.hasFileDescriptors()) {
11639 throw new IllegalArgumentException("File descriptors passed in Intent");
11640 }
11641
11642 synchronized(this) {
11643 ProcessRecord app = getRecordForAppLocked(target);
11644 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011645 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011646 return;
11647 }
11648 final long origId = Binder.clearCallingIdentity();
11649 finishInstrumentationLocked(app, resultCode, results);
11650 Binder.restoreCallingIdentity(origId);
11651 }
11652 }
11653
11654 // =========================================================
11655 // CONFIGURATION
11656 // =========================================================
11657
11658 public ConfigurationInfo getDeviceConfigurationInfo() {
11659 ConfigurationInfo config = new ConfigurationInfo();
11660 synchronized (this) {
11661 config.reqTouchScreen = mConfiguration.touchscreen;
11662 config.reqKeyboardType = mConfiguration.keyboard;
11663 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011664 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11665 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11667 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011668 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11669 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011670 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11671 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011672 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 }
11674 return config;
11675 }
11676
11677 public Configuration getConfiguration() {
11678 Configuration ci;
11679 synchronized(this) {
11680 ci = new Configuration(mConfiguration);
11681 }
11682 return ci;
11683 }
11684
11685 public void updateConfiguration(Configuration values) {
11686 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11687 "updateConfiguration()");
11688
11689 synchronized(this) {
11690 if (values == null && mWindowManager != null) {
11691 // sentinel: fetch the current configuration from the window manager
11692 values = mWindowManager.computeNewConfiguration();
11693 }
11694
11695 final long origId = Binder.clearCallingIdentity();
11696 updateConfigurationLocked(values, null);
11697 Binder.restoreCallingIdentity(origId);
11698 }
11699 }
11700
11701 /**
11702 * Do either or both things: (1) change the current configuration, and (2)
11703 * make sure the given activity is running with the (now) current
11704 * configuration. Returns true if the activity has been left running, or
11705 * false if <var>starting</var> is being destroyed to match the new
11706 * configuration.
11707 */
11708 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011709 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011710 int changes = 0;
11711
11712 boolean kept = true;
11713
11714 if (values != null) {
11715 Configuration newConfig = new Configuration(mConfiguration);
11716 changes = newConfig.updateFrom(values);
11717 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011718 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011719 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011720 }
11721
Doug Zongker2bec3d42009-12-04 12:52:44 -080011722 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011723
11724 if (values.locale != null) {
11725 saveLocaleLocked(values.locale,
11726 !values.locale.equals(mConfiguration.locale),
11727 values.userSetLocale);
11728 }
11729
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011730 mConfigurationSeq++;
11731 if (mConfigurationSeq <= 0) {
11732 mConfigurationSeq = 1;
11733 }
11734 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011735 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011736 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011737
11738 AttributeCache ac = AttributeCache.instance();
11739 if (ac != null) {
11740 ac.updateConfiguration(mConfiguration);
11741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011742
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011743 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11744 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11745 msg.obj = new Configuration(mConfiguration);
11746 mHandler.sendMessage(msg);
11747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011748
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011749 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11750 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011751 try {
11752 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011753 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011754 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011755 app.thread.scheduleConfigurationChanged(mConfiguration);
11756 }
11757 } catch (Exception e) {
11758 }
11759 }
11760 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011761 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11762 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11764 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011765 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11766 broadcastIntentLocked(null, null,
11767 new Intent(Intent.ACTION_LOCALE_CHANGED),
11768 null, null, 0, null, null,
11769 null, false, false, MY_PID, Process.SYSTEM_UID);
11770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 }
11772 }
11773
11774 if (changes != 0 && starting == null) {
11775 // If the configuration changed, and the caller is not already
11776 // in the process of starting an activity, then find the top
11777 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011778 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 }
11780
11781 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011782 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080011783 // And we need to make sure at this point that all other activities
11784 // are made visible with the correct configuration.
11785 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011786 }
11787
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011788 if (values != null && mWindowManager != null) {
11789 mWindowManager.setNewConfiguration(mConfiguration);
11790 }
11791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011792 return kept;
11793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794
11795 /**
11796 * Save the locale. You must be inside a synchronized (this) block.
11797 */
11798 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11799 if(isDiff) {
11800 SystemProperties.set("user.language", l.getLanguage());
11801 SystemProperties.set("user.region", l.getCountry());
11802 }
11803
11804 if(isPersist) {
11805 SystemProperties.set("persist.sys.language", l.getLanguage());
11806 SystemProperties.set("persist.sys.country", l.getCountry());
11807 SystemProperties.set("persist.sys.localevar", l.getVariant());
11808 }
11809 }
11810
11811 // =========================================================
11812 // LIFETIME MANAGEMENT
11813 // =========================================================
11814
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011815 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11816 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011817 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011818 // This adjustment has already been computed. If we are calling
11819 // from the top, we may have already computed our adjustment with
11820 // an earlier hidden adjustment that isn't really for us... if
11821 // so, use the new hidden adjustment.
11822 if (!recursed && app.hidden) {
11823 app.curAdj = hiddenAdj;
11824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011825 return app.curAdj;
11826 }
11827
11828 if (app.thread == null) {
11829 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011830 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011831 return (app.curAdj=EMPTY_APP_ADJ);
11832 }
11833
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011834 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11835 // The max adjustment doesn't allow this app to be anything
11836 // below foreground, so it is not worth doing work for it.
11837 app.adjType = "fixed";
11838 app.adjSeq = mAdjSeq;
11839 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011840 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011841 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11842 return (app.curAdj=app.maxAdj);
11843 }
11844
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011845 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011846 app.adjSource = null;
11847 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011848 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011849 app.empty = false;
11850 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011851
The Android Open Source Project4df24232009-03-05 14:34:35 -080011852 // Determine the importance of the process, starting with most
11853 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011854 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011855 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011857 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011858 // The last app on the list is the foreground app.
11859 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011860 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011861 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011862 } else if (app.instrumentationClass != null) {
11863 // Don't want to kill running instrumentation.
11864 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011865 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011866 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011867 } else if (app.curReceiver != null ||
11868 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11869 // An app that is currently receiving a broadcast also
11870 // counts as being in the foreground.
11871 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011872 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011873 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011874 } else if (app.executingServices.size() > 0) {
11875 // An app that is currently executing a service callback also
11876 // counts as being in the foreground.
11877 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011878 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011879 app.adjType = "exec-service";
11880 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011882 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011883 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011884 app.adjType = "foreground-service";
11885 } else if (app.forcingToForeground != null) {
11886 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011887 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011888 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011889 app.adjType = "force-foreground";
11890 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011891 } else if (app == mHeavyWeightProcess) {
11892 // We don't want to kill the current heavy-weight process.
11893 adj = HEAVY_WEIGHT_APP_ADJ;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011894 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011895 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011896 } else if (app == mHomeProcess) {
11897 // This process is hosting what we currently consider to be the
11898 // home app, so we don't want to let it go into the background.
11899 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011900 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011901 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011902 } else if ((N=app.activities.size()) != 0) {
11903 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011904 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011905 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011906 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011907 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011908 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011910 ActivityRecord r = app.activities.get(j);
11911 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011912 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011913 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011914 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011915 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011916 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011917 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080011918 } else if (r.state == ActivityState.PAUSING
11919 || r.state == ActivityState.PAUSED
11920 || r.state == ActivityState.STOPPING) {
11921 adj = PERCEPTIBLE_APP_ADJ;
11922 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011923 }
11924 }
11925 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011926 // A very not-needed process. If this is lower in the lru list,
11927 // we will push it in to the empty bucket.
11928 app.hidden = true;
11929 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011930 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011931 adj = hiddenAdj;
11932 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011933 }
11934
Joe Onorato8a9b2202010-02-26 18:56:32 -080011935 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011936
The Android Open Source Project4df24232009-03-05 14:34:35 -080011937 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011938 // there are applications dependent on our services or providers, but
11939 // this gives us a baseline and makes sure we don't get into an
11940 // infinite recursion.
11941 app.adjSeq = mAdjSeq;
11942 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011943
Christopher Tate6fa95972009-06-05 18:43:55 -070011944 if (mBackupTarget != null && app == mBackupTarget.app) {
11945 // If possible we want to avoid killing apps while they're being backed up
11946 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011947 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011948 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011949 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011950 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011951 }
11952 }
11953
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011954 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11955 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011956 final long now = SystemClock.uptimeMillis();
11957 // This process is more important if the top activity is
11958 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011959 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011960 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011961 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011962 if (s.startRequested) {
11963 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11964 // This service has seen some activity within
11965 // recent memory, so we will keep its process ahead
11966 // of the background processes.
11967 if (adj > SECONDARY_SERVER_ADJ) {
11968 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011969 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011970 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011971 }
11972 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011973 // If we have let the service slide into the background
11974 // state, still have some text describing what it is doing
11975 // even though the service no longer has an impact.
11976 if (adj > SECONDARY_SERVER_ADJ) {
11977 app.adjType = "started-bg-services";
11978 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011979 // Don't kill this process because it is doing work; it
11980 // has said it is doing work.
11981 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011982 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011983 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11984 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011985 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011986 = s.connections.values().iterator();
11987 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011988 ArrayList<ConnectionRecord> clist = kt.next();
11989 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11990 // XXX should compute this based on the max of
11991 // all connected clients.
11992 ConnectionRecord cr = clist.get(i);
11993 if (cr.binding.client == app) {
11994 // Binding to ourself is not interesting.
11995 continue;
11996 }
11997 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11998 ProcessRecord client = cr.binding.client;
11999 int myHiddenAdj = hiddenAdj;
12000 if (myHiddenAdj > client.hiddenAdj) {
12001 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12002 myHiddenAdj = client.hiddenAdj;
12003 } else {
12004 myHiddenAdj = VISIBLE_APP_ADJ;
12005 }
12006 }
12007 int clientAdj = computeOomAdjLocked(
12008 client, myHiddenAdj, TOP_APP, true);
12009 if (adj > clientAdj) {
12010 adj = clientAdj >= VISIBLE_APP_ADJ
12011 ? clientAdj : VISIBLE_APP_ADJ;
12012 if (!client.hidden) {
12013 app.hidden = false;
12014 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012015 if (client.keeping) {
12016 app.keeping = true;
12017 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012018 app.adjType = "service";
12019 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12020 .REASON_SERVICE_IN_USE;
12021 app.adjSource = cr.binding.client;
12022 app.adjTarget = s.name;
12023 }
12024 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12025 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12026 schedGroup = Process.THREAD_GROUP_DEFAULT;
12027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012028 }
12029 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012030 ActivityRecord a = cr.activity;
12031 //if (a != null) {
12032 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12033 //}
12034 if (a != null && adj > FOREGROUND_APP_ADJ &&
12035 (a.state == ActivityState.RESUMED
12036 || a.state == ActivityState.PAUSING)) {
12037 adj = FOREGROUND_APP_ADJ;
12038 schedGroup = Process.THREAD_GROUP_DEFAULT;
12039 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012040 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012041 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12042 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012043 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012044 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012046 }
12047 }
12048 }
12049 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012050
Dianne Hackborn287952c2010-09-22 22:34:31 -070012051 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012052 // would like to avoid killing it unless it would prevent the current
12053 // application from running. By default we put the process in
12054 // with the rest of the background processes; as we scan through
12055 // its services we may bump it up from there.
12056 if (adj > hiddenAdj) {
12057 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012058 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012059 app.adjType = "bg-services";
12060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012061 }
12062
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012063 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12064 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012065 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012066 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12067 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012068 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012069 if (cpr.clients.size() != 0) {
12070 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12071 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12072 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012073 if (client == app) {
12074 // Being our own client is not interesting.
12075 continue;
12076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012077 int myHiddenAdj = hiddenAdj;
12078 if (myHiddenAdj > client.hiddenAdj) {
12079 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12080 myHiddenAdj = client.hiddenAdj;
12081 } else {
12082 myHiddenAdj = FOREGROUND_APP_ADJ;
12083 }
12084 }
12085 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012086 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012087 if (adj > clientAdj) {
12088 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012089 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012090 if (!client.hidden) {
12091 app.hidden = false;
12092 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012093 if (client.keeping) {
12094 app.keeping = true;
12095 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012096 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012097 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12098 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012099 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012100 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012101 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012102 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12103 schedGroup = Process.THREAD_GROUP_DEFAULT;
12104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012105 }
12106 }
12107 // If the provider has external (non-framework) process
12108 // dependencies, ensure that its adjustment is at least
12109 // FOREGROUND_APP_ADJ.
12110 if (cpr.externals != 0) {
12111 if (adj > FOREGROUND_APP_ADJ) {
12112 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012113 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012114 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012115 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012116 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012117 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012118 }
12119 }
12120 }
12121 }
12122
12123 app.curRawAdj = adj;
12124
Joe Onorato8a9b2202010-02-26 18:56:32 -080012125 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012126 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12127 if (adj > app.maxAdj) {
12128 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012129 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012130 schedGroup = Process.THREAD_GROUP_DEFAULT;
12131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012132 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012133 if (adj < HIDDEN_APP_MIN_ADJ) {
12134 app.keeping = true;
12135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012136
12137 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012138 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012140 return adj;
12141 }
12142
12143 /**
12144 * Ask a given process to GC right now.
12145 */
12146 final void performAppGcLocked(ProcessRecord app) {
12147 try {
12148 app.lastRequestedGc = SystemClock.uptimeMillis();
12149 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012150 if (app.reportLowMemory) {
12151 app.reportLowMemory = false;
12152 app.thread.scheduleLowMemory();
12153 } else {
12154 app.thread.processInBackground();
12155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012156 }
12157 } catch (Exception e) {
12158 // whatever.
12159 }
12160 }
12161
12162 /**
12163 * Returns true if things are idle enough to perform GCs.
12164 */
Josh Bartel7f208742010-02-25 11:01:44 -060012165 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012166 return mParallelBroadcasts.size() == 0
12167 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012168 && (mSleeping || (mMainStack.mResumedActivity != null &&
12169 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012170 }
12171
12172 /**
12173 * Perform GCs on all processes that are waiting for it, but only
12174 * if things are idle.
12175 */
12176 final void performAppGcsLocked() {
12177 final int N = mProcessesToGc.size();
12178 if (N <= 0) {
12179 return;
12180 }
Josh Bartel7f208742010-02-25 11:01:44 -060012181 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012182 while (mProcessesToGc.size() > 0) {
12183 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012184 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012185 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12186 <= SystemClock.uptimeMillis()) {
12187 // To avoid spamming the system, we will GC processes one
12188 // at a time, waiting a few seconds between each.
12189 performAppGcLocked(proc);
12190 scheduleAppGcsLocked();
12191 return;
12192 } else {
12193 // It hasn't been long enough since we last GCed this
12194 // process... put it in the list to wait for its time.
12195 addProcessToGcListLocked(proc);
12196 break;
12197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012198 }
12199 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012200
12201 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012202 }
12203 }
12204
12205 /**
12206 * If all looks good, perform GCs on all processes waiting for them.
12207 */
12208 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012209 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012210 performAppGcsLocked();
12211 return;
12212 }
12213 // Still not idle, wait some more.
12214 scheduleAppGcsLocked();
12215 }
12216
12217 /**
12218 * Schedule the execution of all pending app GCs.
12219 */
12220 final void scheduleAppGcsLocked() {
12221 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012222
12223 if (mProcessesToGc.size() > 0) {
12224 // Schedule a GC for the time to the next process.
12225 ProcessRecord proc = mProcessesToGc.get(0);
12226 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12227
12228 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12229 long now = SystemClock.uptimeMillis();
12230 if (when < (now+GC_TIMEOUT)) {
12231 when = now + GC_TIMEOUT;
12232 }
12233 mHandler.sendMessageAtTime(msg, when);
12234 }
12235 }
12236
12237 /**
12238 * Add a process to the array of processes waiting to be GCed. Keeps the
12239 * list in sorted order by the last GC time. The process can't already be
12240 * on the list.
12241 */
12242 final void addProcessToGcListLocked(ProcessRecord proc) {
12243 boolean added = false;
12244 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12245 if (mProcessesToGc.get(i).lastRequestedGc <
12246 proc.lastRequestedGc) {
12247 added = true;
12248 mProcessesToGc.add(i+1, proc);
12249 break;
12250 }
12251 }
12252 if (!added) {
12253 mProcessesToGc.add(0, proc);
12254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012255 }
12256
12257 /**
12258 * Set up to ask a process to GC itself. This will either do it
12259 * immediately, or put it on the list of processes to gc the next
12260 * time things are idle.
12261 */
12262 final void scheduleAppGcLocked(ProcessRecord app) {
12263 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012264 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012265 return;
12266 }
12267 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012268 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012269 scheduleAppGcsLocked();
12270 }
12271 }
12272
Dianne Hackborn287952c2010-09-22 22:34:31 -070012273 final void checkExcessivePowerUsageLocked(boolean doKills) {
12274 updateCpuStatsNow();
12275
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012276 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012277 boolean doWakeKills = doKills;
12278 boolean doCpuKills = doKills;
12279 if (mLastPowerCheckRealtime == 0) {
12280 doWakeKills = false;
12281 }
12282 if (mLastPowerCheckUptime == 0) {
12283 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012284 }
12285 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012286 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012287 }
12288 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012289 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12290 final long curUptime = SystemClock.uptimeMillis();
12291 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12292 mLastPowerCheckRealtime = curRealtime;
12293 mLastPowerCheckUptime = curUptime;
12294 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12295 doWakeKills = false;
12296 }
12297 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12298 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012299 }
12300 int i = mLruProcesses.size();
12301 while (i > 0) {
12302 i--;
12303 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012304 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012305 long wtime;
12306 synchronized (stats) {
12307 wtime = stats.getProcessWakeTime(app.info.uid,
12308 app.pid, curRealtime);
12309 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012310 long wtimeUsed = wtime - app.lastWakeTime;
12311 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12312 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012313 StringBuilder sb = new StringBuilder(128);
12314 sb.append("Wake for ");
12315 app.toShortString(sb);
12316 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012317 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012318 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012319 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012320 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012321 sb.append((wtimeUsed*100)/realtimeSince);
12322 sb.append("%)");
12323 Slog.i(TAG, sb.toString());
12324 sb.setLength(0);
12325 sb.append("CPU for ");
12326 app.toShortString(sb);
12327 sb.append(": over ");
12328 TimeUtils.formatDuration(uptimeSince, sb);
12329 sb.append(" used ");
12330 TimeUtils.formatDuration(cputimeUsed, sb);
12331 sb.append(" (");
12332 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012333 sb.append("%)");
12334 Slog.i(TAG, sb.toString());
12335 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012336 // If a process has held a wake lock for more
12337 // than 50% of the time during this period,
12338 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012339 if (doWakeKills && realtimeSince > 0
12340 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12341 synchronized (stats) {
12342 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12343 realtimeSince, wtimeUsed);
12344 }
12345 Slog.w(TAG, "Excessive wake lock in " + app.processName
12346 + " (pid " + app.pid + "): held " + wtimeUsed
12347 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012348 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12349 app.processName, app.setAdj, "excessive wake lock");
12350 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012351 } else if (doCpuKills && uptimeSince > 0
12352 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12353 synchronized (stats) {
12354 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12355 uptimeSince, cputimeUsed);
12356 }
12357 Slog.w(TAG, "Excessive CPU in " + app.processName
12358 + " (pid " + app.pid + "): used " + cputimeUsed
12359 + " during " + uptimeSince);
12360 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12361 app.processName, app.setAdj, "excessive cpu");
12362 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012363 } else {
12364 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012365 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012366 }
12367 }
12368 }
12369 }
12370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012371 private final boolean updateOomAdjLocked(
12372 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12373 app.hiddenAdj = hiddenAdj;
12374
12375 if (app.thread == null) {
12376 return true;
12377 }
12378
Dianne Hackborn287952c2010-09-22 22:34:31 -070012379 final boolean wasKeeping = app.keeping;
12380
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012381 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012383 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012384 if (app.curRawAdj != app.setRawAdj) {
12385 if (app.curRawAdj > FOREGROUND_APP_ADJ
12386 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12387 // If this app is transitioning from foreground to
12388 // non-foreground, have it do a gc.
12389 scheduleAppGcLocked(app);
12390 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12391 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12392 // Likewise do a gc when an app is moving in to the
12393 // background (such as a service stopping).
12394 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012395 }
12396
12397 if (wasKeeping && !app.keeping) {
12398 // This app is no longer something we want to keep. Note
12399 // its current wake lock time to later know to kill it if
12400 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012401 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12402 synchronized (stats) {
12403 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12404 app.pid, SystemClock.elapsedRealtime());
12405 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012406 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012407 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012409 app.setRawAdj = app.curRawAdj;
12410 }
12411 if (adj != app.setAdj) {
12412 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012413 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012414 TAG, "Set app " + app.processName +
12415 " oom adj to " + adj);
12416 app.setAdj = adj;
12417 } else {
12418 return false;
12419 }
12420 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012421 if (app.setSchedGroup != app.curSchedGroup) {
12422 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012423 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012424 "Setting process group of " + app.processName
12425 + " to " + app.curSchedGroup);
12426 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012427 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012428 try {
12429 Process.setProcessGroup(app.pid, app.curSchedGroup);
12430 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012431 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012432 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012433 e.printStackTrace();
12434 } finally {
12435 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012436 }
12437 }
12438 if (false) {
12439 if (app.thread != null) {
12440 try {
12441 app.thread.setSchedulingGroup(app.curSchedGroup);
12442 } catch (RemoteException e) {
12443 }
12444 }
12445 }
12446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447 }
12448
12449 return true;
12450 }
12451
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012452 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012453 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012454 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012455 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012456 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012457 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012458 }
12459 }
12460 return resumedActivity;
12461 }
12462
12463 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012464 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012465 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12466 int curAdj = app.curAdj;
12467 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12468 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12469
12470 mAdjSeq++;
12471
12472 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12473 if (res) {
12474 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12475 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12476 if (nowHidden != wasHidden) {
12477 // Changed to/from hidden state, so apps after it in the LRU
12478 // list may also be changed.
12479 updateOomAdjLocked();
12480 }
12481 }
12482 return res;
12483 }
12484
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012485 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012486 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012487 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012488 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12489
12490 if (false) {
12491 RuntimeException e = new RuntimeException();
12492 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012493 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012494 }
12495
12496 mAdjSeq++;
12497
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012498 // Let's determine how many processes we have running vs.
12499 // how many slots we have for background processes; we may want
12500 // to put multiple processes in a slot of there are enough of
12501 // them.
12502 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12503 int factor = (mLruProcesses.size()-4)/numSlots;
12504 if (factor < 1) factor = 1;
12505 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012506 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012508 // First try updating the OOM adjustment for each of the
12509 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012510 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012511 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12512 while (i > 0) {
12513 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012514 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012515 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012516 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012517 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012518 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012519 step++;
12520 if (step >= factor) {
12521 step = 0;
12522 curHiddenAdj++;
12523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012524 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012525 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012526 if (!app.killedBackground) {
12527 numHidden++;
12528 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012529 Slog.i(TAG, "No longer want " + app.processName
12530 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012531 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12532 app.processName, app.setAdj, "too many background");
12533 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012534 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012535 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012536 }
12537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012538 } else {
12539 didOomAdj = false;
12540 }
12541 }
12542
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012543 // If we return false, we will fall back on killing processes to
12544 // have a fixed limit. Do this if a limit has been requested; else
12545 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012546 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12547 }
12548
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012549 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012550 synchronized (this) {
12551 int i;
12552
12553 // First remove any unused application processes whose package
12554 // has been removed.
12555 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12556 final ProcessRecord app = mRemovedProcesses.get(i);
12557 if (app.activities.size() == 0
12558 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012559 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012560 TAG, "Exiting empty application process "
12561 + app.processName + " ("
12562 + (app.thread != null ? app.thread.asBinder() : null)
12563 + ")\n");
12564 if (app.pid > 0 && app.pid != MY_PID) {
12565 Process.killProcess(app.pid);
12566 } else {
12567 try {
12568 app.thread.scheduleExit();
12569 } catch (Exception e) {
12570 // Ignore exceptions.
12571 }
12572 }
12573 cleanUpApplicationRecordLocked(app, false, -1);
12574 mRemovedProcesses.remove(i);
12575
12576 if (app.persistent) {
12577 if (app.persistent) {
12578 addAppLocked(app.info);
12579 }
12580 }
12581 }
12582 }
12583
12584 // Now try updating the OOM adjustment for each of the
12585 // application processes based on their current state.
12586 // If the setOomAdj() API is not supported, then go with our
12587 // back-up plan...
12588 if (!updateOomAdjLocked()) {
12589
12590 // Count how many processes are running services.
12591 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012592 for (i=mLruProcesses.size()-1; i>=0; i--) {
12593 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012594
12595 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012596 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012597 // Don't count processes holding services against our
12598 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012599 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012600 TAG, "Not trimming app " + app + " with services: "
12601 + app.services);
12602 numServiceProcs++;
12603 }
12604 }
12605
12606 int curMaxProcs = mProcessLimit;
12607 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12608 if (mAlwaysFinishActivities) {
12609 curMaxProcs = 1;
12610 }
12611 curMaxProcs += numServiceProcs;
12612
12613 // Quit as many processes as we can to get down to the desired
12614 // process count. First remove any processes that no longer
12615 // have activites running in them.
12616 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012617 i<mLruProcesses.size()
12618 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012619 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012620 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012621 // Quit an application only if it is not currently
12622 // running any activities.
12623 if (!app.persistent && app.activities.size() == 0
12624 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012625 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012626 TAG, "Exiting empty application process "
12627 + app.processName + " ("
12628 + (app.thread != null ? app.thread.asBinder() : null)
12629 + ")\n");
12630 if (app.pid > 0 && app.pid != MY_PID) {
12631 Process.killProcess(app.pid);
12632 } else {
12633 try {
12634 app.thread.scheduleExit();
12635 } catch (Exception e) {
12636 // Ignore exceptions.
12637 }
12638 }
12639 // todo: For now we assume the application is not buggy
12640 // or evil, and will quit as a result of our request.
12641 // Eventually we need to drive this off of the death
12642 // notification, and kill the process if it takes too long.
12643 cleanUpApplicationRecordLocked(app, false, i);
12644 i--;
12645 }
12646 }
12647
12648 // If we still have too many processes, now from the least
12649 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012650 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012651 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012652 " of " + curMaxProcs + " processes");
12653 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012654 i<mLruProcesses.size()
12655 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012657 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012658 // Quit the application only if we have a state saved for
12659 // all of its activities.
12660 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012661 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012662 int NUMA = app.activities.size();
12663 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012664 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012665 TAG, "Looking to quit " + app.processName);
12666 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012667 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012668 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012669 TAG, " " + r.intent.getComponent().flattenToShortString()
12670 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12671 canQuit = (r.haveState || !r.stateNotNeeded)
12672 && !r.visible && r.stopped;
12673 }
12674 if (canQuit) {
12675 // Finish all of the activities, and then the app itself.
12676 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012677 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012678 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012679 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012680 }
12681 r.resultTo = null;
12682 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012683 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012684 + app.processName + " ("
12685 + (app.thread != null ? app.thread.asBinder() : null)
12686 + ")\n");
12687 if (app.pid > 0 && app.pid != MY_PID) {
12688 Process.killProcess(app.pid);
12689 } else {
12690 try {
12691 app.thread.scheduleExit();
12692 } catch (Exception e) {
12693 // Ignore exceptions.
12694 }
12695 }
12696 // todo: For now we assume the application is not buggy
12697 // or evil, and will quit as a result of our request.
12698 // Eventually we need to drive this off of the death
12699 // notification, and kill the process if it takes too long.
12700 cleanUpApplicationRecordLocked(app, false, i);
12701 i--;
12702 //dump();
12703 }
12704 }
12705
12706 }
12707
12708 int curMaxActivities = MAX_ACTIVITIES;
12709 if (mAlwaysFinishActivities) {
12710 curMaxActivities = 1;
12711 }
12712
12713 // Finally, if there are too many activities now running, try to
12714 // finish as many as we can to get back down to the limit.
12715 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012716 i<mMainStack.mLRUActivities.size()
12717 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012718 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012719 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012720 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012721
12722 // We can finish this one if we have its icicle saved and
12723 // it is not persistent.
12724 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012725 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012726 final int origSize = mMainStack.mLRUActivities.size();
12727 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012728
12729 // This will remove it from the LRU list, so keep
12730 // our index at the same value. Note that this check to
12731 // see if the size changes is just paranoia -- if
12732 // something unexpected happens, we don't want to end up
12733 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012734 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012735 i--;
12736 }
12737 }
12738 }
12739 }
12740 }
12741
12742 /** This method sends the specified signal to each of the persistent apps */
12743 public void signalPersistentProcesses(int sig) throws RemoteException {
12744 if (sig != Process.SIGNAL_USR1) {
12745 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12746 }
12747
12748 synchronized (this) {
12749 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12750 != PackageManager.PERMISSION_GRANTED) {
12751 throw new SecurityException("Requires permission "
12752 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12753 }
12754
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012755 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12756 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012757 if (r.thread != null && r.persistent) {
12758 Process.sendSignal(r.pid, sig);
12759 }
12760 }
12761 }
12762 }
12763
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012764 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012765 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012766
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012767 try {
12768 synchronized (this) {
12769 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12770 // its own permission.
12771 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12772 != PackageManager.PERMISSION_GRANTED) {
12773 throw new SecurityException("Requires permission "
12774 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012775 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012776
12777 if (start && fd == null) {
12778 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012779 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012780
12781 ProcessRecord proc = null;
12782 try {
12783 int pid = Integer.parseInt(process);
12784 synchronized (mPidsSelfLocked) {
12785 proc = mPidsSelfLocked.get(pid);
12786 }
12787 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012788 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012789
12790 if (proc == null) {
12791 HashMap<String, SparseArray<ProcessRecord>> all
12792 = mProcessNames.getMap();
12793 SparseArray<ProcessRecord> procs = all.get(process);
12794 if (procs != null && procs.size() > 0) {
12795 proc = procs.valueAt(0);
12796 }
12797 }
12798
12799 if (proc == null || proc.thread == null) {
12800 throw new IllegalArgumentException("Unknown process: " + process);
12801 }
12802
12803 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12804 if (isSecure) {
12805 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12806 throw new SecurityException("Process not debuggable: " + proc);
12807 }
12808 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012809
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012810 proc.thread.profilerControl(start, path, fd);
12811 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012812 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012813 }
12814 } catch (RemoteException e) {
12815 throw new IllegalStateException("Process disappeared");
12816 } finally {
12817 if (fd != null) {
12818 try {
12819 fd.close();
12820 } catch (IOException e) {
12821 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012822 }
12823 }
12824 }
Andy McFadden824c5102010-07-09 16:26:57 -070012825
12826 public boolean dumpHeap(String process, boolean managed,
12827 String path, ParcelFileDescriptor fd) throws RemoteException {
12828
12829 try {
12830 synchronized (this) {
12831 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12832 // its own permission (same as profileControl).
12833 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12834 != PackageManager.PERMISSION_GRANTED) {
12835 throw new SecurityException("Requires permission "
12836 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
12837 }
12838
12839 if (fd == null) {
12840 throw new IllegalArgumentException("null fd");
12841 }
12842
12843 ProcessRecord proc = null;
12844 try {
12845 int pid = Integer.parseInt(process);
12846 synchronized (mPidsSelfLocked) {
12847 proc = mPidsSelfLocked.get(pid);
12848 }
12849 } catch (NumberFormatException e) {
12850 }
12851
12852 if (proc == null) {
12853 HashMap<String, SparseArray<ProcessRecord>> all
12854 = mProcessNames.getMap();
12855 SparseArray<ProcessRecord> procs = all.get(process);
12856 if (procs != null && procs.size() > 0) {
12857 proc = procs.valueAt(0);
12858 }
12859 }
12860
12861 if (proc == null || proc.thread == null) {
12862 throw new IllegalArgumentException("Unknown process: " + process);
12863 }
12864
12865 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12866 if (isSecure) {
12867 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12868 throw new SecurityException("Process not debuggable: " + proc);
12869 }
12870 }
12871
12872 proc.thread.dumpHeap(managed, path, fd);
12873 fd = null;
12874 return true;
12875 }
12876 } catch (RemoteException e) {
12877 throw new IllegalStateException("Process disappeared");
12878 } finally {
12879 if (fd != null) {
12880 try {
12881 fd.close();
12882 } catch (IOException e) {
12883 }
12884 }
12885 }
12886 }
12887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012888 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12889 public void monitor() {
12890 synchronized (this) { }
12891 }
12892}