blob: 4f0d2d56499bdf2e6989fd6cdd5b6a86db4ad9c3 [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;
58import android.content.Intent;
59import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070060import android.content.IIntentReceiver;
61import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070062import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.content.pm.ActivityInfo;
64import android.content.pm.ApplicationInfo;
65import android.content.pm.ConfigurationInfo;
66import android.content.pm.IPackageDataObserver;
67import android.content.pm.IPackageManager;
68import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080069import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070071import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.ProviderInfo;
73import android.content.pm.ResolveInfo;
74import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070075import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.res.Configuration;
77import android.graphics.Bitmap;
78import android.net.Uri;
79import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080080import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070082import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.FileUtils;
87import android.os.Handler;
88import android.os.IBinder;
89import android.os.IPermissionController;
90import android.os.Looper;
91import android.os.Message;
92import android.os.Parcel;
93import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070095import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.RemoteException;
97import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070098import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.SystemClock;
100import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.Config;
103import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800104import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800105import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.util.PrintWriterPrinter;
107import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700108import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.view.Gravity;
110import android.view.LayoutInflater;
111import android.view.View;
112import android.view.WindowManager;
113import android.view.WindowManagerPolicy;
114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.File;
116import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200118import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800119import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.PrintWriter;
121import java.lang.IllegalStateException;
122import java.lang.ref.WeakReference;
123import java.util.ArrayList;
124import java.util.HashMap;
125import java.util.HashSet;
126import java.util.Iterator;
127import java.util.List;
128import java.util.Locale;
129import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700130import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700131import java.util.concurrent.atomic.AtomicBoolean;
132import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700134public final class ActivityManagerService extends ActivityManagerNative
135 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 static final String TAG = "ActivityManager";
137 static final boolean DEBUG = false;
138 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
139 static final boolean DEBUG_SWITCH = localLOGV || false;
140 static final boolean DEBUG_TASKS = localLOGV || false;
141 static final boolean DEBUG_PAUSE = localLOGV || false;
142 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
143 static final boolean DEBUG_TRANSITION = localLOGV || false;
144 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700145 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 static final boolean DEBUG_SERVICE = localLOGV || false;
147 static final boolean DEBUG_VISBILITY = localLOGV || false;
148 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700149 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800150 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700152 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700153 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700154 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean VALIDATE_TOKENS = false;
156 static final boolean SHOW_ACTIVITY_START_TIME = true;
157
158 // Control over CPU and battery monitoring.
159 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
160 static final boolean MONITOR_CPU_USAGE = true;
161 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
162 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
163 static final boolean MONITOR_THREAD_CPU_USAGE = false;
164
Dianne Hackborn1655be42009-05-08 14:29:01 -0700165 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700166 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 private static final String SYSTEM_SECURE = "ro.secure";
169
170 // This is the maximum number of application processes we would like
171 // to have running. Due to the asynchronous nature of things, we can
172 // temporarily go beyond this limit.
173 static final int MAX_PROCESSES = 2;
174
175 // Set to false to leave processes running indefinitely, relying on
176 // the kernel killing them as resources are required.
177 static final boolean ENFORCE_PROCESS_LIMIT = false;
178
179 // This is the maximum number of activities that we would like to have
180 // running at a given time.
181 static final int MAX_ACTIVITIES = 20;
182
183 // Maximum number of recent tasks that we can remember.
184 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700185
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700186 // Amount of time after a call to stopAppSwitches() during which we will
187 // prevent further untrusted switches from happening.
188 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
190 // How long we wait for a launched process to attach to the activity manager
191 // before we decide it's never going to come up for real.
192 static final int PROC_START_TIMEOUT = 10*1000;
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 // How long to wait after going idle before forcing apps to GC.
195 static final int GC_TIMEOUT = 5*1000;
196
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700197 // The minimum amount of time between successive GC requests for a process.
198 static final int GC_MIN_INTERVAL = 60*1000;
199
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700200 // The rate at which we check for apps using excessive wake locks -- 15 mins.
201 static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 // How long we allow a receiver to run before giving up on it.
204 static final int BROADCAST_TIMEOUT = 10*1000;
205
206 // How long we wait for a service to finish executing.
207 static final int SERVICE_TIMEOUT = 20*1000;
208
209 // How long a service needs to be running until restarting its process
210 // is no longer considered to be a relaunch of the service.
211 static final int SERVICE_RESTART_DURATION = 5*1000;
212
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700213 // How long a service needs to be running until it will start back at
214 // SERVICE_RESTART_DURATION after being killed.
215 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
216
217 // Multiplying factor to increase restart duration time by, for each time
218 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
219 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
220
221 // The minimum amount of time between restarting services that we allow.
222 // That is, when multiple services are restarting, we won't allow each
223 // to restart less than this amount of time from the last one.
224 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 // Maximum amount of time for there to be no activity on a service before
227 // we consider it non-essential and allow its process to go on the
228 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700229 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230
231 // How long we wait until we timeout on key dispatching.
232 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
233
234 // The minimum time we allow between crashes, for us to consider this
235 // application to be bad and stop and its services and reject broadcasts.
236 static final int MIN_CRASH_INTERVAL = 60*1000;
237
238 // How long we wait until we timeout on key dispatching during instrumentation.
239 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
240
241 // OOM adjustments for processes in various states:
242
243 // This is a process without anything currently running in it. Definitely
244 // the first to go! Value set in system/rootdir/init.rc on startup.
245 // This value is initalized in the constructor, careful when refering to
246 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800247 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248
249 // This is a process only hosting activities that are not visible,
250 // so it can be killed without any disruption. Value set in
251 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800252 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 static int HIDDEN_APP_MIN_ADJ;
254
The Android Open Source Project4df24232009-03-05 14:34:35 -0800255 // This is a process holding the home application -- we want to try
256 // avoiding killing it, even if it would normally be in the background,
257 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800258 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800259
Christopher Tate6fa95972009-06-05 18:43:55 -0700260 // This is a process currently hosting a backup operation. Killing it
261 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800262 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 // This is a process holding a secondary server -- killing it will not
265 // have much of an impact as far as the user is concerned. Value set in
266 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800267 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700269 // This is a process with a heavy-weight application. It is in the
270 // background, but we want to try to avoid killing it. Value set in
271 // system/rootdir/init.rc on startup.
272 static final int HEAVY_WEIGHT_APP_ADJ;
273
274 // This is a process only hosting components that are perceptible to the
275 // user, and we really want to avoid killing them, but they are not
276 // immediately visible. An example is background music playback. Value set in
277 // system/rootdir/init.rc on startup.
278 static final int PERCEPTIBLE_APP_ADJ;
279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 // This is a process only hosting activities that are visible to the
281 // user, so we'd prefer they don't disappear. Value set in
282 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800283 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
285 // This is the process running the current foreground app. We'd really
286 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 // This is a process running a core server, such as telephony. Definitely
290 // don't want to kill it, but doing so is not completely fatal.
291 static final int CORE_SERVER_ADJ = -12;
292
293 // The system process runs at the default adjustment.
294 static final int SYSTEM_ADJ = -16;
295
296 // Memory pages are 4K.
297 static final int PAGE_SIZE = 4*1024;
298
299 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800300 static final int EMPTY_APP_MEM;
301 static final int HIDDEN_APP_MEM;
302 static final int HOME_APP_MEM;
303 static final int BACKUP_APP_MEM;
304 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700305 static final int HEAVY_WEIGHT_APP_MEM;
306 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int VISIBLE_APP_MEM;
308 static final int FOREGROUND_APP_MEM;
309
310 // The minimum number of hidden apps we want to be able to keep around,
311 // without empty apps being able to push them out of memory.
312 static final int MIN_HIDDEN_APPS = 2;
313
Dianne Hackborn8633e682010-04-22 16:03:41 -0700314 // The maximum number of hidden processes we will keep around before
315 // killing them; this is just a control to not let us go too crazy with
316 // keeping around processes on devices with large amounts of RAM.
317 static final int MAX_HIDDEN_APPS = 15;
318
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800319 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700320 // been idle for less than 15 seconds.
321 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800322
323 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700324 // been idle for less than 120 seconds.
325 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800326
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700327 static int getIntProp(String name, boolean allowZero) {
328 String str = SystemProperties.get(name);
329 if (str == null) {
330 throw new IllegalArgumentException("Property not defined: " + name);
331 }
332 int val = Integer.valueOf(str);
333 if (val == 0 && !allowZero) {
334 throw new IllegalArgumentException("Property must not be zero: " + name);
335 }
336 return val;
337 }
338
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339 static {
340 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700341 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
342 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
343 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
344 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
345 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
346 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
347 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
348 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
349 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
350 // These days we use the last empty slot for hidden apps as well.
351 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
352 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
353 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
354 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
355 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
356 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
357 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
358 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
359 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
360 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362
Dan Egnor42471dd2010-01-07 17:25:22 -0800363 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364
365 static final String[] EMPTY_STRING_ARRAY = new String[0];
366
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700367 public ActivityStack mMainStack;
368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700370 * Description of a request to start a new activity, which has been held
371 * due to app switches being disabled.
372 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700373 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700374 ActivityRecord r;
375 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700376 Uri[] grantedUriPermissions;
377 int grantedMode;
378 boolean onlyIfNeeded;
379 }
380
381 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
382 = new ArrayList<PendingActivityLaunch>();
383
384 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 * List of all active broadcasts that are to be executed immediately
386 * (without waiting for another broadcast to finish). Currently this only
387 * contains broadcasts to registered receivers, to avoid spinning up
388 * a bunch of processes to execute IntentReceiver components.
389 */
390 final ArrayList<BroadcastRecord> mParallelBroadcasts
391 = new ArrayList<BroadcastRecord>();
392
393 /**
394 * List of all active broadcasts that are to be executed one at a time.
395 * The object at the top of the list is the currently activity broadcasts;
396 * those after it are waiting for the top to finish..
397 */
398 final ArrayList<BroadcastRecord> mOrderedBroadcasts
399 = new ArrayList<BroadcastRecord>();
400
401 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800402 * Historical data of past broadcasts, for debugging.
403 */
404 static final int MAX_BROADCAST_HISTORY = 100;
405 final BroadcastRecord[] mBroadcastHistory
406 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
407
408 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 * Set when we current have a BROADCAST_INTENT_MSG in flight.
410 */
411 boolean mBroadcastsScheduled = false;
412
413 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 * Activity we have told the window manager to have key focus.
415 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700416 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700417 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 * List of intents that were used to start the most recent tasks.
419 */
420 final ArrayList<TaskRecord> mRecentTasks
421 = new ArrayList<TaskRecord>();
422
423 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 * All of the applications we currently have running organized by name.
425 * The keys are strings of the application package name (as
426 * returned by the package manager), and the keys are ApplicationRecord
427 * objects.
428 */
429 final ProcessMap<ProcessRecord> mProcessNames
430 = new ProcessMap<ProcessRecord>();
431
432 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700433 * The currently running heavy-weight process, if any.
434 */
435 ProcessRecord mHeavyWeightProcess = null;
436
437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * The last time that various processes have crashed.
439 */
440 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
441
442 /**
443 * Set of applications that we consider to be bad, and will reject
444 * incoming broadcasts from (which the user has no control over).
445 * Processes are added to this set when they have crashed twice within
446 * a minimum amount of time; they are removed from it when they are
447 * later restarted (hopefully due to some user action). The value is the
448 * time it was added to the list.
449 */
450 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
451
452 /**
453 * All of the processes we currently have running organized by pid.
454 * The keys are the pid running the application.
455 *
456 * <p>NOTE: This object is protected by its own lock, NOT the global
457 * activity manager lock!
458 */
459 final SparseArray<ProcessRecord> mPidsSelfLocked
460 = new SparseArray<ProcessRecord>();
461
462 /**
463 * All of the processes that have been forced to be foreground. The key
464 * is the pid of the caller who requested it (we hold a death
465 * link on it).
466 */
467 abstract class ForegroundToken implements IBinder.DeathRecipient {
468 int pid;
469 IBinder token;
470 }
471 final SparseArray<ForegroundToken> mForegroundProcesses
472 = new SparseArray<ForegroundToken>();
473
474 /**
475 * List of records for processes that someone had tried to start before the
476 * system was ready. We don't start them at that point, but ensure they
477 * are started by the time booting is complete.
478 */
479 final ArrayList<ProcessRecord> mProcessesOnHold
480 = new ArrayList<ProcessRecord>();
481
482 /**
483 * List of records for processes that we have started and are waiting
484 * for them to call back. This is really only needed when running in
485 * single processes mode, in which case we do not have a unique pid for
486 * each process.
487 */
488 final ArrayList<ProcessRecord> mStartingProcesses
489 = new ArrayList<ProcessRecord>();
490
491 /**
492 * List of persistent applications that are in the process
493 * of being started.
494 */
495 final ArrayList<ProcessRecord> mPersistentStartingProcesses
496 = new ArrayList<ProcessRecord>();
497
498 /**
499 * Processes that are being forcibly torn down.
500 */
501 final ArrayList<ProcessRecord> mRemovedProcesses
502 = new ArrayList<ProcessRecord>();
503
504 /**
505 * List of running applications, sorted by recent usage.
506 * The first entry in the list is the least recently used.
507 * It contains ApplicationRecord objects. This list does NOT include
508 * any persistent application records (since we never want to exit them).
509 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800510 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 = new ArrayList<ProcessRecord>();
512
513 /**
514 * List of processes that should gc as soon as things are idle.
515 */
516 final ArrayList<ProcessRecord> mProcessesToGc
517 = new ArrayList<ProcessRecord>();
518
519 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800520 * This is the process holding what we currently consider to be
521 * the "home" activity.
522 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700523 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800524
525 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 * Set of PendingResultRecord objects that are currently active.
527 */
528 final HashSet mPendingResultRecords = new HashSet();
529
530 /**
531 * Set of IntentSenderRecord objects that are currently active.
532 */
533 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
534 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
535
536 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700537 * Fingerprints (String.hashCode()) of stack traces that we've
538 * already logged DropBox entries for. Guarded by itself. If
539 * something (rogue user app) forces this over
540 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
541 */
542 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
543 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
544
545 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700546 * Strict Mode background batched logging state.
547 *
548 * The string buffer is guarded by itself, and its lock is also
549 * used to determine if another batched write is already
550 * in-flight.
551 */
552 private final StringBuilder mStrictModeBuffer = new StringBuilder();
553
554 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 * Intent broadcast that we have tried to start, but are
556 * waiting for its application's process to be created. We only
557 * need one (instead of a list) because we always process broadcasts
558 * one at a time, so no others can be started while waiting for this
559 * one.
560 */
561 BroadcastRecord mPendingBroadcast = null;
562
563 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700564 * The receiver index that is pending, to restart the broadcast if needed.
565 */
566 int mPendingBroadcastRecvIndex;
567
568 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 * Keeps track of all IIntentReceivers that have been registered for
570 * broadcasts. Hash keys are the receiver IBinder, hash value is
571 * a ReceiverList.
572 */
573 final HashMap mRegisteredReceivers = new HashMap();
574
575 /**
576 * Resolver for broadcast intents to registered receivers.
577 * Holds BroadcastFilter (subclass of IntentFilter).
578 */
579 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
580 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
581 @Override
582 protected boolean allowFilterResult(
583 BroadcastFilter filter, List<BroadcastFilter> dest) {
584 IBinder target = filter.receiverList.receiver.asBinder();
585 for (int i=dest.size()-1; i>=0; i--) {
586 if (dest.get(i).receiverList.receiver.asBinder() == target) {
587 return false;
588 }
589 }
590 return true;
591 }
592 };
593
594 /**
595 * State of all active sticky broadcasts. Keys are the action of the
596 * sticky Intent, values are an ArrayList of all broadcasted intents with
597 * that action (which should usually be one).
598 */
599 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
600 new HashMap<String, ArrayList<Intent>>();
601
602 /**
603 * All currently running services.
604 */
605 final HashMap<ComponentName, ServiceRecord> mServices =
606 new HashMap<ComponentName, ServiceRecord>();
607
608 /**
609 * All currently running services indexed by the Intent used to start them.
610 */
611 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
612 new HashMap<Intent.FilterComparison, ServiceRecord>();
613
614 /**
615 * All currently bound service connections. Keys are the IBinder of
616 * the client's IServiceConnection.
617 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700618 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
619 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620
621 /**
622 * List of services that we have been asked to start,
623 * but haven't yet been able to. It is used to hold start requests
624 * while waiting for their corresponding application thread to get
625 * going.
626 */
627 final ArrayList<ServiceRecord> mPendingServices
628 = new ArrayList<ServiceRecord>();
629
630 /**
631 * List of services that are scheduled to restart following a crash.
632 */
633 final ArrayList<ServiceRecord> mRestartingServices
634 = new ArrayList<ServiceRecord>();
635
636 /**
637 * List of services that are in the process of being stopped.
638 */
639 final ArrayList<ServiceRecord> mStoppingServices
640 = new ArrayList<ServiceRecord>();
641
642 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700643 * Backup/restore process management
644 */
645 String mBackupAppName = null;
646 BackupRecord mBackupTarget = null;
647
648 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 * List of PendingThumbnailsRecord objects of clients who are still
650 * waiting to receive all of the thumbnails for a task.
651 */
652 final ArrayList mPendingThumbnails = new ArrayList();
653
654 /**
655 * List of HistoryRecord objects that have been finished and must
656 * still report back to a pending thumbnail receiver.
657 */
658 final ArrayList mCancelledThumbnails = new ArrayList();
659
660 /**
661 * All of the currently running global content providers. Keys are a
662 * string containing the provider name and values are a
663 * ContentProviderRecord object containing the data about it. Note
664 * that a single provider may be published under multiple names, so
665 * there may be multiple entries here for a single one in mProvidersByClass.
666 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700667 final HashMap<String, ContentProviderRecord> mProvidersByName
668 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669
670 /**
671 * All of the currently running global content providers. Keys are a
672 * string containing the provider's implementation class and values are a
673 * ContentProviderRecord object containing the data about it.
674 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700675 final HashMap<String, ContentProviderRecord> mProvidersByClass
676 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677
678 /**
679 * List of content providers who have clients waiting for them. The
680 * application is currently being launched and the provider will be
681 * removed from this list once it is published.
682 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700683 final ArrayList<ContentProviderRecord> mLaunchingProviders
684 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685
686 /**
687 * Global set of specific Uri permissions that have been granted.
688 */
689 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
690 = new SparseArray<HashMap<Uri, UriPermission>>();
691
692 /**
693 * Thread-local storage used to carry caller permissions over through
694 * indirect content-provider access.
695 * @see #ActivityManagerService.openContentUri()
696 */
697 private class Identity {
698 public int pid;
699 public int uid;
700
701 Identity(int _pid, int _uid) {
702 pid = _pid;
703 uid = _uid;
704 }
705 }
706 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
707
708 /**
709 * All information we have collected about the runtime performance of
710 * any user id that can impact battery performance.
711 */
712 final BatteryStatsService mBatteryStatsService;
713
714 /**
715 * information about component usage
716 */
717 final UsageStatsService mUsageStatsService;
718
719 /**
720 * Current configuration information. HistoryRecord objects are given
721 * a reference to this object to indicate which configuration they are
722 * currently running in, so this object must be kept immutable.
723 */
724 Configuration mConfiguration = new Configuration();
725
726 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800727 * Current sequencing integer of the configuration, for skipping old
728 * configurations.
729 */
730 int mConfigurationSeq = 0;
731
732 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700733 * Hardware-reported OpenGLES version.
734 */
735 final int GL_ES_VERSION;
736
737 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 * List of initialization arguments to pass to all processes when binding applications to them.
739 * For example, references to the commonly used services.
740 */
741 HashMap<String, IBinder> mAppBindArgs;
742
743 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700744 * Temporary to avoid allocations. Protected by main lock.
745 */
746 final StringBuilder mStringBuilder = new StringBuilder(256);
747
748 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 * Used to control how we initialize the service.
750 */
751 boolean mStartRunning = false;
752 ComponentName mTopComponent;
753 String mTopAction;
754 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700755 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 boolean mSystemReady = false;
757 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700758 boolean mWaitingUpdate = false;
759 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700760 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700761 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762
763 Context mContext;
764
765 int mFactoryTest;
766
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700767 boolean mCheckedForSetup;
768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700770 * The time at which we will allow normal application switches again,
771 * after a call to {@link #stopAppSwitches()}.
772 */
773 long mAppSwitchesAllowedTime;
774
775 /**
776 * This is set to true after the first switch after mAppSwitchesAllowedTime
777 * is set; any switches after that will clear the time.
778 */
779 boolean mDidAppSwitch;
780
781 /**
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700782 * Last time (in realtime) at which we checked for wake lock usage.
783 */
784 long mLastWakeLockCheckTime;
785
786 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 * Set while we are wanting to sleep, to prevent any
788 * activities from being started/resumed.
789 */
790 boolean mSleeping = false;
791
792 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700793 * Set if we are shutting down the system, similar to sleeping.
794 */
795 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796
797 /**
798 * Task identifier that activities are currently being started
799 * in. Incremented each time a new task is created.
800 * todo: Replace this with a TokenSpace class that generates non-repeating
801 * integers that won't wrap.
802 */
803 int mCurTask = 1;
804
805 /**
806 * Current sequence id for oom_adj computation traversal.
807 */
808 int mAdjSeq = 0;
809
810 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700811 * Current sequence id for process LRU updating.
812 */
813 int mLruSeq = 0;
814
815 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
817 * is set, indicating the user wants processes started in such a way
818 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
819 * running in each process (thus no pre-initialized process, etc).
820 */
821 boolean mSimpleProcessManagement = false;
822
823 /**
824 * System monitoring: number of processes that died since the last
825 * N procs were started.
826 */
827 int[] mProcDeaths = new int[20];
828
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700829 /**
830 * This is set if we had to do a delayed dexopt of an app before launching
831 * it, to increasing the ANR timeouts in that case.
832 */
833 boolean mDidDexOpt;
834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 String mDebugApp = null;
836 boolean mWaitForDebugger = false;
837 boolean mDebugTransient = false;
838 String mOrigDebugApp = null;
839 boolean mOrigWaitForDebugger = false;
840 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700841 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700843 final RemoteCallbackList<IActivityWatcher> mWatchers
844 = new RemoteCallbackList<IActivityWatcher>();
845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 /**
847 * Callback of last caller to {@link #requestPss}.
848 */
849 Runnable mRequestPssCallback;
850
851 /**
852 * Remaining processes for which we are waiting results from the last
853 * call to {@link #requestPss}.
854 */
855 final ArrayList<ProcessRecord> mRequestPssList
856 = new ArrayList<ProcessRecord>();
857
858 /**
859 * Runtime statistics collection thread. This object's lock is used to
860 * protect all related state.
861 */
862 final Thread mProcessStatsThread;
863
864 /**
865 * Used to collect process stats when showing not responding dialog.
866 * Protected by mProcessStatsThread.
867 */
868 final ProcessStats mProcessStats = new ProcessStats(
869 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700870 final AtomicLong mLastCpuTime = new AtomicLong(0);
871 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 long mLastWriteTime = 0;
874
875 /**
876 * Set to true after the system has finished booting.
877 */
878 boolean mBooted = false;
879
880 int mProcessLimit = 0;
881
882 WindowManagerService mWindowManager;
883
884 static ActivityManagerService mSelf;
885 static ActivityThread mSystemThread;
886
887 private final class AppDeathRecipient implements IBinder.DeathRecipient {
888 final ProcessRecord mApp;
889 final int mPid;
890 final IApplicationThread mAppThread;
891
892 AppDeathRecipient(ProcessRecord app, int pid,
893 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800894 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 TAG, "New death recipient " + this
896 + " for thread " + thread.asBinder());
897 mApp = app;
898 mPid = pid;
899 mAppThread = thread;
900 }
901
902 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800903 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 TAG, "Death received in " + this
905 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 synchronized(ActivityManagerService.this) {
907 appDiedLocked(mApp, mPid, mAppThread);
908 }
909 }
910 }
911
912 static final int SHOW_ERROR_MSG = 1;
913 static final int SHOW_NOT_RESPONDING_MSG = 2;
914 static final int SHOW_FACTORY_ERROR_MSG = 3;
915 static final int UPDATE_CONFIGURATION_MSG = 4;
916 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
917 static final int WAIT_FOR_DEBUGGER_MSG = 6;
918 static final int BROADCAST_INTENT_MSG = 7;
919 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 static final int SERVICE_TIMEOUT_MSG = 12;
921 static final int UPDATE_TIME_ZONE = 13;
922 static final int SHOW_UID_ERROR_MSG = 14;
923 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700925 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700926 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800927 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700928 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
929 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700930 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700931 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932
933 AlertDialog mUidAlert;
934
935 final Handler mHandler = new Handler() {
936 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800937 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 //}
939
940 public void handleMessage(Message msg) {
941 switch (msg.what) {
942 case SHOW_ERROR_MSG: {
943 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 synchronized (ActivityManagerService.this) {
945 ProcessRecord proc = (ProcessRecord)data.get("app");
946 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800947 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 return;
949 }
950 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700951 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800952 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 d.show();
954 proc.crashDialog = d;
955 } else {
956 // The device is asleep, so just pretend that the user
957 // saw a crash dialog and hit "force quit".
958 res.set(0);
959 }
960 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700961
962 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 } break;
964 case SHOW_NOT_RESPONDING_MSG: {
965 synchronized (ActivityManagerService.this) {
966 HashMap data = (HashMap) msg.obj;
967 ProcessRecord proc = (ProcessRecord)data.get("app");
968 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800969 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 return;
971 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800972
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700973 Intent intent = new Intent("android.intent.action.ANR");
974 if (!mProcessesReady) {
975 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
976 }
977 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -0800978 null, null, 0, null, null, null,
979 false, false, MY_PID, Process.SYSTEM_UID);
980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700982 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 d.show();
984 proc.anrDialog = d;
985 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700986
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700987 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700989 case SHOW_STRICT_MODE_VIOLATION_MSG: {
990 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
991 synchronized (ActivityManagerService.this) {
992 ProcessRecord proc = (ProcessRecord) data.get("app");
993 if (proc == null) {
994 Slog.e(TAG, "App not found when showing strict mode dialog.");
995 break;
996 }
997 if (proc.crashDialog != null) {
998 Slog.e(TAG, "App already has strict mode dialog: " + proc);
999 return;
1000 }
1001 AppErrorResult res = (AppErrorResult) data.get("result");
1002 if (!mSleeping && !mShuttingDown) {
1003 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1004 d.show();
1005 proc.crashDialog = d;
1006 } else {
1007 // The device is asleep, so just pretend that the user
1008 // saw a crash dialog and hit "force quit".
1009 res.set(0);
1010 }
1011 }
1012 ensureBootCompleted();
1013 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 case SHOW_FACTORY_ERROR_MSG: {
1015 Dialog d = new FactoryErrorDialog(
1016 mContext, msg.getData().getCharSequence("msg"));
1017 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001018 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 } break;
1020 case UPDATE_CONFIGURATION_MSG: {
1021 final ContentResolver resolver = mContext.getContentResolver();
1022 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1023 } break;
1024 case GC_BACKGROUND_PROCESSES_MSG: {
1025 synchronized (ActivityManagerService.this) {
1026 performAppGcsIfAppropriateLocked();
1027 }
1028 } break;
1029 case WAIT_FOR_DEBUGGER_MSG: {
1030 synchronized (ActivityManagerService.this) {
1031 ProcessRecord app = (ProcessRecord)msg.obj;
1032 if (msg.arg1 != 0) {
1033 if (!app.waitedForDebugger) {
1034 Dialog d = new AppWaitingForDebuggerDialog(
1035 ActivityManagerService.this,
1036 mContext, app);
1037 app.waitDialog = d;
1038 app.waitedForDebugger = true;
1039 d.show();
1040 }
1041 } else {
1042 if (app.waitDialog != null) {
1043 app.waitDialog.dismiss();
1044 app.waitDialog = null;
1045 }
1046 }
1047 }
1048 } break;
1049 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001050 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 TAG, "Received BROADCAST_INTENT_MSG");
1052 processNextBroadcast(true);
1053 } break;
1054 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001055 if (mDidDexOpt) {
1056 mDidDexOpt = false;
1057 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1058 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1059 return;
1060 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001061 // Only process broadcast timeouts if the system is ready. That way
1062 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1063 // to do heavy lifting for system up
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001064 if (mProcessesReady) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001065 broadcastTimeout();
1066 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001069 if (mDidDexOpt) {
1070 mDidDexOpt = false;
1071 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1072 nmsg.obj = msg.obj;
1073 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1074 return;
1075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 serviceTimeout((ProcessRecord)msg.obj);
1077 } break;
1078 case UPDATE_TIME_ZONE: {
1079 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001080 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1081 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 if (r.thread != null) {
1083 try {
1084 r.thread.updateTimeZone();
1085 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001086 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 }
1088 }
1089 }
1090 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001091 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 case SHOW_UID_ERROR_MSG: {
1093 // XXX This is a temporary dialog, no need to localize.
1094 AlertDialog d = new BaseErrorDialog(mContext);
1095 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1096 d.setCancelable(false);
1097 d.setTitle("System UIDs Inconsistent");
1098 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1099 d.setButton("I'm Feeling Lucky",
1100 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1101 mUidAlert = d;
1102 d.show();
1103 } break;
1104 case IM_FEELING_LUCKY_MSG: {
1105 if (mUidAlert != null) {
1106 mUidAlert.dismiss();
1107 mUidAlert = null;
1108 }
1109 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001111 if (mDidDexOpt) {
1112 mDidDexOpt = false;
1113 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1114 nmsg.obj = msg.obj;
1115 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1116 return;
1117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 ProcessRecord app = (ProcessRecord)msg.obj;
1119 synchronized (ActivityManagerService.this) {
1120 processStartTimedOutLocked(app);
1121 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001122 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001123 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1124 synchronized (ActivityManagerService.this) {
1125 doPendingActivityLaunchesLocked(true);
1126 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001127 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001128 case KILL_APPLICATION_MSG: {
1129 synchronized (ActivityManagerService.this) {
1130 int uid = msg.arg1;
1131 boolean restart = (msg.arg2 == 1);
1132 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001133 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001134 }
1135 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001136 case FINALIZE_PENDING_INTENT_MSG: {
1137 ((PendingIntentRecord)msg.obj).completeFinalize();
1138 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001139 case POST_HEAVY_NOTIFICATION_MSG: {
1140 INotificationManager inm = NotificationManager.getService();
1141 if (inm == null) {
1142 return;
1143 }
1144
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001145 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001146 ProcessRecord process = root.app;
1147 if (process == null) {
1148 return;
1149 }
1150
1151 try {
1152 Context context = mContext.createPackageContext(process.info.packageName, 0);
1153 String text = mContext.getString(R.string.heavy_weight_notification,
1154 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1155 Notification notification = new Notification();
1156 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1157 notification.when = 0;
1158 notification.flags = Notification.FLAG_ONGOING_EVENT;
1159 notification.tickerText = text;
1160 notification.defaults = 0; // please be quiet
1161 notification.sound = null;
1162 notification.vibrate = null;
1163 notification.setLatestEventInfo(context, text,
1164 mContext.getText(R.string.heavy_weight_notification_detail),
1165 PendingIntent.getActivity(mContext, 0, root.intent,
1166 PendingIntent.FLAG_CANCEL_CURRENT));
1167
1168 try {
1169 int[] outId = new int[1];
1170 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1171 notification, outId);
1172 } catch (RuntimeException e) {
1173 Slog.w(ActivityManagerService.TAG,
1174 "Error showing notification for heavy-weight app", e);
1175 } catch (RemoteException e) {
1176 }
1177 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001178 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001179 }
1180 } break;
1181 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1182 INotificationManager inm = NotificationManager.getService();
1183 if (inm == null) {
1184 return;
1185 }
1186 try {
1187 inm.cancelNotification("android",
1188 R.string.heavy_weight_notification);
1189 } catch (RuntimeException e) {
1190 Slog.w(ActivityManagerService.TAG,
1191 "Error canceling notification for service", e);
1192 } catch (RemoteException e) {
1193 }
1194 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001195 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1196 synchronized (ActivityManagerService.this) {
1197 checkExcessiveWakeLocksLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001198 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001199 if (mSleeping) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001200 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1201 sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001202 }
1203 }
1204 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 }
1206 }
1207 };
1208
1209 public static void setSystemProcess() {
1210 try {
1211 ActivityManagerService m = mSelf;
1212
1213 ServiceManager.addService("activity", m);
1214 ServiceManager.addService("meminfo", new MemBinder(m));
1215 if (MONITOR_CPU_USAGE) {
1216 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 ServiceManager.addService("permission", new PermissionController(m));
1219
1220 ApplicationInfo info =
1221 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001222 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001223 mSystemThread.installSystemApplicationInfo(info);
1224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 synchronized (mSelf) {
1226 ProcessRecord app = mSelf.newProcessRecordLocked(
1227 mSystemThread.getApplicationThread(), info,
1228 info.processName);
1229 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001230 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 app.maxAdj = SYSTEM_ADJ;
1232 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1233 synchronized (mSelf.mPidsSelfLocked) {
1234 mSelf.mPidsSelfLocked.put(app.pid, app);
1235 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001236 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 }
1238 } catch (PackageManager.NameNotFoundException e) {
1239 throw new RuntimeException(
1240 "Unable to find android system package", e);
1241 }
1242 }
1243
1244 public void setWindowManager(WindowManagerService wm) {
1245 mWindowManager = wm;
1246 }
1247
1248 public static final Context main(int factoryTest) {
1249 AThread thr = new AThread();
1250 thr.start();
1251
1252 synchronized (thr) {
1253 while (thr.mService == null) {
1254 try {
1255 thr.wait();
1256 } catch (InterruptedException e) {
1257 }
1258 }
1259 }
1260
1261 ActivityManagerService m = thr.mService;
1262 mSelf = m;
1263 ActivityThread at = ActivityThread.systemMain();
1264 mSystemThread = at;
1265 Context context = at.getSystemContext();
1266 m.mContext = context;
1267 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001268 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269
1270 m.mBatteryStatsService.publish(context);
1271 m.mUsageStatsService.publish(context);
1272
1273 synchronized (thr) {
1274 thr.mReady = true;
1275 thr.notifyAll();
1276 }
1277
1278 m.startRunning(null, null, null, null);
1279
1280 return context;
1281 }
1282
1283 public static ActivityManagerService self() {
1284 return mSelf;
1285 }
1286
1287 static class AThread extends Thread {
1288 ActivityManagerService mService;
1289 boolean mReady = false;
1290
1291 public AThread() {
1292 super("ActivityManager");
1293 }
1294
1295 public void run() {
1296 Looper.prepare();
1297
1298 android.os.Process.setThreadPriority(
1299 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001300 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301
1302 ActivityManagerService m = new ActivityManagerService();
1303
1304 synchronized (this) {
1305 mService = m;
1306 notifyAll();
1307 }
1308
1309 synchronized (this) {
1310 while (!mReady) {
1311 try {
1312 wait();
1313 } catch (InterruptedException e) {
1314 }
1315 }
1316 }
1317
1318 Looper.loop();
1319 }
1320 }
1321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001322 static class MemBinder extends Binder {
1323 ActivityManagerService mActivityManagerService;
1324 MemBinder(ActivityManagerService activityManagerService) {
1325 mActivityManagerService = activityManagerService;
1326 }
1327
1328 @Override
1329 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1330 ActivityManagerService service = mActivityManagerService;
1331 ArrayList<ProcessRecord> procs;
1332 synchronized (mActivityManagerService) {
1333 if (args != null && args.length > 0
1334 && args[0].charAt(0) != '-') {
1335 procs = new ArrayList<ProcessRecord>();
1336 int pid = -1;
1337 try {
1338 pid = Integer.parseInt(args[0]);
1339 } catch (NumberFormatException e) {
1340
1341 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001342 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1343 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 if (proc.pid == pid) {
1345 procs.add(proc);
1346 } else if (proc.processName.equals(args[0])) {
1347 procs.add(proc);
1348 }
1349 }
1350 if (procs.size() <= 0) {
1351 pw.println("No process found for: " + args[0]);
1352 return;
1353 }
1354 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001355 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 }
1357 }
1358 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1359 }
1360 }
1361
1362 static class CpuBinder extends Binder {
1363 ActivityManagerService mActivityManagerService;
1364 CpuBinder(ActivityManagerService activityManagerService) {
1365 mActivityManagerService = activityManagerService;
1366 }
1367
1368 @Override
1369 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1370 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001371 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1372 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1373 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 }
1375 }
1376 }
1377
1378 private ActivityManagerService() {
1379 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1380 if (v != null && Integer.getInteger(v) != 0) {
1381 mSimpleProcessManagement = true;
1382 }
1383 v = System.getenv("ANDROID_DEBUG_APP");
1384 if (v != null) {
1385 mSimpleProcessManagement = true;
1386 }
1387
Joe Onorato8a9b2202010-02-26 18:56:32 -08001388 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 File dataDir = Environment.getDataDirectory();
1391 File systemDir = new File(dataDir, "system");
1392 systemDir.mkdirs();
1393 mBatteryStatsService = new BatteryStatsService(new File(
1394 systemDir, "batterystats.bin").toString());
1395 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001396 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001397 mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
1398 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001400 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001401 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402
Jack Palevichb90d28c2009-07-22 15:35:24 -07001403 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1404 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1405
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001406 mConfiguration.setToDefaults();
1407 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 mProcessStats.init();
1409
1410 // Add ourself to the Watchdog monitors.
1411 Watchdog.getInstance().addMonitor(this);
1412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 mProcessStatsThread = new Thread("ProcessStats") {
1414 public void run() {
1415 while (true) {
1416 try {
1417 try {
1418 synchronized(this) {
1419 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001420 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001422 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 // + ", write delay=" + nextWriteDelay);
1424 if (nextWriteDelay < nextCpuDelay) {
1425 nextCpuDelay = nextWriteDelay;
1426 }
1427 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001428 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 this.wait(nextCpuDelay);
1430 }
1431 }
1432 } catch (InterruptedException e) {
1433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 updateCpuStatsNow();
1435 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001436 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 }
1438 }
1439 }
1440 };
1441 mProcessStatsThread.start();
1442 }
1443
1444 @Override
1445 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1446 throws RemoteException {
1447 try {
1448 return super.onTransact(code, data, reply, flags);
1449 } catch (RuntimeException e) {
1450 // The activity manager only throws security exceptions, so let's
1451 // log all others.
1452 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001453 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 }
1455 throw e;
1456 }
1457 }
1458
1459 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001460 final long now = SystemClock.uptimeMillis();
1461 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1462 return;
1463 }
1464 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1465 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 mProcessStatsThread.notify();
1467 }
1468 }
1469 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 void updateCpuStatsNow() {
1472 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001473 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 final long now = SystemClock.uptimeMillis();
1475 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001478 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1479 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 haveNewCpuStats = true;
1481 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001482 //Slog.i(TAG, mProcessStats.printCurrentState());
1483 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 // + mProcessStats.getTotalCpuPercent() + "%");
1485
Joe Onorato8a9b2202010-02-26 18:56:32 -08001486 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 if ("true".equals(SystemProperties.get("events.cpu"))) {
1488 int user = mProcessStats.getLastUserTime();
1489 int system = mProcessStats.getLastSystemTime();
1490 int iowait = mProcessStats.getLastIoWaitTime();
1491 int irq = mProcessStats.getLastIrqTime();
1492 int softIrq = mProcessStats.getLastSoftIrqTime();
1493 int idle = mProcessStats.getLastIdleTime();
1494
1495 int total = user + system + iowait + irq + softIrq + idle;
1496 if (total == 0) total = 1;
1497
Doug Zongker2bec3d42009-12-04 12:52:44 -08001498 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 ((user+system+iowait+irq+softIrq) * 100) / total,
1500 (user * 100) / total,
1501 (system * 100) / total,
1502 (iowait * 100) / total,
1503 (irq * 100) / total,
1504 (softIrq * 100) / total);
1505 }
1506 }
1507
Amith Yamasanie43530a2009-08-21 13:11:37 -07001508 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001509 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001510 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 synchronized(mPidsSelfLocked) {
1512 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001513 if (mOnBattery) {
1514 int perc = bstats.startAddingCpuLocked();
1515 int totalUTime = 0;
1516 int totalSTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 final int N = mProcessStats.countWorkingStats();
1518 for (int i=0; i<N; i++) {
1519 ProcessStats.Stats st
1520 = mProcessStats.getWorkingStats(i);
1521 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001522 int otherUTime = (st.rel_utime*perc)/100;
1523 int otherSTime = (st.rel_stime*perc)/100;
1524 totalUTime += otherUTime;
1525 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 if (pr != null) {
1527 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001528 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1529 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001530 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001531 } else {
1532 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001533 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001534 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001535 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1536 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001537 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 }
1540 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001541 bstats.finishAddingCpuLocked(perc, totalUTime,
1542 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 }
1544 }
1545 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1548 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001549 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 }
1551 }
1552 }
1553 }
1554
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001555 @Override
1556 public void batteryNeedsCpuUpdate() {
1557 updateCpuStatsNow();
1558 }
1559
1560 @Override
1561 public void batteryPowerChanged(boolean onBattery) {
1562 // When plugging in, update the CPU stats first before changing
1563 // the plug state.
1564 updateCpuStatsNow();
1565 synchronized (this) {
1566 synchronized(mPidsSelfLocked) {
1567 mOnBattery = onBattery;
1568 }
1569 }
1570 }
1571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 /**
1573 * Initialize the application bind args. These are passed to each
1574 * process when the bindApplication() IPC is sent to the process. They're
1575 * lazily setup to make sure the services are running when they're asked for.
1576 */
1577 private HashMap<String, IBinder> getCommonServicesLocked() {
1578 if (mAppBindArgs == null) {
1579 mAppBindArgs = new HashMap<String, IBinder>();
1580
1581 // Setup the application init args
1582 mAppBindArgs.put("package", ServiceManager.getService("package"));
1583 mAppBindArgs.put("window", ServiceManager.getService("window"));
1584 mAppBindArgs.put(Context.ALARM_SERVICE,
1585 ServiceManager.getService(Context.ALARM_SERVICE));
1586 }
1587 return mAppBindArgs;
1588 }
1589
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001590 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 if (mFocusedActivity != r) {
1592 mFocusedActivity = r;
1593 mWindowManager.setFocusedApp(r, true);
1594 }
1595 }
1596
Dianne Hackborn906497c2010-05-10 15:57:38 -07001597 private final void updateLruProcessInternalLocked(ProcessRecord app,
1598 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001600 int lrui = mLruProcesses.indexOf(app);
1601 if (lrui >= 0) mLruProcesses.remove(lrui);
1602
1603 int i = mLruProcesses.size()-1;
1604 int skipTop = 0;
1605
Dianne Hackborn906497c2010-05-10 15:57:38 -07001606 app.lruSeq = mLruSeq;
1607
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001608 // compute the new weight for this process.
1609 if (updateActivityTime) {
1610 app.lastActivityTime = SystemClock.uptimeMillis();
1611 }
1612 if (app.activities.size() > 0) {
1613 // If this process has activities, we more strongly want to keep
1614 // it around.
1615 app.lruWeight = app.lastActivityTime;
1616 } else if (app.pubProviders.size() > 0) {
1617 // If this process contains content providers, we want to keep
1618 // it a little more strongly.
1619 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1620 // Also don't let it kick out the first few "real" hidden processes.
1621 skipTop = MIN_HIDDEN_APPS;
1622 } else {
1623 // If this process doesn't have activities, we less strongly
1624 // want to keep it around, and generally want to avoid getting
1625 // in front of any very recently used activities.
1626 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1627 // Also don't let it kick out the first few "real" hidden processes.
1628 skipTop = MIN_HIDDEN_APPS;
1629 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001630
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001631 while (i >= 0) {
1632 ProcessRecord p = mLruProcesses.get(i);
1633 // If this app shouldn't be in front of the first N background
1634 // apps, then skip over that many that are currently hidden.
1635 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1636 skipTop--;
1637 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001638 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001639 mLruProcesses.add(i+1, app);
1640 break;
1641 }
1642 i--;
1643 }
1644 if (i < 0) {
1645 mLruProcesses.add(0, app);
1646 }
1647
Dianne Hackborn906497c2010-05-10 15:57:38 -07001648 // If the app is currently using a content provider or service,
1649 // bump those processes as well.
1650 if (app.connections.size() > 0) {
1651 for (ConnectionRecord cr : app.connections) {
1652 if (cr.binding != null && cr.binding.service != null
1653 && cr.binding.service.app != null
1654 && cr.binding.service.app.lruSeq != mLruSeq) {
1655 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1656 updateActivityTime, i+1);
1657 }
1658 }
1659 }
1660 if (app.conProviders.size() > 0) {
1661 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1662 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1663 updateLruProcessInternalLocked(cpr.app, oomAdj,
1664 updateActivityTime, i+1);
1665 }
1666 }
1667 }
1668
Joe Onorato8a9b2202010-02-26 18:56:32 -08001669 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 if (oomAdj) {
1671 updateOomAdjLocked();
1672 }
1673 }
1674
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001675 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001676 boolean oomAdj, boolean updateActivityTime) {
1677 mLruSeq++;
1678 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1679 }
1680
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001681 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 String processName, int uid) {
1683 if (uid == Process.SYSTEM_UID) {
1684 // The system gets to run in any process. If there are multiple
1685 // processes with the same uid, just pick the first (this
1686 // should never happen).
1687 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1688 processName);
1689 return procs != null ? procs.valueAt(0) : null;
1690 }
1691 ProcessRecord proc = mProcessNames.get(processName, uid);
1692 return proc;
1693 }
1694
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001695 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001696 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001697 try {
1698 if (pm.performDexOpt(packageName)) {
1699 mDidDexOpt = true;
1700 }
1701 } catch (RemoteException e) {
1702 }
1703 }
1704
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001705 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 int transit = mWindowManager.getPendingAppTransition();
1707 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1708 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1709 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1710 }
1711
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001712 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001714 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1716 // We don't have to do anything more if:
1717 // (1) There is an existing application record; and
1718 // (2) The caller doesn't think it is dead, OR there is no thread
1719 // object attached to it so we know it couldn't have crashed; and
1720 // (3) There is a pid assigned to it, so it is either starting or
1721 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001722 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 + " app=" + app + " knownToBeDead=" + knownToBeDead
1724 + " thread=" + (app != null ? app.thread : null)
1725 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001726 if (app != null && app.pid > 0) {
1727 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001728 // We already have the app running, or are waiting for it to
1729 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001730 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001731 return app;
1732 } else {
1733 // An application record is attached to a previous process,
1734 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001735 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001736 handleAppDiedLocked(app, true);
1737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 String hostingNameStr = hostingName != null
1741 ? hostingName.flattenToShortString() : null;
1742
1743 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1744 // If we are in the background, then check to see if this process
1745 // is bad. If so, we will just silently fail.
1746 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001747 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1748 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 return null;
1750 }
1751 } else {
1752 // When the user is explicitly starting a process, then clear its
1753 // crash count so that we won't make it bad until they see at
1754 // least one crash dialog again, and make the process good again
1755 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001756 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1757 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 mProcessCrashTimes.remove(info.processName, info.uid);
1759 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001760 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 info.processName);
1762 mBadProcesses.remove(info.processName, info.uid);
1763 if (app != null) {
1764 app.bad = false;
1765 }
1766 }
1767 }
1768
1769 if (app == null) {
1770 app = newProcessRecordLocked(null, info, processName);
1771 mProcessNames.put(processName, info.uid, app);
1772 } else {
1773 // If this is a new package in the process, add the package to the list
1774 app.addPackage(info.packageName);
1775 }
1776
1777 // If the system is not ready yet, then hold off on starting this
1778 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001779 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001780 && !isAllowedWhileBooting(info)
1781 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 if (!mProcessesOnHold.contains(app)) {
1783 mProcessesOnHold.add(app);
1784 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001785 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 return app;
1787 }
1788
1789 startProcessLocked(app, hostingType, hostingNameStr);
1790 return (app.pid != 0) ? app : null;
1791 }
1792
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001793 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1794 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1795 }
1796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 private final void startProcessLocked(ProcessRecord app,
1798 String hostingType, String hostingNameStr) {
1799 if (app.pid > 0 && app.pid != MY_PID) {
1800 synchronized (mPidsSelfLocked) {
1801 mPidsSelfLocked.remove(app.pid);
1802 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1803 }
1804 app.pid = 0;
1805 }
1806
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001807 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1808 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 mProcessesOnHold.remove(app);
1810
1811 updateCpuStats();
1812
1813 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1814 mProcDeaths[0] = 0;
1815
1816 try {
1817 int uid = app.info.uid;
1818 int[] gids = null;
1819 try {
1820 gids = mContext.getPackageManager().getPackageGids(
1821 app.info.packageName);
1822 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001823 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001824 }
1825 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1826 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1827 && mTopComponent != null
1828 && app.processName.equals(mTopComponent.getPackageName())) {
1829 uid = 0;
1830 }
1831 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1832 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1833 uid = 0;
1834 }
1835 }
1836 int debugFlags = 0;
1837 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1838 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1839 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001840 // Run the app in safe mode if its manifest requests so or the
1841 // system is booted in safe mode.
1842 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1843 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001844 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1847 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1848 }
1849 if ("1".equals(SystemProperties.get("debug.assert"))) {
1850 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1851 }
1852 int pid = Process.start("android.app.ActivityThread",
1853 mSimpleProcessManagement ? app.processName : null, uid, uid,
1854 gids, debugFlags, null);
1855 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1856 synchronized (bs) {
1857 if (bs.isOnBattery()) {
1858 app.batteryStats.incStartsLocked();
1859 }
1860 }
1861
Doug Zongker2bec3d42009-12-04 12:52:44 -08001862 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 app.processName, hostingType,
1864 hostingNameStr != null ? hostingNameStr : "");
1865
1866 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001867 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 }
1869
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001870 StringBuilder buf = mStringBuilder;
1871 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 buf.append("Start proc ");
1873 buf.append(app.processName);
1874 buf.append(" for ");
1875 buf.append(hostingType);
1876 if (hostingNameStr != null) {
1877 buf.append(" ");
1878 buf.append(hostingNameStr);
1879 }
1880 buf.append(": pid=");
1881 buf.append(pid);
1882 buf.append(" uid=");
1883 buf.append(uid);
1884 buf.append(" gids={");
1885 if (gids != null) {
1886 for (int gi=0; gi<gids.length; gi++) {
1887 if (gi != 0) buf.append(", ");
1888 buf.append(gids[gi]);
1889
1890 }
1891 }
1892 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001893 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 if (pid == 0 || pid == MY_PID) {
1895 // Processes are being emulated with threads.
1896 app.pid = MY_PID;
1897 app.removed = false;
1898 mStartingProcesses.add(app);
1899 } else if (pid > 0) {
1900 app.pid = pid;
1901 app.removed = false;
1902 synchronized (mPidsSelfLocked) {
1903 this.mPidsSelfLocked.put(pid, app);
1904 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1905 msg.obj = app;
1906 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1907 }
1908 } else {
1909 app.pid = 0;
1910 RuntimeException e = new RuntimeException(
1911 "Failure starting process " + app.processName
1912 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001913 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 }
1915 } catch (RuntimeException e) {
1916 // XXX do better error recovery.
1917 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001918 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001919 }
1920 }
1921
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001922 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923 if (resumed) {
1924 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1925 } else {
1926 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1927 }
1928 }
1929
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001930 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001931 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1932 && mTopAction == null) {
1933 // We are running in factory test mode, but unable to find
1934 // the factory test app, so just sit around displaying the
1935 // error message and don't try to start anything.
1936 return false;
1937 }
1938 Intent intent = new Intent(
1939 mTopAction,
1940 mTopData != null ? Uri.parse(mTopData) : null);
1941 intent.setComponent(mTopComponent);
1942 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1943 intent.addCategory(Intent.CATEGORY_HOME);
1944 }
1945 ActivityInfo aInfo =
1946 intent.resolveActivityInfo(mContext.getPackageManager(),
1947 STOCK_PM_FLAGS);
1948 if (aInfo != null) {
1949 intent.setComponent(new ComponentName(
1950 aInfo.applicationInfo.packageName, aInfo.name));
1951 // Don't do this if the home app is currently being
1952 // instrumented.
1953 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1954 aInfo.applicationInfo.uid);
1955 if (app == null || app.instrumentationClass == null) {
1956 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001957 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001958 null, null, 0, 0, 0, false, false);
1959 }
1960 }
1961
1962
1963 return true;
1964 }
1965
1966 /**
1967 * Starts the "new version setup screen" if appropriate.
1968 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001969 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001970 // Only do this once per boot.
1971 if (mCheckedForSetup) {
1972 return;
1973 }
1974
1975 // We will show this screen if the current one is a different
1976 // version than the last one shown, and we are not running in
1977 // low-level factory test mode.
1978 final ContentResolver resolver = mContext.getContentResolver();
1979 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1980 Settings.Secure.getInt(resolver,
1981 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1982 mCheckedForSetup = true;
1983
1984 // See if we should be showing the platform update setup UI.
1985 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1986 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1987 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1988
1989 // We don't allow third party apps to replace this.
1990 ResolveInfo ri = null;
1991 for (int i=0; ris != null && i<ris.size(); i++) {
1992 if ((ris.get(i).activityInfo.applicationInfo.flags
1993 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1994 ri = ris.get(i);
1995 break;
1996 }
1997 }
1998
1999 if (ri != null) {
2000 String vers = ri.activityInfo.metaData != null
2001 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2002 : null;
2003 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2004 vers = ri.activityInfo.applicationInfo.metaData.getString(
2005 Intent.METADATA_SETUP_VERSION);
2006 }
2007 String lastVers = Settings.Secure.getString(
2008 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2009 if (vers != null && !vers.equals(lastVers)) {
2010 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2011 intent.setComponent(new ComponentName(
2012 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002013 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002014 null, null, 0, 0, 0, false, false);
2015 }
2016 }
2017 }
2018 }
2019
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002020 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002021 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002022
2023 final int identHash = System.identityHashCode(r);
2024 updateUsageStats(r, true);
2025
2026 int i = mWatchers.beginBroadcast();
2027 while (i > 0) {
2028 i--;
2029 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2030 if (w != null) {
2031 try {
2032 w.activityResuming(identHash);
2033 } catch (RemoteException e) {
2034 }
2035 }
2036 }
2037 mWatchers.finishBroadcast();
2038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002040 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002041 final int N = mPendingActivityLaunches.size();
2042 if (N <= 0) {
2043 return;
2044 }
2045 for (int i=0; i<N; i++) {
2046 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002047 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002048 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2049 doResume && i == (N-1));
2050 }
2051 mPendingActivityLaunches.clear();
2052 }
2053
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002054 public final int startActivity(IApplicationThread caller,
2055 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2056 int grantedMode, IBinder resultTo,
2057 String resultWho, int requestCode, boolean onlyIfNeeded,
2058 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002059 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002060 grantedUriPermissions, grantedMode, resultTo, resultWho,
2061 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002062 }
2063
2064 public final WaitResult startActivityAndWait(IApplicationThread caller,
2065 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2066 int grantedMode, IBinder resultTo,
2067 String resultWho, int requestCode, boolean onlyIfNeeded,
2068 boolean debug) {
2069 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002070 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002071 grantedUriPermissions, grantedMode, resultTo, resultWho,
2072 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002073 return res;
2074 }
2075
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002076 public final int startActivityWithConfig(IApplicationThread caller,
2077 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2078 int grantedMode, IBinder resultTo,
2079 String resultWho, int requestCode, boolean onlyIfNeeded,
2080 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002081 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002082 grantedUriPermissions, grantedMode, resultTo, resultWho,
2083 requestCode, onlyIfNeeded, debug, null, config);
2084 }
2085
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002086 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002087 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002088 IBinder resultTo, String resultWho, int requestCode,
2089 int flagsMask, int flagsValues) {
2090 // Refuse possible leaked file descriptors
2091 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2092 throw new IllegalArgumentException("File descriptors passed in Intent");
2093 }
2094
2095 IIntentSender sender = intent.getTarget();
2096 if (!(sender instanceof PendingIntentRecord)) {
2097 throw new IllegalArgumentException("Bad PendingIntent object");
2098 }
2099
2100 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002101
2102 synchronized (this) {
2103 // If this is coming from the currently resumed activity, it is
2104 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002105 if (mMainStack.mResumedActivity != null
2106 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002107 Binder.getCallingUid()) {
2108 mAppSwitchesAllowedTime = 0;
2109 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002110 }
2111
2112 return pir.sendInner(0, fillInIntent, resolvedType,
2113 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2114 }
2115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 public boolean startNextMatchingActivity(IBinder callingActivity,
2117 Intent intent) {
2118 // Refuse possible leaked file descriptors
2119 if (intent != null && intent.hasFileDescriptors() == true) {
2120 throw new IllegalArgumentException("File descriptors passed in Intent");
2121 }
2122
2123 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002124 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 if (index < 0) {
2126 return false;
2127 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002128 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129 if (r.app == null || r.app.thread == null) {
2130 // The caller is not running... d'oh!
2131 return false;
2132 }
2133 intent = new Intent(intent);
2134 // The caller is not allowed to change the data.
2135 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2136 // And we are resetting to find the next component...
2137 intent.setComponent(null);
2138
2139 ActivityInfo aInfo = null;
2140 try {
2141 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002142 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002144 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145
2146 // Look for the original activity in the list...
2147 final int N = resolves != null ? resolves.size() : 0;
2148 for (int i=0; i<N; i++) {
2149 ResolveInfo rInfo = resolves.get(i);
2150 if (rInfo.activityInfo.packageName.equals(r.packageName)
2151 && rInfo.activityInfo.name.equals(r.info.name)) {
2152 // We found the current one... the next matching is
2153 // after it.
2154 i++;
2155 if (i<N) {
2156 aInfo = resolves.get(i).activityInfo;
2157 }
2158 break;
2159 }
2160 }
2161 } catch (RemoteException e) {
2162 }
2163
2164 if (aInfo == null) {
2165 // Nobody who is next!
2166 return false;
2167 }
2168
2169 intent.setComponent(new ComponentName(
2170 aInfo.applicationInfo.packageName, aInfo.name));
2171 intent.setFlags(intent.getFlags()&~(
2172 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2173 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2174 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2175 Intent.FLAG_ACTIVITY_NEW_TASK));
2176
2177 // Okay now we need to start the new activity, replacing the
2178 // currently running activity. This is a little tricky because
2179 // we want to start the new one as if the current one is finished,
2180 // but not finish the current one first so that there is no flicker.
2181 // And thus...
2182 final boolean wasFinishing = r.finishing;
2183 r.finishing = true;
2184
2185 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002186 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 final String resultWho = r.resultWho;
2188 final int requestCode = r.requestCode;
2189 r.resultTo = null;
2190 if (resultTo != null) {
2191 resultTo.removeResultsLocked(r, resultWho, requestCode);
2192 }
2193
2194 final long origId = Binder.clearCallingIdentity();
2195 // XXX we are not dealing with propagating grantedUriPermissions...
2196 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002197 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002199 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 Binder.restoreCallingIdentity(origId);
2201
2202 r.finishing = wasFinishing;
2203 if (res != START_SUCCESS) {
2204 return false;
2205 }
2206 return true;
2207 }
2208 }
2209
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002210 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 Intent intent, String resolvedType, IBinder resultTo,
2212 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002213
2214 // This is so super not safe, that only the system (or okay root)
2215 // can do it.
2216 final int callingUid = Binder.getCallingUid();
2217 if (callingUid != 0 && callingUid != Process.myUid()) {
2218 throw new SecurityException(
2219 "startActivityInPackage only available to the system");
2220 }
2221
The Android Open Source Project4df24232009-03-05 14:34:35 -08002222 final boolean componentSpecified = intent.getComponent() != null;
2223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 // Don't modify the client's object!
2225 intent = new Intent(intent);
2226
2227 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 ActivityInfo aInfo;
2229 try {
2230 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002231 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002233 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 aInfo = rInfo != null ? rInfo.activityInfo : null;
2235 } catch (RemoteException e) {
2236 aInfo = null;
2237 }
2238
2239 if (aInfo != null) {
2240 // Store the found target back into the intent, because now that
2241 // we have it we never want to do this again. For example, if the
2242 // user navigates back to this point in the history, we should
2243 // always restart the exact same activity.
2244 intent.setComponent(new ComponentName(
2245 aInfo.applicationInfo.packageName, aInfo.name));
2246 }
2247
2248 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002249 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002251 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 }
2253 }
2254
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002255 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 // Remove any existing entries that are the same kind of task.
2257 int N = mRecentTasks.size();
2258 for (int i=0; i<N; i++) {
2259 TaskRecord tr = mRecentTasks.get(i);
2260 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2261 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2262 mRecentTasks.remove(i);
2263 i--;
2264 N--;
2265 if (task.intent == null) {
2266 // If the new recent task we are adding is not fully
2267 // specified, then replace it with the existing recent task.
2268 task = tr;
2269 }
2270 }
2271 }
2272 if (N >= MAX_RECENT_TASKS) {
2273 mRecentTasks.remove(N-1);
2274 }
2275 mRecentTasks.add(0, task);
2276 }
2277
2278 public void setRequestedOrientation(IBinder token,
2279 int requestedOrientation) {
2280 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002281 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 if (index < 0) {
2283 return;
2284 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002285 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286 final long origId = Binder.clearCallingIdentity();
2287 mWindowManager.setAppOrientation(r, requestedOrientation);
2288 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002289 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 r.mayFreezeScreenLocked(r.app) ? r : null);
2291 if (config != null) {
2292 r.frozenBeforeDestroy = true;
2293 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002294 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 }
2296 }
2297 Binder.restoreCallingIdentity(origId);
2298 }
2299 }
2300
2301 public int getRequestedOrientation(IBinder token) {
2302 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002303 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002304 if (index < 0) {
2305 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2306 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002307 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308 return mWindowManager.getAppOrientation(r);
2309 }
2310 }
2311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 /**
2313 * This is the internal entry point for handling Activity.finish().
2314 *
2315 * @param token The Binder token referencing the Activity we want to finish.
2316 * @param resultCode Result code, if any, from this Activity.
2317 * @param resultData Result data (Intent), if any, from this Activity.
2318 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002319 * @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 -08002320 */
2321 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2322 // Refuse possible leaked file descriptors
2323 if (resultData != null && resultData.hasFileDescriptors() == true) {
2324 throw new IllegalArgumentException("File descriptors passed in Intent");
2325 }
2326
2327 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002328 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002330 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 if (next != null) {
2332 // ask watcher if this is allowed
2333 boolean resumeOK = true;
2334 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002335 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002336 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002337 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 }
2339
2340 if (!resumeOK) {
2341 return false;
2342 }
2343 }
2344 }
2345 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002346 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 resultData, "app-request");
2348 Binder.restoreCallingIdentity(origId);
2349 return res;
2350 }
2351 }
2352
Dianne Hackborn860755f2010-06-03 18:47:52 -07002353 public final void finishHeavyWeightApp() {
2354 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2355 != PackageManager.PERMISSION_GRANTED) {
2356 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2357 + Binder.getCallingPid()
2358 + ", uid=" + Binder.getCallingUid()
2359 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2360 Slog.w(TAG, msg);
2361 throw new SecurityException(msg);
2362 }
2363
2364 synchronized(this) {
2365 if (mHeavyWeightProcess == null) {
2366 return;
2367 }
2368
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002369 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002370 mHeavyWeightProcess.activities);
2371 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002372 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002373 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002374 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002375 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002376 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002377 null, "finish-heavy");
2378 }
2379 }
2380 }
2381
2382 mHeavyWeightProcess = null;
2383 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2384 }
2385 }
2386
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002387 public void crashApplication(int uid, int initialPid, String packageName,
2388 String message) {
2389 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2390 != PackageManager.PERMISSION_GRANTED) {
2391 String msg = "Permission Denial: crashApplication() from pid="
2392 + Binder.getCallingPid()
2393 + ", uid=" + Binder.getCallingUid()
2394 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2395 Slog.w(TAG, msg);
2396 throw new SecurityException(msg);
2397 }
2398
2399 synchronized(this) {
2400 ProcessRecord proc = null;
2401
2402 // Figure out which process to kill. We don't trust that initialPid
2403 // still has any relation to current pids, so must scan through the
2404 // list.
2405 synchronized (mPidsSelfLocked) {
2406 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2407 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2408 if (p.info.uid != uid) {
2409 continue;
2410 }
2411 if (p.pid == initialPid) {
2412 proc = p;
2413 break;
2414 }
2415 for (String str : p.pkgList) {
2416 if (str.equals(packageName)) {
2417 proc = p;
2418 }
2419 }
2420 }
2421 }
2422
2423 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002424 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002425 + " initialPid=" + initialPid
2426 + " packageName=" + packageName);
2427 return;
2428 }
2429
2430 if (proc.thread != null) {
2431 long ident = Binder.clearCallingIdentity();
2432 try {
2433 proc.thread.scheduleCrash(message);
2434 } catch (RemoteException e) {
2435 }
2436 Binder.restoreCallingIdentity(ident);
2437 }
2438 }
2439 }
2440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002441 public final void finishSubActivity(IBinder token, String resultWho,
2442 int requestCode) {
2443 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002444 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 if (index < 0) {
2446 return;
2447 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002448 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002449
2450 final long origId = Binder.clearCallingIdentity();
2451
2452 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002453 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2454 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002455 if (r.resultTo == self && r.requestCode == requestCode) {
2456 if ((r.resultWho == null && resultWho == null) ||
2457 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002458 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002459 Activity.RESULT_CANCELED, null, "request-sub");
2460 }
2461 }
2462 }
2463
2464 Binder.restoreCallingIdentity(origId);
2465 }
2466 }
2467
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002468 public boolean willActivityBeVisible(IBinder token) {
2469 synchronized(this) {
2470 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002471 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2472 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002473 if (r == token) {
2474 return true;
2475 }
2476 if (r.fullscreen && !r.finishing) {
2477 return false;
2478 }
2479 }
2480 return true;
2481 }
2482 }
2483
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002484 public void overridePendingTransition(IBinder token, String packageName,
2485 int enterAnim, int exitAnim) {
2486 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002487 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002488 if (index < 0) {
2489 return;
2490 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002491 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002492
2493 final long origId = Binder.clearCallingIdentity();
2494
2495 if (self.state == ActivityState.RESUMED
2496 || self.state == ActivityState.PAUSING) {
2497 mWindowManager.overridePendingAppTransition(packageName,
2498 enterAnim, exitAnim);
2499 }
2500
2501 Binder.restoreCallingIdentity(origId);
2502 }
2503 }
2504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 * Main function for removing an existing process from the activity manager
2507 * as a result of that process going away. Clears out all connections
2508 * to the process.
2509 */
2510 private final void handleAppDiedLocked(ProcessRecord app,
2511 boolean restarting) {
2512 cleanUpApplicationRecordLocked(app, restarting, -1);
2513 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002514 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 }
2516
2517 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2519 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2520 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002522 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2523 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 }
2525
2526 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002527 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528
2529 boolean atTop = true;
2530 boolean hasVisibleActivities = false;
2531
2532 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002533 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002534 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 TAG, "Removing app " + app + " from history with " + i + " entries");
2536 while (i > 0) {
2537 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002538 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002539 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2541 if (r.app == app) {
2542 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002543 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 TAG, "Removing this entry! frozen=" + r.haveState
2545 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002546 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547
2548 r.inHistory = false;
2549 mWindowManager.removeAppToken(r);
2550 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002551 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002553 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554
2555 } else {
2556 // We have the current state for this activity, so
2557 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002558 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002559 TAG, "Keeping entry, setting app to null");
2560 if (r.visible) {
2561 hasVisibleActivities = true;
2562 }
2563 r.app = null;
2564 r.nowVisible = false;
2565 if (!r.haveState) {
2566 r.icicle = null;
2567 }
2568 }
2569
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002570 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 r.state = ActivityState.STOPPED;
2572 }
2573 atTop = false;
2574 }
2575
2576 app.activities.clear();
2577
2578 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002579 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 + " running instrumentation " + app.instrumentationClass);
2581 Bundle info = new Bundle();
2582 info.putString("shortMsg", "Process crashed.");
2583 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2584 }
2585
2586 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002587 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 // If there was nothing to resume, and we are not already
2589 // restarting this process, but there is a visible activity that
2590 // is hosted by the process... then make sure all visible
2591 // activities are running, taking care of restarting this
2592 // process.
2593 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002594 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 }
2596 }
2597 }
2598 }
2599
2600 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2601 IBinder threadBinder = thread.asBinder();
2602
2603 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002604 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2605 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002606 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2607 return i;
2608 }
2609 }
2610 return -1;
2611 }
2612
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002613 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614 IApplicationThread thread) {
2615 if (thread == null) {
2616 return null;
2617 }
2618
2619 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002620 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 }
2622
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002623 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 IApplicationThread thread) {
2625
2626 mProcDeaths[0]++;
2627
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002628 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2629 synchronized (stats) {
2630 stats.noteProcessDiedLocked(app.info.uid, pid);
2631 }
2632
Magnus Edlund7bb25812010-02-24 15:45:06 +01002633 // Clean up already done if the process has been re-started.
2634 if (app.pid == pid && app.thread != null &&
2635 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002636 if (!app.killedBackground) {
2637 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2638 + ") has died.");
2639 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002640 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002641 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 TAG, "Dying app: " + app + ", pid: " + pid
2643 + ", thread: " + thread.asBinder());
2644 boolean doLowMem = app.instrumentationClass == null;
2645 handleAppDiedLocked(app, false);
2646
2647 if (doLowMem) {
2648 // If there are no longer any background processes running,
2649 // and the app that died was not running instrumentation,
2650 // then tell everyone we are now low on memory.
2651 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002652 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2653 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2655 haveBg = true;
2656 break;
2657 }
2658 }
2659
2660 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002661 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002662 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002663 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002664 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2665 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002666 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002667 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2668 // The low memory report is overriding any current
2669 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002670 // heavy/important/visible/foreground processes first.
2671 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002672 rec.lastRequestedGc = 0;
2673 } else {
2674 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002675 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002676 rec.reportLowMemory = true;
2677 rec.lastLowMemory = now;
2678 mProcessesToGc.remove(rec);
2679 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 }
2681 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002682 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 }
2684 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002685 } else if (app.pid != pid) {
2686 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002687 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002688 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002689 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002690 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002691 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 + thread.asBinder());
2693 }
2694 }
2695
Dan Egnor42471dd2010-01-07 17:25:22 -08002696 /**
2697 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002698 * @param clearTraces causes the dump file to be erased prior to the new
2699 * traces being written, if true; when false, the new traces will be
2700 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002701 * @param firstPids of dalvik VM processes to dump stack traces for first
2702 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002703 * @return file containing stack traces, or null if no dump file is configured
2704 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002705 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2706 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002707 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2708 if (tracesPath == null || tracesPath.length() == 0) {
2709 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002711
2712 File tracesFile = new File(tracesPath);
2713 try {
2714 File tracesDir = tracesFile.getParentFile();
2715 if (!tracesDir.exists()) tracesFile.mkdirs();
2716 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2717
Christopher Tate6ee412d2010-05-28 12:01:56 -07002718 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002719 tracesFile.createNewFile();
2720 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2721 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002722 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002723 return null;
2724 }
2725
2726 // Use a FileObserver to detect when traces finish writing.
2727 // The order of traces is considered important to maintain for legibility.
2728 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2729 public synchronized void onEvent(int event, String path) { notify(); }
2730 };
2731
2732 try {
2733 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002734
2735 // First collect all of the stacks of the most important pids.
2736 try {
2737 int num = firstPids.size();
2738 for (int i = 0; i < num; i++) {
2739 synchronized (observer) {
2740 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2741 observer.wait(200); // Wait for write-close, give up after 200msec
2742 }
2743 }
2744 } catch (InterruptedException e) {
2745 Log.wtf(TAG, e);
2746 }
2747
2748 // Next measure CPU usage.
2749 if (processStats != null) {
2750 processStats.init();
2751 System.gc();
2752 processStats.update();
2753 try {
2754 synchronized (processStats) {
2755 processStats.wait(500); // measure over 1/2 second.
2756 }
2757 } catch (InterruptedException e) {
2758 }
2759 processStats.update();
2760
2761 // We'll take the stack crawls of just the top apps using CPU.
2762 final int N = processStats.countWorkingStats();
2763 int numProcs = 0;
2764 for (int i=0; i<N && numProcs<5; i++) {
2765 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2766 if (lastPids.indexOfKey(stats.pid) >= 0) {
2767 numProcs++;
2768 try {
2769 synchronized (observer) {
2770 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2771 observer.wait(200); // Wait for write-close, give up after 200msec
2772 }
2773 } catch (InterruptedException e) {
2774 Log.wtf(TAG, e);
2775 }
2776
2777 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002778 }
2779 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002780
2781 return tracesFile;
2782
Dan Egnor42471dd2010-01-07 17:25:22 -08002783 } finally {
2784 observer.stopWatching();
2785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 }
2787
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002788 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2789 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002790 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2791 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2792
2793 long anrTime = SystemClock.uptimeMillis();
2794 if (MONITOR_CPU_USAGE) {
2795 updateCpuStatsNow();
2796 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002797
2798 synchronized (this) {
2799 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2800 if (mShuttingDown) {
2801 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2802 return;
2803 } else if (app.notResponding) {
2804 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2805 return;
2806 } else if (app.crashing) {
2807 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2808 return;
2809 }
2810
2811 // In case we come through here for the same app before completing
2812 // this one, mark as anring now so we will bail out.
2813 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002814
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002815 // Log the ANR to the event log.
2816 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2817 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002818
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002819 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002820 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002821
2822 int parentPid = app.pid;
2823 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002824 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002825
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002826 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002827
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002828 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2829 ProcessRecord r = mLruProcesses.get(i);
2830 if (r != null && r.thread != null) {
2831 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002832 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2833 if (r.persistent) {
2834 firstPids.add(pid);
2835 } else {
2836 lastPids.put(pid, Boolean.TRUE);
2837 }
2838 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002839 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002840 }
2841 }
2842
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002843 final ProcessStats processStats = new ProcessStats(true);
2844
2845 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002846
2847 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002848 StringBuilder info = mStringBuilder;
2849 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002850 info.append("ANR in ").append(app.processName);
2851 if (activity != null && activity.shortComponentName != null) {
2852 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002853 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002854 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002856 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002857 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002858 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002859 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002861
Dan Egnor42471dd2010-01-07 17:25:22 -08002862 String cpuInfo = null;
2863 if (MONITOR_CPU_USAGE) {
2864 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002865 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002866 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002867 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002868 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002869 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002870 }
2871
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002872 info.append(processStats.printCurrentState(anrTime));
2873
Joe Onorato8a9b2202010-02-26 18:56:32 -08002874 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002875 if (tracesFile == null) {
2876 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2877 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2878 }
2879
2880 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2881
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002882 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002884 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2885 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002887 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2888 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002889 }
2890 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002891 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 }
2893 }
2894
Dan Egnor42471dd2010-01-07 17:25:22 -08002895 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2896 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2897 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002898
2899 synchronized (this) {
2900 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2901 Process.killProcess(app.pid);
2902 return;
2903 }
2904
2905 // Set the app's notResponding state, and look up the errorReportReceiver
2906 makeAppNotRespondingLocked(app,
2907 activity != null ? activity.shortComponentName : null,
2908 annotation != null ? "ANR " + annotation : "ANR",
2909 info.toString());
2910
2911 // Bring up the infamous App Not Responding dialog
2912 Message msg = Message.obtain();
2913 HashMap map = new HashMap();
2914 msg.what = SHOW_NOT_RESPONDING_MSG;
2915 msg.obj = map;
2916 map.put("app", app);
2917 if (activity != null) {
2918 map.put("activity", activity);
2919 }
2920
2921 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 }
2924
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002925 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2926 if (!mLaunchWarningShown) {
2927 mLaunchWarningShown = true;
2928 mHandler.post(new Runnable() {
2929 @Override
2930 public void run() {
2931 synchronized (ActivityManagerService.this) {
2932 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2933 d.show();
2934 mHandler.postDelayed(new Runnable() {
2935 @Override
2936 public void run() {
2937 synchronized (ActivityManagerService.this) {
2938 d.dismiss();
2939 mLaunchWarningShown = false;
2940 }
2941 }
2942 }, 4000);
2943 }
2944 }
2945 });
2946 }
2947 }
2948
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002949 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 app.persistentActivities--;
2951 if (app.persistentActivities > 0) {
2952 // Still more of 'em...
2953 return;
2954 }
2955 if (app.persistent) {
2956 // Ah, but the application itself is persistent. Whatever!
2957 return;
2958 }
2959
2960 // App is no longer persistent... make sure it and the ones
2961 // following it in the LRU list have the correc oom_adj.
2962 updateOomAdjLocked();
2963 }
2964
2965 public void setPersistent(IBinder token, boolean isPersistent) {
2966 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2967 != PackageManager.PERMISSION_GRANTED) {
2968 String msg = "Permission Denial: setPersistent() from pid="
2969 + Binder.getCallingPid()
2970 + ", uid=" + Binder.getCallingUid()
2971 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002972 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 throw new SecurityException(msg);
2974 }
2975
2976 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002977 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 if (index < 0) {
2979 return;
2980 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002981 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002982 ProcessRecord app = r.app;
2983
Joe Onorato8a9b2202010-02-26 18:56:32 -08002984 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 TAG, "Setting persistence " + isPersistent + ": " + r);
2986
2987 if (isPersistent) {
2988 if (r.persistent) {
2989 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002990 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 return;
2992 }
2993 r.persistent = true;
2994 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002995 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 if (app.persistentActivities > 1) {
2997 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002998 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002999 return;
3000 }
3001 if (app.persistent) {
3002 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003003 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003004 return;
3005 }
3006
3007 // App is now persistent... make sure it and the ones
3008 // following it now have the correct oom_adj.
3009 final long origId = Binder.clearCallingIdentity();
3010 updateOomAdjLocked();
3011 Binder.restoreCallingIdentity(origId);
3012
3013 } else {
3014 if (!r.persistent) {
3015 // Okay okay, I heard you already!
3016 return;
3017 }
3018 r.persistent = false;
3019 final long origId = Binder.clearCallingIdentity();
3020 decPersistentCountLocked(app);
3021 Binder.restoreCallingIdentity(origId);
3022
3023 }
3024 }
3025 }
3026
3027 public boolean clearApplicationUserData(final String packageName,
3028 final IPackageDataObserver observer) {
3029 int uid = Binder.getCallingUid();
3030 int pid = Binder.getCallingPid();
3031 long callingId = Binder.clearCallingIdentity();
3032 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003033 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 int pkgUid = -1;
3035 synchronized(this) {
3036 try {
3037 pkgUid = pm.getPackageUid(packageName);
3038 } catch (RemoteException e) {
3039 }
3040 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003041 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003042 return false;
3043 }
3044 if (uid == pkgUid || checkComponentPermission(
3045 android.Manifest.permission.CLEAR_APP_USER_DATA,
3046 pid, uid, -1)
3047 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003048 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 } else {
3050 throw new SecurityException(pid+" does not have permission:"+
3051 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3052 "for process:"+packageName);
3053 }
3054 }
3055
3056 try {
3057 //clear application user data
3058 pm.clearApplicationUserData(packageName, observer);
3059 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3060 Uri.fromParts("package", packageName, null));
3061 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003062 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3063 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 } catch (RemoteException e) {
3065 }
3066 } finally {
3067 Binder.restoreCallingIdentity(callingId);
3068 }
3069 return true;
3070 }
3071
Dianne Hackborn03abb812010-01-04 18:43:19 -08003072 public void killBackgroundProcesses(final String packageName) {
3073 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3074 != PackageManager.PERMISSION_GRANTED &&
3075 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3076 != PackageManager.PERMISSION_GRANTED) {
3077 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 + Binder.getCallingPid()
3079 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003080 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003081 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 throw new SecurityException(msg);
3083 }
3084
3085 long callingId = Binder.clearCallingIdentity();
3086 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003087 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003088 int pkgUid = -1;
3089 synchronized(this) {
3090 try {
3091 pkgUid = pm.getPackageUid(packageName);
3092 } catch (RemoteException e) {
3093 }
3094 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003095 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 return;
3097 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003098 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003099 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003100 }
3101 } finally {
3102 Binder.restoreCallingIdentity(callingId);
3103 }
3104 }
3105
3106 public void forceStopPackage(final String packageName) {
3107 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3108 != PackageManager.PERMISSION_GRANTED) {
3109 String msg = "Permission Denial: forceStopPackage() from pid="
3110 + Binder.getCallingPid()
3111 + ", uid=" + Binder.getCallingUid()
3112 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003113 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003114 throw new SecurityException(msg);
3115 }
3116
3117 long callingId = Binder.clearCallingIdentity();
3118 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003119 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003120 int pkgUid = -1;
3121 synchronized(this) {
3122 try {
3123 pkgUid = pm.getPackageUid(packageName);
3124 } catch (RemoteException e) {
3125 }
3126 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003127 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003128 return;
3129 }
3130 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003131 }
3132 } finally {
3133 Binder.restoreCallingIdentity(callingId);
3134 }
3135 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003136
3137 /*
3138 * The pkg name and uid have to be specified.
3139 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3140 */
3141 public void killApplicationWithUid(String pkg, int uid) {
3142 if (pkg == null) {
3143 return;
3144 }
3145 // Make sure the uid is valid.
3146 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003147 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003148 return;
3149 }
3150 int callerUid = Binder.getCallingUid();
3151 // Only the system server can kill an application
3152 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003153 // Post an aysnc message to kill the application
3154 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3155 msg.arg1 = uid;
3156 msg.arg2 = 0;
3157 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003158 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003159 } else {
3160 throw new SecurityException(callerUid + " cannot kill pkg: " +
3161 pkg);
3162 }
3163 }
3164
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003165 public void closeSystemDialogs(String reason) {
3166 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003167 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003168 if (reason != null) {
3169 intent.putExtra("reason", reason);
3170 }
3171
3172 final int uid = Binder.getCallingUid();
3173 final long origId = Binder.clearCallingIdentity();
3174 synchronized (this) {
3175 int i = mWatchers.beginBroadcast();
3176 while (i > 0) {
3177 i--;
3178 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3179 if (w != null) {
3180 try {
3181 w.closingSystemDialogs(reason);
3182 } catch (RemoteException e) {
3183 }
3184 }
3185 }
3186 mWatchers.finishBroadcast();
3187
Dianne Hackbornffa42482009-09-23 22:20:11 -07003188 mWindowManager.closeSystemDialogs(reason);
3189
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003190 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3191 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003192 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003193 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003194 Activity.RESULT_CANCELED, null, "close-sys");
3195 }
3196 }
3197
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003198 broadcastIntentLocked(null, null, intent, null,
3199 null, 0, null, null, null, false, false, -1, uid);
3200 }
3201 Binder.restoreCallingIdentity(origId);
3202 }
3203
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003204 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003205 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003206 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3207 for (int i=pids.length-1; i>=0; i--) {
3208 infos[i] = new Debug.MemoryInfo();
3209 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003210 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003211 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003212 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003213
3214 public void killApplicationProcess(String processName, int uid) {
3215 if (processName == null) {
3216 return;
3217 }
3218
3219 int callerUid = Binder.getCallingUid();
3220 // Only the system server can kill an application
3221 if (callerUid == Process.SYSTEM_UID) {
3222 synchronized (this) {
3223 ProcessRecord app = getProcessRecordLocked(processName, uid);
3224 if (app != null) {
3225 try {
3226 app.thread.scheduleSuicide();
3227 } catch (RemoteException e) {
3228 // If the other end already died, then our work here is done.
3229 }
3230 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003231 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003232 + processName + " / " + uid);
3233 }
3234 }
3235 } else {
3236 throw new SecurityException(callerUid + " cannot kill app process: " +
3237 processName);
3238 }
3239 }
3240
Dianne Hackborn03abb812010-01-04 18:43:19 -08003241 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003242 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003243 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3244 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003245 if (!mProcessesReady) {
3246 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 intent.putExtra(Intent.EXTRA_UID, uid);
3249 broadcastIntentLocked(null, null, intent,
3250 null, null, 0, null, null, null,
3251 false, false, MY_PID, Process.SYSTEM_UID);
3252 }
3253
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003254 private final boolean killPackageProcessesLocked(String packageName, int uid,
3255 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003256 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003257
Dianne Hackborn03abb812010-01-04 18:43:19 -08003258 // Remove all processes this package may have touched: all with the
3259 // same UID (except for the system or root user), and all whose name
3260 // matches the package name.
3261 final String procNamePrefix = packageName + ":";
3262 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3263 final int NA = apps.size();
3264 for (int ia=0; ia<NA; ia++) {
3265 ProcessRecord app = apps.valueAt(ia);
3266 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003267 if (doit) {
3268 procs.add(app);
3269 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003270 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3271 || app.processName.equals(packageName)
3272 || app.processName.startsWith(procNamePrefix)) {
3273 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003274 if (!doit) {
3275 return true;
3276 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003277 app.removed = true;
3278 procs.add(app);
3279 }
3280 }
3281 }
3282 }
3283
3284 int N = procs.size();
3285 for (int i=0; i<N; i++) {
3286 removeProcessLocked(procs.get(i), callerWillRestart);
3287 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003288 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003289 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003290
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003291 private final boolean forceStopPackageLocked(String name, int uid,
3292 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003293 int i, N;
3294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 if (uid < 0) {
3296 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003297 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298 } catch (RemoteException e) {
3299 }
3300 }
3301
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003302 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003303 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003304
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003305 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3306 while (badApps.hasNext()) {
3307 SparseArray<Long> ba = badApps.next();
3308 if (ba.get(uid) != null) {
3309 badApps.remove();
3310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 }
3312 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003313
3314 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3315 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003317 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3318 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003320 if (!doit) {
3321 return true;
3322 }
3323 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003324 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 if (r.app != null) {
3326 r.app.removed = true;
3327 }
3328 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003329 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003330 }
3331 }
3332
3333 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3334 for (ServiceRecord service : mServices.values()) {
3335 if (service.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 stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 if (service.app != null) {
3342 service.app.removed = true;
3343 }
3344 service.app = null;
3345 services.add(service);
3346 }
3347 }
3348
3349 N = services.size();
3350 for (i=0; i<N; i++) {
3351 bringDownServiceLocked(services.get(i), true);
3352 }
3353
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003354 if (doit) {
3355 if (purgeCache) {
3356 AttributeCache ac = AttributeCache.instance();
3357 if (ac != null) {
3358 ac.removePackage(name);
3359 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003360 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003361 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003362 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003363
3364 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 }
3366
3367 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3368 final String name = app.processName;
3369 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003370 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 TAG, "Force removing process " + app + " (" + name
3372 + "/" + uid + ")");
3373
3374 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003375 if (mHeavyWeightProcess == app) {
3376 mHeavyWeightProcess = null;
3377 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 boolean needRestart = false;
3380 if (app.pid > 0 && app.pid != MY_PID) {
3381 int pid = app.pid;
3382 synchronized (mPidsSelfLocked) {
3383 mPidsSelfLocked.remove(pid);
3384 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3385 }
3386 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003387 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 Process.killProcess(pid);
3389
3390 if (app.persistent) {
3391 if (!callerWillRestart) {
3392 addAppLocked(app.info);
3393 } else {
3394 needRestart = true;
3395 }
3396 }
3397 } else {
3398 mRemovedProcesses.add(app);
3399 }
3400
3401 return needRestart;
3402 }
3403
3404 private final void processStartTimedOutLocked(ProcessRecord app) {
3405 final int pid = app.pid;
3406 boolean gone = false;
3407 synchronized (mPidsSelfLocked) {
3408 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3409 if (knownApp != null && knownApp.thread == null) {
3410 mPidsSelfLocked.remove(pid);
3411 gone = true;
3412 }
3413 }
3414
3415 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003416 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003417 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003418 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003420 if (mHeavyWeightProcess == app) {
3421 mHeavyWeightProcess = null;
3422 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3423 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003424 // Take care of any launching providers waiting for this process.
3425 checkAppInLaunchingProvidersLocked(app, true);
3426 // Take care of any services that are waiting for the process.
3427 for (int i=0; i<mPendingServices.size(); i++) {
3428 ServiceRecord sr = mPendingServices.get(i);
3429 if (app.info.uid == sr.appInfo.uid
3430 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003431 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003432 mPendingServices.remove(i);
3433 i--;
3434 bringDownServiceLocked(sr, true);
3435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003437 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003438 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003439 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003440 try {
3441 IBackupManager bm = IBackupManager.Stub.asInterface(
3442 ServiceManager.getService(Context.BACKUP_SERVICE));
3443 bm.agentDisconnected(app.info.packageName);
3444 } catch (RemoteException e) {
3445 // Can't happen; the backup manager is local
3446 }
3447 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003448 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003449 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003450 mPendingBroadcast.state = BroadcastRecord.IDLE;
3451 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003452 mPendingBroadcast = null;
3453 scheduleBroadcastsLocked();
3454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003456 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 }
3458 }
3459
3460 private final boolean attachApplicationLocked(IApplicationThread thread,
3461 int pid) {
3462
3463 // Find the application record that is being attached... either via
3464 // the pid if we are running in multiple processes, or just pull the
3465 // next app record if we are emulating process with anonymous threads.
3466 ProcessRecord app;
3467 if (pid != MY_PID && pid >= 0) {
3468 synchronized (mPidsSelfLocked) {
3469 app = mPidsSelfLocked.get(pid);
3470 }
3471 } else if (mStartingProcesses.size() > 0) {
3472 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003473 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 } else {
3475 app = null;
3476 }
3477
3478 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003479 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003481 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482 if (pid > 0 && pid != MY_PID) {
3483 Process.killProcess(pid);
3484 } else {
3485 try {
3486 thread.scheduleExit();
3487 } catch (Exception e) {
3488 // Ignore exceptions.
3489 }
3490 }
3491 return false;
3492 }
3493
3494 // If this application record is still attached to a previous
3495 // process, clean it up now.
3496 if (app.thread != null) {
3497 handleAppDiedLocked(app, true);
3498 }
3499
3500 // Tell the process all about itself.
3501
Joe Onorato8a9b2202010-02-26 18:56:32 -08003502 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003503 TAG, "Binding process pid " + pid + " to record " + app);
3504
3505 String processName = app.processName;
3506 try {
3507 thread.asBinder().linkToDeath(new AppDeathRecipient(
3508 app, pid, thread), 0);
3509 } catch (RemoteException e) {
3510 app.resetPackageList();
3511 startProcessLocked(app, "link fail", processName);
3512 return false;
3513 }
3514
Doug Zongker2bec3d42009-12-04 12:52:44 -08003515 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516
3517 app.thread = thread;
3518 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003519 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3520 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 app.forcingToForeground = null;
3522 app.foregroundServices = false;
3523 app.debugging = false;
3524
3525 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3526
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003527 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003528 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003530 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003531 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003532 }
3533
Joe Onorato8a9b2202010-02-26 18:56:32 -08003534 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 TAG, "New app record " + app
3536 + " thread=" + thread.asBinder() + " pid=" + pid);
3537 try {
3538 int testMode = IApplicationThread.DEBUG_OFF;
3539 if (mDebugApp != null && mDebugApp.equals(processName)) {
3540 testMode = mWaitForDebugger
3541 ? IApplicationThread.DEBUG_WAIT
3542 : IApplicationThread.DEBUG_ON;
3543 app.debugging = true;
3544 if (mDebugTransient) {
3545 mDebugApp = mOrigDebugApp;
3546 mWaitForDebugger = mOrigWaitForDebugger;
3547 }
3548 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003549
Christopher Tate181fafa2009-05-14 11:12:14 -07003550 // If the app is being launched for restore or full backup, set it up specially
3551 boolean isRestrictedBackupMode = false;
3552 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3553 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3554 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3555 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003556
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003557 ensurePackageDexOpt(app.instrumentationInfo != null
3558 ? app.instrumentationInfo.packageName
3559 : app.info.packageName);
3560 if (app.instrumentationClass != null) {
3561 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003562 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003563 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003564 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003565 thread.bindApplication(processName, app.instrumentationInfo != null
3566 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 app.instrumentationClass, app.instrumentationProfileFile,
3568 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003569 isRestrictedBackupMode || !normalMode,
3570 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003571 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003572 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 } catch (Exception e) {
3574 // todo: Yikes! What should we do? For now we will try to
3575 // start another process, but that could easily get us in
3576 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003577 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578
3579 app.resetPackageList();
3580 startProcessLocked(app, "bind fail", processName);
3581 return false;
3582 }
3583
3584 // Remove this record from the list of starting applications.
3585 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003586 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3587 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588 mProcessesOnHold.remove(app);
3589
3590 boolean badApp = false;
3591 boolean didSomething = false;
3592
3593 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003594 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003595 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003596 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3597 && processName.equals(hr.processName)) {
3598 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003599 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 didSomething = true;
3601 }
3602 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003603 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003604 + hr.intent.getComponent().flattenToShortString(), e);
3605 badApp = true;
3606 }
3607 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003608 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 }
3610 }
3611
3612 // Find any services that should be running in this process...
3613 if (!badApp && mPendingServices.size() > 0) {
3614 ServiceRecord sr = null;
3615 try {
3616 for (int i=0; i<mPendingServices.size(); i++) {
3617 sr = mPendingServices.get(i);
3618 if (app.info.uid != sr.appInfo.uid
3619 || !processName.equals(sr.processName)) {
3620 continue;
3621 }
3622
3623 mPendingServices.remove(i);
3624 i--;
3625 realStartServiceLocked(sr, app);
3626 didSomething = true;
3627 }
3628 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003629 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 + sr.shortName, e);
3631 badApp = true;
3632 }
3633 }
3634
3635 // Check if the next broadcast receiver is in this process...
3636 BroadcastRecord br = mPendingBroadcast;
3637 if (!badApp && br != null && br.curApp == app) {
3638 try {
3639 mPendingBroadcast = null;
3640 processCurBroadcastLocked(br, app);
3641 didSomething = true;
3642 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003643 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 + br.curComponent.flattenToShortString(), e);
3645 badApp = true;
3646 logBroadcastReceiverDiscard(br);
3647 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3648 br.resultExtras, br.resultAbort, true);
3649 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003650 // We need to reset the state if we fails to start the receiver.
3651 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003652 }
3653 }
3654
Christopher Tate181fafa2009-05-14 11:12:14 -07003655 // Check whether the next backup agent is in this process...
3656 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003657 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003658 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003659 try {
3660 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3661 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003662 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003663 e.printStackTrace();
3664 }
3665 }
3666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 if (badApp) {
3668 // todo: Also need to kill application to deal with all
3669 // kinds of exceptions.
3670 handleAppDiedLocked(app, false);
3671 return false;
3672 }
3673
3674 if (!didSomething) {
3675 updateOomAdjLocked();
3676 }
3677
3678 return true;
3679 }
3680
3681 public final void attachApplication(IApplicationThread thread) {
3682 synchronized (this) {
3683 int callingPid = Binder.getCallingPid();
3684 final long origId = Binder.clearCallingIdentity();
3685 attachApplicationLocked(thread, callingPid);
3686 Binder.restoreCallingIdentity(origId);
3687 }
3688 }
3689
Dianne Hackborne88846e2009-09-30 21:34:25 -07003690 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003692 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 Binder.restoreCallingIdentity(origId);
3694 }
3695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003696 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003697 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003698 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 mWindowManager.enableScreenAfterBoot();
3700 }
3701
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003702 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003703 IntentFilter pkgFilter = new IntentFilter();
3704 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3705 pkgFilter.addDataScheme("package");
3706 mContext.registerReceiver(new BroadcastReceiver() {
3707 @Override
3708 public void onReceive(Context context, Intent intent) {
3709 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3710 if (pkgs != null) {
3711 for (String pkg : pkgs) {
3712 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3713 setResultCode(Activity.RESULT_OK);
3714 return;
3715 }
3716 }
3717 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003718 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003719 }, pkgFilter);
3720
3721 synchronized (this) {
3722 // Ensure that any processes we had put on hold are now started
3723 // up.
3724 final int NP = mProcessesOnHold.size();
3725 if (NP > 0) {
3726 ArrayList<ProcessRecord> procs =
3727 new ArrayList<ProcessRecord>(mProcessesOnHold);
3728 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003729 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3730 + procs.get(ip));
3731 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003732 }
3733 }
3734
3735 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003736 // Start looking for apps that are abusing wake locks.
3737 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
3738 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003739 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003740 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003741 broadcastIntentLocked(null, null,
3742 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3743 null, null, 0, null, null,
3744 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3745 false, false, MY_PID, Process.SYSTEM_UID);
3746 }
3747 }
3748 }
3749
3750 final void ensureBootCompleted() {
3751 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003752 boolean enableScreen;
3753 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003754 booting = mBooting;
3755 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003756 enableScreen = !mBooted;
3757 mBooted = true;
3758 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003759
3760 if (booting) {
3761 finishBooting();
3762 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003763
3764 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003765 enableScreenAfterBoot();
3766 }
3767 }
3768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003769 public final void activityPaused(IBinder token, Bundle icicle) {
3770 // Refuse possible leaked file descriptors
3771 if (icicle != null && icicle.hasFileDescriptors()) {
3772 throw new IllegalArgumentException("File descriptors passed in Bundle");
3773 }
3774
3775 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003776 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003777 Binder.restoreCallingIdentity(origId);
3778 }
3779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780 public final void activityStopped(IBinder token, Bitmap thumbnail,
3781 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003782 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 TAG, "Activity stopped: token=" + token);
3784
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003785 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003786
3787 final long origId = Binder.clearCallingIdentity();
3788
3789 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003790 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003791 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003792 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 r.thumbnail = thumbnail;
3794 r.description = description;
3795 r.stopped = true;
3796 r.state = ActivityState.STOPPED;
3797 if (!r.finishing) {
3798 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003799 r.stack.destroyActivityLocked(r, true);
3800 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003801 }
3802 }
3803 }
3804 }
3805
3806 if (r != null) {
3807 sendPendingThumbnail(r, null, null, null, false);
3808 }
3809
3810 trimApplications();
3811
3812 Binder.restoreCallingIdentity(origId);
3813 }
3814
3815 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003816 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003817 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818 }
3819
3820 public String getCallingPackage(IBinder token) {
3821 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003822 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003823 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 }
3825 }
3826
3827 public ComponentName getCallingActivity(IBinder token) {
3828 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003829 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 return r != null ? r.intent.getComponent() : null;
3831 }
3832 }
3833
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003834 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003835 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003837 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 if (r != null) {
3839 return r.resultTo;
3840 }
3841 }
3842 return null;
3843 }
3844
3845 public ComponentName getActivityClassForToken(IBinder token) {
3846 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003847 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003848 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003849 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 return r.intent.getComponent();
3851 }
3852 return null;
3853 }
3854 }
3855
3856 public String getPackageForToken(IBinder token) {
3857 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003858 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003860 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003861 return r.packageName;
3862 }
3863 return null;
3864 }
3865 }
3866
3867 public IIntentSender getIntentSender(int type,
3868 String packageName, IBinder token, String resultWho,
3869 int requestCode, Intent intent, String resolvedType, int flags) {
3870 // Refuse possible leaked file descriptors
3871 if (intent != null && intent.hasFileDescriptors() == true) {
3872 throw new IllegalArgumentException("File descriptors passed in Intent");
3873 }
3874
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003875 if (type == INTENT_SENDER_BROADCAST) {
3876 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3877 throw new IllegalArgumentException(
3878 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3879 }
3880 }
3881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 synchronized(this) {
3883 int callingUid = Binder.getCallingUid();
3884 try {
3885 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3886 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003887 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 .getPackageUid(packageName);
3889 if (uid != Binder.getCallingUid()) {
3890 String msg = "Permission Denial: getIntentSender() from pid="
3891 + Binder.getCallingPid()
3892 + ", uid=" + Binder.getCallingUid()
3893 + ", (need uid=" + uid + ")"
3894 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003895 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 throw new SecurityException(msg);
3897 }
3898 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003899
3900 return getIntentSenderLocked(type, packageName, callingUid,
3901 token, resultWho, requestCode, intent, resolvedType, flags);
3902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003903 } catch (RemoteException e) {
3904 throw new SecurityException(e);
3905 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003906 }
3907 }
3908
3909 IIntentSender getIntentSenderLocked(int type,
3910 String packageName, int callingUid, IBinder token, String resultWho,
3911 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003912 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003913 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003914 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003915 if (index < 0) {
3916 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003918 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003919 if (activity.finishing) {
3920 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003921 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003922 }
3923
3924 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3925 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3926 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3927 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3928 |PendingIntent.FLAG_UPDATE_CURRENT);
3929
3930 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3931 type, packageName, activity, resultWho,
3932 requestCode, intent, resolvedType, flags);
3933 WeakReference<PendingIntentRecord> ref;
3934 ref = mIntentSenderRecords.get(key);
3935 PendingIntentRecord rec = ref != null ? ref.get() : null;
3936 if (rec != null) {
3937 if (!cancelCurrent) {
3938 if (updateCurrent) {
3939 rec.key.requestIntent.replaceExtras(intent);
3940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003941 return rec;
3942 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003943 rec.canceled = true;
3944 mIntentSenderRecords.remove(key);
3945 }
3946 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003947 return rec;
3948 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003949 rec = new PendingIntentRecord(this, key, callingUid);
3950 mIntentSenderRecords.put(key, rec.ref);
3951 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3952 if (activity.pendingResults == null) {
3953 activity.pendingResults
3954 = new HashSet<WeakReference<PendingIntentRecord>>();
3955 }
3956 activity.pendingResults.add(rec.ref);
3957 }
3958 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003959 }
3960
3961 public void cancelIntentSender(IIntentSender sender) {
3962 if (!(sender instanceof PendingIntentRecord)) {
3963 return;
3964 }
3965 synchronized(this) {
3966 PendingIntentRecord rec = (PendingIntentRecord)sender;
3967 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003968 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003969 .getPackageUid(rec.key.packageName);
3970 if (uid != Binder.getCallingUid()) {
3971 String msg = "Permission Denial: cancelIntentSender() from pid="
3972 + Binder.getCallingPid()
3973 + ", uid=" + Binder.getCallingUid()
3974 + " is not allowed to cancel packges "
3975 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003976 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 throw new SecurityException(msg);
3978 }
3979 } catch (RemoteException e) {
3980 throw new SecurityException(e);
3981 }
3982 cancelIntentSenderLocked(rec, true);
3983 }
3984 }
3985
3986 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3987 rec.canceled = true;
3988 mIntentSenderRecords.remove(rec.key);
3989 if (cleanActivity && rec.key.activity != null) {
3990 rec.key.activity.pendingResults.remove(rec.ref);
3991 }
3992 }
3993
3994 public String getPackageForIntentSender(IIntentSender pendingResult) {
3995 if (!(pendingResult instanceof PendingIntentRecord)) {
3996 return null;
3997 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003998 try {
3999 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4000 return res.key.packageName;
4001 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 }
4003 return null;
4004 }
4005
4006 public void setProcessLimit(int max) {
4007 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4008 "setProcessLimit()");
4009 mProcessLimit = max;
4010 }
4011
4012 public int getProcessLimit() {
4013 return mProcessLimit;
4014 }
4015
4016 void foregroundTokenDied(ForegroundToken token) {
4017 synchronized (ActivityManagerService.this) {
4018 synchronized (mPidsSelfLocked) {
4019 ForegroundToken cur
4020 = mForegroundProcesses.get(token.pid);
4021 if (cur != token) {
4022 return;
4023 }
4024 mForegroundProcesses.remove(token.pid);
4025 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4026 if (pr == null) {
4027 return;
4028 }
4029 pr.forcingToForeground = null;
4030 pr.foregroundServices = false;
4031 }
4032 updateOomAdjLocked();
4033 }
4034 }
4035
4036 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4037 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4038 "setProcessForeground()");
4039 synchronized(this) {
4040 boolean changed = false;
4041
4042 synchronized (mPidsSelfLocked) {
4043 ProcessRecord pr = mPidsSelfLocked.get(pid);
4044 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004045 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004046 return;
4047 }
4048 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4049 if (oldToken != null) {
4050 oldToken.token.unlinkToDeath(oldToken, 0);
4051 mForegroundProcesses.remove(pid);
4052 pr.forcingToForeground = null;
4053 changed = true;
4054 }
4055 if (isForeground && token != null) {
4056 ForegroundToken newToken = new ForegroundToken() {
4057 public void binderDied() {
4058 foregroundTokenDied(this);
4059 }
4060 };
4061 newToken.pid = pid;
4062 newToken.token = token;
4063 try {
4064 token.linkToDeath(newToken, 0);
4065 mForegroundProcesses.put(pid, newToken);
4066 pr.forcingToForeground = token;
4067 changed = true;
4068 } catch (RemoteException e) {
4069 // If the process died while doing this, we will later
4070 // do the cleanup with the process death link.
4071 }
4072 }
4073 }
4074
4075 if (changed) {
4076 updateOomAdjLocked();
4077 }
4078 }
4079 }
4080
4081 // =========================================================
4082 // PERMISSIONS
4083 // =========================================================
4084
4085 static class PermissionController extends IPermissionController.Stub {
4086 ActivityManagerService mActivityManagerService;
4087 PermissionController(ActivityManagerService activityManagerService) {
4088 mActivityManagerService = activityManagerService;
4089 }
4090
4091 public boolean checkPermission(String permission, int pid, int uid) {
4092 return mActivityManagerService.checkPermission(permission, pid,
4093 uid) == PackageManager.PERMISSION_GRANTED;
4094 }
4095 }
4096
4097 /**
4098 * This can be called with or without the global lock held.
4099 */
4100 int checkComponentPermission(String permission, int pid, int uid,
4101 int reqUid) {
4102 // We might be performing an operation on behalf of an indirect binder
4103 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4104 // client identity accordingly before proceeding.
4105 Identity tlsIdentity = sCallerIdentity.get();
4106 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004107 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4109 uid = tlsIdentity.uid;
4110 pid = tlsIdentity.pid;
4111 }
4112
4113 // Root, system server and our own process get to do everything.
4114 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4115 !Process.supportsProcesses()) {
4116 return PackageManager.PERMISSION_GRANTED;
4117 }
4118 // If the target requires a specific UID, always fail for others.
4119 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004120 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 return PackageManager.PERMISSION_DENIED;
4122 }
4123 if (permission == null) {
4124 return PackageManager.PERMISSION_GRANTED;
4125 }
4126 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004127 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 .checkUidPermission(permission, uid);
4129 } catch (RemoteException e) {
4130 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004131 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 }
4133 return PackageManager.PERMISSION_DENIED;
4134 }
4135
4136 /**
4137 * As the only public entry point for permissions checking, this method
4138 * can enforce the semantic that requesting a check on a null global
4139 * permission is automatically denied. (Internally a null permission
4140 * string is used when calling {@link #checkComponentPermission} in cases
4141 * when only uid-based security is needed.)
4142 *
4143 * This can be called with or without the global lock held.
4144 */
4145 public int checkPermission(String permission, int pid, int uid) {
4146 if (permission == null) {
4147 return PackageManager.PERMISSION_DENIED;
4148 }
4149 return checkComponentPermission(permission, pid, uid, -1);
4150 }
4151
4152 /**
4153 * Binder IPC calls go through the public entry point.
4154 * This can be called with or without the global lock held.
4155 */
4156 int checkCallingPermission(String permission) {
4157 return checkPermission(permission,
4158 Binder.getCallingPid(),
4159 Binder.getCallingUid());
4160 }
4161
4162 /**
4163 * This can be called with or without the global lock held.
4164 */
4165 void enforceCallingPermission(String permission, String func) {
4166 if (checkCallingPermission(permission)
4167 == PackageManager.PERMISSION_GRANTED) {
4168 return;
4169 }
4170
4171 String msg = "Permission Denial: " + func + " from pid="
4172 + Binder.getCallingPid()
4173 + ", uid=" + Binder.getCallingUid()
4174 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004175 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004176 throw new SecurityException(msg);
4177 }
4178
4179 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4180 ProviderInfo pi, int uid, int modeFlags) {
4181 try {
4182 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4183 if ((pi.readPermission != null) &&
4184 (pm.checkUidPermission(pi.readPermission, uid)
4185 != PackageManager.PERMISSION_GRANTED)) {
4186 return false;
4187 }
4188 }
4189 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4190 if ((pi.writePermission != null) &&
4191 (pm.checkUidPermission(pi.writePermission, uid)
4192 != PackageManager.PERMISSION_GRANTED)) {
4193 return false;
4194 }
4195 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004196 if (!pi.exported && pi.applicationInfo.uid != uid) {
4197 return false;
4198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 return true;
4200 } catch (RemoteException e) {
4201 return false;
4202 }
4203 }
4204
4205 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4206 int modeFlags) {
4207 // Root gets to do everything.
4208 if (uid == 0 || !Process.supportsProcesses()) {
4209 return true;
4210 }
4211 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4212 if (perms == null) return false;
4213 UriPermission perm = perms.get(uri);
4214 if (perm == null) return false;
4215 return (modeFlags&perm.modeFlags) == modeFlags;
4216 }
4217
4218 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4219 // Another redirected-binder-call permissions check as in
4220 // {@link checkComponentPermission}.
4221 Identity tlsIdentity = sCallerIdentity.get();
4222 if (tlsIdentity != null) {
4223 uid = tlsIdentity.uid;
4224 pid = tlsIdentity.pid;
4225 }
4226
4227 // Our own process gets to do everything.
4228 if (pid == MY_PID) {
4229 return PackageManager.PERMISSION_GRANTED;
4230 }
4231 synchronized(this) {
4232 return checkUriPermissionLocked(uri, uid, modeFlags)
4233 ? PackageManager.PERMISSION_GRANTED
4234 : PackageManager.PERMISSION_DENIED;
4235 }
4236 }
4237
Dianne Hackborn39792d22010-08-19 18:01:52 -07004238 /**
4239 * Check if the targetPkg can be granted permission to access uri by
4240 * the callingUid using the given modeFlags. Throws a security exception
4241 * if callingUid is not allowed to do this. Returns the uid of the target
4242 * if the URI permission grant should be performed; returns -1 if it is not
4243 * needed (for example targetPkg already has permission to access the URI).
4244 */
4245 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4246 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4248 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4249 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004250 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251 }
4252
Joe Onorato8a9b2202010-02-26 18:56:32 -08004253 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004254 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004255
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004256 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004257
4258 // If this is not a content: uri, we can't do anything with it.
4259 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004260 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004261 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004262 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004263 }
4264
4265 String name = uri.getAuthority();
4266 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004267 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004268 if (cpr != null) {
4269 pi = cpr.info;
4270 } else {
4271 try {
4272 pi = pm.resolveContentProvider(name,
4273 PackageManager.GET_URI_PERMISSION_PATTERNS);
4274 } catch (RemoteException ex) {
4275 }
4276 }
4277 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004278 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004279 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004280 }
4281
4282 int targetUid;
4283 try {
4284 targetUid = pm.getPackageUid(targetPkg);
4285 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004286 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004287 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004288 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 }
4290 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004291 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 }
4293
4294 // First... does the target actually need this permission?
4295 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4296 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004297 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004298 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004299 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004300 }
4301
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004302 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 if (!pi.grantUriPermissions) {
4304 throw new SecurityException("Provider " + pi.packageName
4305 + "/" + pi.name
4306 + " does not allow granting of Uri permissions (uri "
4307 + uri + ")");
4308 }
4309 if (pi.uriPermissionPatterns != null) {
4310 final int N = pi.uriPermissionPatterns.length;
4311 boolean allowed = false;
4312 for (int i=0; i<N; i++) {
4313 if (pi.uriPermissionPatterns[i] != null
4314 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4315 allowed = true;
4316 break;
4317 }
4318 }
4319 if (!allowed) {
4320 throw new SecurityException("Provider " + pi.packageName
4321 + "/" + pi.name
4322 + " does not allow granting of permission to path of Uri "
4323 + uri);
4324 }
4325 }
4326
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004327 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004328 // this uri?
4329 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4330 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4331 throw new SecurityException("Uid " + callingUid
4332 + " does not have permission to uri " + uri);
4333 }
4334 }
4335
Dianne Hackborn39792d22010-08-19 18:01:52 -07004336 return targetUid;
4337 }
4338
4339 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4340 Uri uri, int modeFlags, UriPermissionOwner owner) {
4341 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4342 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4343 if (modeFlags == 0) {
4344 return;
4345 }
4346
4347 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 // to the uri, and the target doesn't. Let's now give this to
4349 // the target.
4350
Joe Onorato8a9b2202010-02-26 18:56:32 -08004351 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004352 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 HashMap<Uri, UriPermission> targetUris
4355 = mGrantedUriPermissions.get(targetUid);
4356 if (targetUris == null) {
4357 targetUris = new HashMap<Uri, UriPermission>();
4358 mGrantedUriPermissions.put(targetUid, targetUris);
4359 }
4360
4361 UriPermission perm = targetUris.get(uri);
4362 if (perm == null) {
4363 perm = new UriPermission(targetUid, uri);
4364 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004365 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004368 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 perm.globalModeFlags |= modeFlags;
4370 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004371 perm.readOwners.add(owner);
4372 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004374 perm.writeOwners.add(owner);
4375 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 }
4377 }
4378
Dianne Hackborn39792d22010-08-19 18:01:52 -07004379 void grantUriPermissionLocked(int callingUid,
4380 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4381 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4382 if (targetUid < 0) {
4383 return;
4384 }
4385
4386 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4387 }
4388
4389 /**
4390 * Like checkGrantUriPermissionLocked, but takes an Intent.
4391 */
4392 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4393 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004394 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004395 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004396 + " from " + intent + "; flags=0x"
4397 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004400 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004401 }
4402 Uri data = intent.getData();
4403 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004404 return -1;
4405 }
4406 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4407 intent.getFlags());
4408 }
4409
4410 /**
4411 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4412 */
4413 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4414 String targetPkg, Intent intent, UriPermissionOwner owner) {
4415 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4416 intent.getFlags(), owner);
4417 }
4418
4419 void grantUriPermissionFromIntentLocked(int callingUid,
4420 String targetPkg, Intent intent, UriPermissionOwner owner) {
4421 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4422 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 return;
4424 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004425
4426 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004427 }
4428
4429 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4430 Uri uri, int modeFlags) {
4431 synchronized(this) {
4432 final ProcessRecord r = getRecordForAppLocked(caller);
4433 if (r == null) {
4434 throw new SecurityException("Unable to find app for caller "
4435 + caller
4436 + " when granting permission to uri " + uri);
4437 }
4438 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004439 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 }
4441 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004442 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 }
4444
4445 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4446 null);
4447 }
4448 }
4449
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004450 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4452 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4453 HashMap<Uri, UriPermission> perms
4454 = mGrantedUriPermissions.get(perm.uid);
4455 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004456 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004457 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 perms.remove(perm.uri);
4459 if (perms.size() == 0) {
4460 mGrantedUriPermissions.remove(perm.uid);
4461 }
4462 }
4463 }
4464 }
4465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4467 int modeFlags) {
4468 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4469 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4470 if (modeFlags == 0) {
4471 return;
4472 }
4473
Joe Onorato8a9b2202010-02-26 18:56:32 -08004474 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004475 "Revoking all granted permissions to " + uri);
4476
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004477 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478
4479 final String authority = uri.getAuthority();
4480 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004481 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 if (cpr != null) {
4483 pi = cpr.info;
4484 } else {
4485 try {
4486 pi = pm.resolveContentProvider(authority,
4487 PackageManager.GET_URI_PERMISSION_PATTERNS);
4488 } catch (RemoteException ex) {
4489 }
4490 }
4491 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004492 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 return;
4494 }
4495
4496 // Does the caller have this permission on the URI?
4497 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4498 // Right now, if you are not the original owner of the permission,
4499 // you are not allowed to revoke it.
4500 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4501 throw new SecurityException("Uid " + callingUid
4502 + " does not have permission to uri " + uri);
4503 //}
4504 }
4505
4506 // Go through all of the permissions and remove any that match.
4507 final List<String> SEGMENTS = uri.getPathSegments();
4508 if (SEGMENTS != null) {
4509 final int NS = SEGMENTS.size();
4510 int N = mGrantedUriPermissions.size();
4511 for (int i=0; i<N; i++) {
4512 HashMap<Uri, UriPermission> perms
4513 = mGrantedUriPermissions.valueAt(i);
4514 Iterator<UriPermission> it = perms.values().iterator();
4515 toploop:
4516 while (it.hasNext()) {
4517 UriPermission perm = it.next();
4518 Uri targetUri = perm.uri;
4519 if (!authority.equals(targetUri.getAuthority())) {
4520 continue;
4521 }
4522 List<String> targetSegments = targetUri.getPathSegments();
4523 if (targetSegments == null) {
4524 continue;
4525 }
4526 if (targetSegments.size() < NS) {
4527 continue;
4528 }
4529 for (int j=0; j<NS; j++) {
4530 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4531 continue toploop;
4532 }
4533 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004534 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004535 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 perm.clearModes(modeFlags);
4537 if (perm.modeFlags == 0) {
4538 it.remove();
4539 }
4540 }
4541 if (perms.size() == 0) {
4542 mGrantedUriPermissions.remove(
4543 mGrantedUriPermissions.keyAt(i));
4544 N--;
4545 i--;
4546 }
4547 }
4548 }
4549 }
4550
4551 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4552 int modeFlags) {
4553 synchronized(this) {
4554 final ProcessRecord r = getRecordForAppLocked(caller);
4555 if (r == null) {
4556 throw new SecurityException("Unable to find app for caller "
4557 + caller
4558 + " when revoking permission to uri " + uri);
4559 }
4560 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004561 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 return;
4563 }
4564
4565 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4566 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4567 if (modeFlags == 0) {
4568 return;
4569 }
4570
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004571 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572
4573 final String authority = uri.getAuthority();
4574 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004575 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 if (cpr != null) {
4577 pi = cpr.info;
4578 } else {
4579 try {
4580 pi = pm.resolveContentProvider(authority,
4581 PackageManager.GET_URI_PERMISSION_PATTERNS);
4582 } catch (RemoteException ex) {
4583 }
4584 }
4585 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004586 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587 return;
4588 }
4589
4590 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4591 }
4592 }
4593
Dianne Hackborn7e269642010-08-25 19:50:20 -07004594 @Override
4595 public IBinder newUriPermissionOwner(String name) {
4596 synchronized(this) {
4597 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4598 return owner.getExternalTokenLocked();
4599 }
4600 }
4601
4602 @Override
4603 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4604 Uri uri, int modeFlags) {
4605 synchronized(this) {
4606 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4607 if (owner == null) {
4608 throw new IllegalArgumentException("Unknown owner: " + token);
4609 }
4610 if (fromUid != Binder.getCallingUid()) {
4611 if (Binder.getCallingUid() != Process.myUid()) {
4612 // Only system code can grant URI permissions on behalf
4613 // of other users.
4614 throw new SecurityException("nice try");
4615 }
4616 }
4617 if (targetPkg == null) {
4618 throw new IllegalArgumentException("null target");
4619 }
4620 if (uri == null) {
4621 throw new IllegalArgumentException("null uri");
4622 }
4623
4624 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4625 }
4626 }
4627
4628 @Override
4629 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4630 synchronized(this) {
4631 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4632 if (owner == null) {
4633 throw new IllegalArgumentException("Unknown owner: " + token);
4634 }
4635
4636 if (uri == null) {
4637 owner.removeUriPermissionsLocked(mode);
4638 } else {
4639 owner.removeUriPermissionLocked(uri, mode);
4640 }
4641 }
4642 }
4643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4645 synchronized (this) {
4646 ProcessRecord app =
4647 who != null ? getRecordForAppLocked(who) : null;
4648 if (app == null) return;
4649
4650 Message msg = Message.obtain();
4651 msg.what = WAIT_FOR_DEBUGGER_MSG;
4652 msg.obj = app;
4653 msg.arg1 = waiting ? 1 : 0;
4654 mHandler.sendMessage(msg);
4655 }
4656 }
4657
4658 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4659 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004660 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004661 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004662 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004663 }
4664
4665 // =========================================================
4666 // TASK MANAGEMENT
4667 // =========================================================
4668
4669 public List getTasks(int maxNum, int flags,
4670 IThumbnailReceiver receiver) {
4671 ArrayList list = new ArrayList();
4672
4673 PendingThumbnailsRecord pending = null;
4674 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004675 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004676
4677 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004678 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4680 + ", receiver=" + receiver);
4681
4682 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4683 != PackageManager.PERMISSION_GRANTED) {
4684 if (receiver != null) {
4685 // If the caller wants to wait for pending thumbnails,
4686 // it ain't gonna get them.
4687 try {
4688 receiver.finished();
4689 } catch (RemoteException ex) {
4690 }
4691 }
4692 String msg = "Permission Denial: getTasks() from pid="
4693 + Binder.getCallingPid()
4694 + ", uid=" + Binder.getCallingUid()
4695 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004696 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 throw new SecurityException(msg);
4698 }
4699
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004700 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004701 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004702 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004703 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004704 CharSequence topDescription = null;
4705 TaskRecord curTask = null;
4706 int numActivities = 0;
4707 int numRunning = 0;
4708 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004709 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004711 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712
4713 // Initialize state for next task if needed.
4714 if (top == null ||
4715 (top.state == ActivityState.INITIALIZING
4716 && top.task == r.task)) {
4717 top = r;
4718 topDescription = r.description;
4719 curTask = r.task;
4720 numActivities = numRunning = 0;
4721 }
4722
4723 // Add 'r' into the current task.
4724 numActivities++;
4725 if (r.app != null && r.app.thread != null) {
4726 numRunning++;
4727 }
4728 if (topDescription == null) {
4729 topDescription = r.description;
4730 }
4731
Joe Onorato8a9b2202010-02-26 18:56:32 -08004732 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 TAG, r.intent.getComponent().flattenToShortString()
4734 + ": task=" + r.task);
4735
4736 // If the next one is a different task, generate a new
4737 // TaskInfo entry for what we have.
4738 if (next == null || next.task != curTask) {
4739 ActivityManager.RunningTaskInfo ci
4740 = new ActivityManager.RunningTaskInfo();
4741 ci.id = curTask.taskId;
4742 ci.baseActivity = r.intent.getComponent();
4743 ci.topActivity = top.intent.getComponent();
4744 ci.thumbnail = top.thumbnail;
4745 ci.description = topDescription;
4746 ci.numActivities = numActivities;
4747 ci.numRunning = numRunning;
4748 //System.out.println(
4749 // "#" + maxNum + ": " + " descr=" + ci.description);
4750 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004751 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 TAG, "State=" + top.state + "Idle=" + top.idle
4753 + " app=" + top.app
4754 + " thr=" + (top.app != null ? top.app.thread : null));
4755 if (top.state == ActivityState.RESUMED
4756 || top.state == ActivityState.PAUSING) {
4757 if (top.idle && top.app != null
4758 && top.app.thread != null) {
4759 topRecord = top;
4760 topThumbnail = top.app.thread;
4761 } else {
4762 top.thumbnailNeeded = true;
4763 }
4764 }
4765 if (pending == null) {
4766 pending = new PendingThumbnailsRecord(receiver);
4767 }
4768 pending.pendingRecords.add(top);
4769 }
4770 list.add(ci);
4771 maxNum--;
4772 top = null;
4773 }
4774 }
4775
4776 if (pending != null) {
4777 mPendingThumbnails.add(pending);
4778 }
4779 }
4780
Joe Onorato8a9b2202010-02-26 18:56:32 -08004781 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004782
4783 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004784 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004785 try {
4786 topThumbnail.requestThumbnail(topRecord);
4787 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004788 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 sendPendingThumbnail(null, topRecord, null, null, true);
4790 }
4791 }
4792
4793 if (pending == null && receiver != null) {
4794 // In this case all thumbnails were available and the client
4795 // is being asked to be told when the remaining ones come in...
4796 // which is unusually, since the top-most currently running
4797 // activity should never have a canned thumbnail! Oh well.
4798 try {
4799 receiver.finished();
4800 } catch (RemoteException ex) {
4801 }
4802 }
4803
4804 return list;
4805 }
4806
4807 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4808 int flags) {
4809 synchronized (this) {
4810 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4811 "getRecentTasks()");
4812
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004813 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 final int N = mRecentTasks.size();
4816 ArrayList<ActivityManager.RecentTaskInfo> res
4817 = new ArrayList<ActivityManager.RecentTaskInfo>(
4818 maxNum < N ? maxNum : N);
4819 for (int i=0; i<N && maxNum > 0; i++) {
4820 TaskRecord tr = mRecentTasks.get(i);
4821 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4822 || (tr.intent == null)
4823 || ((tr.intent.getFlags()
4824 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4825 ActivityManager.RecentTaskInfo rti
4826 = new ActivityManager.RecentTaskInfo();
4827 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4828 rti.baseIntent = new Intent(
4829 tr.intent != null ? tr.intent : tr.affinityIntent);
4830 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004831
4832 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4833 // Check whether this activity is currently available.
4834 try {
4835 if (rti.origActivity != null) {
4836 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4837 continue;
4838 }
4839 } else if (rti.baseIntent != null) {
4840 if (pm.queryIntentActivities(rti.baseIntent,
4841 null, 0) == null) {
4842 continue;
4843 }
4844 }
4845 } catch (RemoteException e) {
4846 // Will never happen.
4847 }
4848 }
4849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004850 res.add(rti);
4851 maxNum--;
4852 }
4853 }
4854 return res;
4855 }
4856 }
4857
4858 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4859 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004860 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004861 TaskRecord jt = startTask;
4862
4863 // First look backwards
4864 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004865 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 if (r.task != jt) {
4867 jt = r.task;
4868 if (affinity.equals(jt.affinity)) {
4869 return j;
4870 }
4871 }
4872 }
4873
4874 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004875 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 jt = startTask;
4877 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004878 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 if (r.task != jt) {
4880 if (affinity.equals(jt.affinity)) {
4881 return j;
4882 }
4883 jt = r.task;
4884 }
4885 }
4886
4887 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004888 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004889 return N-1;
4890 }
4891
4892 return -1;
4893 }
4894
4895 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004896 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 */
4898 public void moveTaskToFront(int task) {
4899 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4900 "moveTaskToFront()");
4901
4902 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004903 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4904 Binder.getCallingUid(), "Task to front")) {
4905 return;
4906 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004907 final long origId = Binder.clearCallingIdentity();
4908 try {
4909 int N = mRecentTasks.size();
4910 for (int i=0; i<N; i++) {
4911 TaskRecord tr = mRecentTasks.get(i);
4912 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004913 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 return;
4915 }
4916 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004917 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4918 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004919 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004920 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004921 return;
4922 }
4923 }
4924 } finally {
4925 Binder.restoreCallingIdentity(origId);
4926 }
4927 }
4928 }
4929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 public void moveTaskToBack(int task) {
4931 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4932 "moveTaskToBack()");
4933
4934 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004935 if (mMainStack.mResumedActivity != null
4936 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004937 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4938 Binder.getCallingUid(), "Task to back")) {
4939 return;
4940 }
4941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004943 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 Binder.restoreCallingIdentity(origId);
4945 }
4946 }
4947
4948 /**
4949 * Moves an activity, and all of the other activities within the same task, to the bottom
4950 * of the history stack. The activity's order within the task is unchanged.
4951 *
4952 * @param token A reference to the activity we wish to move
4953 * @param nonRoot If false then this only works if the activity is the root
4954 * of a task; if true it will work for any activity in a task.
4955 * @return Returns true if the move completed, false if not.
4956 */
4957 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4958 synchronized(this) {
4959 final long origId = Binder.clearCallingIdentity();
4960 int taskId = getTaskForActivityLocked(token, !nonRoot);
4961 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004962 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 }
4964 Binder.restoreCallingIdentity(origId);
4965 }
4966 return false;
4967 }
4968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 public void moveTaskBackwards(int task) {
4970 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4971 "moveTaskBackwards()");
4972
4973 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004974 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4975 Binder.getCallingUid(), "Task backwards")) {
4976 return;
4977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978 final long origId = Binder.clearCallingIdentity();
4979 moveTaskBackwardsLocked(task);
4980 Binder.restoreCallingIdentity(origId);
4981 }
4982 }
4983
4984 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004985 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 }
4987
4988 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4989 synchronized(this) {
4990 return getTaskForActivityLocked(token, onlyRoot);
4991 }
4992 }
4993
4994 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004995 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 TaskRecord lastTask = null;
4997 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004998 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 if (r == token) {
5000 if (!onlyRoot || lastTask != r.task) {
5001 return r.task.taskId;
5002 }
5003 return -1;
5004 }
5005 lastTask = r.task;
5006 }
5007
5008 return -1;
5009 }
5010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005011 public void finishOtherInstances(IBinder token, ComponentName className) {
5012 synchronized(this) {
5013 final long origId = Binder.clearCallingIdentity();
5014
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005015 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 TaskRecord lastTask = null;
5017 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005018 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019 if (r.realActivity.equals(className)
5020 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005021 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005022 null, "others")) {
5023 i--;
5024 N--;
5025 }
5026 }
5027 lastTask = r.task;
5028 }
5029
5030 Binder.restoreCallingIdentity(origId);
5031 }
5032 }
5033
5034 // =========================================================
5035 // THUMBNAILS
5036 // =========================================================
5037
5038 public void reportThumbnail(IBinder token,
5039 Bitmap thumbnail, CharSequence description) {
5040 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5041 final long origId = Binder.clearCallingIdentity();
5042 sendPendingThumbnail(null, token, thumbnail, description, true);
5043 Binder.restoreCallingIdentity(origId);
5044 }
5045
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005046 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005047 Bitmap thumbnail, CharSequence description, boolean always) {
5048 TaskRecord task = null;
5049 ArrayList receivers = null;
5050
5051 //System.out.println("Send pending thumbnail: " + r);
5052
5053 synchronized(this) {
5054 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005055 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 if (index < 0) {
5057 return;
5058 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005059 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005060 }
5061 if (thumbnail == null) {
5062 thumbnail = r.thumbnail;
5063 description = r.description;
5064 }
5065 if (thumbnail == null && !always) {
5066 // If there is no thumbnail, and this entry is not actually
5067 // going away, then abort for now and pick up the next
5068 // thumbnail we get.
5069 return;
5070 }
5071 task = r.task;
5072
5073 int N = mPendingThumbnails.size();
5074 int i=0;
5075 while (i<N) {
5076 PendingThumbnailsRecord pr =
5077 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5078 //System.out.println("Looking in " + pr.pendingRecords);
5079 if (pr.pendingRecords.remove(r)) {
5080 if (receivers == null) {
5081 receivers = new ArrayList();
5082 }
5083 receivers.add(pr);
5084 if (pr.pendingRecords.size() == 0) {
5085 pr.finished = true;
5086 mPendingThumbnails.remove(i);
5087 N--;
5088 continue;
5089 }
5090 }
5091 i++;
5092 }
5093 }
5094
5095 if (receivers != null) {
5096 final int N = receivers.size();
5097 for (int i=0; i<N; i++) {
5098 try {
5099 PendingThumbnailsRecord pr =
5100 (PendingThumbnailsRecord)receivers.get(i);
5101 pr.receiver.newThumbnail(
5102 task != null ? task.taskId : -1, thumbnail, description);
5103 if (pr.finished) {
5104 pr.receiver.finished();
5105 }
5106 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005107 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005108 }
5109 }
5110 }
5111 }
5112
5113 // =========================================================
5114 // CONTENT PROVIDERS
5115 // =========================================================
5116
5117 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5118 List providers = null;
5119 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005120 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005122 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005123 } catch (RemoteException ex) {
5124 }
5125 if (providers != null) {
5126 final int N = providers.size();
5127 for (int i=0; i<N; i++) {
5128 ProviderInfo cpi =
5129 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005130 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131 if (cpr == null) {
5132 cpr = new ContentProviderRecord(cpi, app.info);
5133 mProvidersByClass.put(cpi.name, cpr);
5134 }
5135 app.pubProviders.put(cpi.name, cpr);
5136 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005137 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 }
5139 }
5140 return providers;
5141 }
5142
5143 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005144 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5146 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5147 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5148 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005149 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005150 return null;
5151 }
5152 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5153 cpi.exported ? -1 : cpi.applicationInfo.uid)
5154 == PackageManager.PERMISSION_GRANTED) {
5155 return null;
5156 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005157
5158 PathPermission[] pps = cpi.pathPermissions;
5159 if (pps != null) {
5160 int i = pps.length;
5161 while (i > 0) {
5162 i--;
5163 PathPermission pp = pps[i];
5164 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5165 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005166 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005167 return null;
5168 }
5169 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5170 cpi.exported ? -1 : cpi.applicationInfo.uid)
5171 == PackageManager.PERMISSION_GRANTED) {
5172 return null;
5173 }
5174 }
5175 }
5176
Dianne Hackbornb424b632010-08-18 15:59:05 -07005177 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5178 if (perms != null) {
5179 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5180 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5181 return null;
5182 }
5183 }
5184 }
5185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 String msg = "Permission Denial: opening provider " + cpi.name
5187 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5188 + ", uid=" + callingUid + ") requires "
5189 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005190 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 return msg;
5192 }
5193
5194 private final ContentProviderHolder getContentProviderImpl(
5195 IApplicationThread caller, String name) {
5196 ContentProviderRecord cpr;
5197 ProviderInfo cpi = null;
5198
5199 synchronized(this) {
5200 ProcessRecord r = null;
5201 if (caller != null) {
5202 r = getRecordForAppLocked(caller);
5203 if (r == null) {
5204 throw new SecurityException(
5205 "Unable to find app for caller " + caller
5206 + " (pid=" + Binder.getCallingPid()
5207 + ") when getting content provider " + name);
5208 }
5209 }
5210
5211 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005212 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005213 if (cpr != null) {
5214 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005215 String msg;
5216 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5217 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 }
5219
5220 if (r != null && cpr.canRunHere(r)) {
5221 // This provider has been published or is in the process
5222 // of being published... but it is also allowed to run
5223 // in the caller's process, so don't make a connection
5224 // and just let the caller instantiate its own instance.
5225 if (cpr.provider != null) {
5226 // don't give caller the provider object, it needs
5227 // to make its own.
5228 cpr = new ContentProviderRecord(cpr);
5229 }
5230 return cpr;
5231 }
5232
5233 final long origId = Binder.clearCallingIdentity();
5234
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005235 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 // return it right away.
5237 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005238 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005239 "Adding provider requested by "
5240 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005241 + cpr.info.processName);
5242 Integer cnt = r.conProviders.get(cpr);
5243 if (cnt == null) {
5244 r.conProviders.put(cpr, new Integer(1));
5245 } else {
5246 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005249 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5250 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005251 // make sure to count it as being accessed and thus
5252 // back up on the LRU list. This is good because
5253 // content providers are often expensive to start.
5254 updateLruProcessLocked(cpr.app, false, true);
5255 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005256 } else {
5257 cpr.externals++;
5258 }
5259
5260 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261 updateOomAdjLocked(cpr.app);
5262 }
5263
5264 Binder.restoreCallingIdentity(origId);
5265
5266 } else {
5267 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005268 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005269 resolveContentProvider(name,
5270 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 } catch (RemoteException ex) {
5272 }
5273 if (cpi == null) {
5274 return null;
5275 }
5276
Dianne Hackbornb424b632010-08-18 15:59:05 -07005277 String msg;
5278 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5279 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 }
5281
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005282 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005283 && !cpi.processName.equals("system")) {
5284 // If this content provider does not run in the system
5285 // process, and the system is not yet ready to run other
5286 // processes, then fail fast instead of hanging.
5287 throw new IllegalArgumentException(
5288 "Attempt to launch content provider before system ready");
5289 }
5290
Dianne Hackborn860755f2010-06-03 18:47:52 -07005291 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 final boolean firstClass = cpr == null;
5293 if (firstClass) {
5294 try {
5295 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005296 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005297 getApplicationInfo(
5298 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005299 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005300 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005301 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 + cpi.name);
5303 return null;
5304 }
5305 cpr = new ContentProviderRecord(cpi, ai);
5306 } catch (RemoteException ex) {
5307 // pm is in same process, this will never happen.
5308 }
5309 }
5310
5311 if (r != null && cpr.canRunHere(r)) {
5312 // If this is a multiprocess provider, then just return its
5313 // info and allow the caller to instantiate it. Only do
5314 // this if the provider is the same user as the caller's
5315 // process, or can run as root (so can be in any process).
5316 return cpr;
5317 }
5318
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005319 if (DEBUG_PROVIDER) {
5320 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005321 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005322 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 }
5324
5325 // This is single process, and our app is now connecting to it.
5326 // See if we are already in the process of launching this
5327 // provider.
5328 final int N = mLaunchingProviders.size();
5329 int i;
5330 for (i=0; i<N; i++) {
5331 if (mLaunchingProviders.get(i) == cpr) {
5332 break;
5333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 }
5335
5336 // If the provider is not already being launched, then get it
5337 // started.
5338 if (i >= N) {
5339 final long origId = Binder.clearCallingIdentity();
5340 ProcessRecord proc = startProcessLocked(cpi.processName,
5341 cpr.appInfo, false, 0, "content provider",
5342 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005343 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005345 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005346 + cpi.applicationInfo.packageName + "/"
5347 + cpi.applicationInfo.uid + " for provider "
5348 + name + ": process is bad");
5349 return null;
5350 }
5351 cpr.launchingApp = proc;
5352 mLaunchingProviders.add(cpr);
5353 Binder.restoreCallingIdentity(origId);
5354 }
5355
5356 // Make sure the provider is published (the same provider class
5357 // may be published under multiple names).
5358 if (firstClass) {
5359 mProvidersByClass.put(cpi.name, cpr);
5360 }
5361 mProvidersByName.put(name, cpr);
5362
5363 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005364 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005365 "Adding provider requested by "
5366 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005367 + cpr.info.processName);
5368 Integer cnt = r.conProviders.get(cpr);
5369 if (cnt == null) {
5370 r.conProviders.put(cpr, new Integer(1));
5371 } else {
5372 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005374 cpr.clients.add(r);
5375 } else {
5376 cpr.externals++;
5377 }
5378 }
5379 }
5380
5381 // Wait for the provider to be published...
5382 synchronized (cpr) {
5383 while (cpr.provider == null) {
5384 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005385 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 + cpi.applicationInfo.packageName + "/"
5387 + cpi.applicationInfo.uid + " for provider "
5388 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005389 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 cpi.applicationInfo.packageName,
5391 cpi.applicationInfo.uid, name);
5392 return null;
5393 }
5394 try {
5395 cpr.wait();
5396 } catch (InterruptedException ex) {
5397 }
5398 }
5399 }
5400 return cpr;
5401 }
5402
5403 public final ContentProviderHolder getContentProvider(
5404 IApplicationThread caller, String name) {
5405 if (caller == null) {
5406 String msg = "null IApplicationThread when getting content provider "
5407 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005408 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 throw new SecurityException(msg);
5410 }
5411
5412 return getContentProviderImpl(caller, name);
5413 }
5414
5415 private ContentProviderHolder getContentProviderExternal(String name) {
5416 return getContentProviderImpl(null, name);
5417 }
5418
5419 /**
5420 * Drop a content provider from a ProcessRecord's bookkeeping
5421 * @param cpr
5422 */
5423 public void removeContentProvider(IApplicationThread caller, String name) {
5424 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005425 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005427 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005428 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005429 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005430 return;
5431 }
5432 final ProcessRecord r = getRecordForAppLocked(caller);
5433 if (r == null) {
5434 throw new SecurityException(
5435 "Unable to find app for caller " + caller +
5436 " when removing content provider " + name);
5437 }
5438 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005439 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005440 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005441 + r.info.processName + " from process "
5442 + localCpr.appInfo.processName);
5443 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005444 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005445 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005446 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005447 return;
5448 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005449 Integer cnt = r.conProviders.get(localCpr);
5450 if (cnt == null || cnt.intValue() <= 1) {
5451 localCpr.clients.remove(r);
5452 r.conProviders.remove(localCpr);
5453 } else {
5454 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005456 }
5457 updateOomAdjLocked();
5458 }
5459 }
5460
5461 private void removeContentProviderExternal(String name) {
5462 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005463 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005464 if(cpr == null) {
5465 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005466 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005467 return;
5468 }
5469
5470 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005471 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 localCpr.externals--;
5473 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005474 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475 }
5476 updateOomAdjLocked();
5477 }
5478 }
5479
5480 public final void publishContentProviders(IApplicationThread caller,
5481 List<ContentProviderHolder> providers) {
5482 if (providers == null) {
5483 return;
5484 }
5485
5486 synchronized(this) {
5487 final ProcessRecord r = getRecordForAppLocked(caller);
5488 if (r == null) {
5489 throw new SecurityException(
5490 "Unable to find app for caller " + caller
5491 + " (pid=" + Binder.getCallingPid()
5492 + ") when publishing content providers");
5493 }
5494
5495 final long origId = Binder.clearCallingIdentity();
5496
5497 final int N = providers.size();
5498 for (int i=0; i<N; i++) {
5499 ContentProviderHolder src = providers.get(i);
5500 if (src == null || src.info == null || src.provider == null) {
5501 continue;
5502 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005503 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 if (dst != null) {
5505 mProvidersByClass.put(dst.info.name, dst);
5506 String names[] = dst.info.authority.split(";");
5507 for (int j = 0; j < names.length; j++) {
5508 mProvidersByName.put(names[j], dst);
5509 }
5510
5511 int NL = mLaunchingProviders.size();
5512 int j;
5513 for (j=0; j<NL; j++) {
5514 if (mLaunchingProviders.get(j) == dst) {
5515 mLaunchingProviders.remove(j);
5516 j--;
5517 NL--;
5518 }
5519 }
5520 synchronized (dst) {
5521 dst.provider = src.provider;
5522 dst.app = r;
5523 dst.notifyAll();
5524 }
5525 updateOomAdjLocked(r);
5526 }
5527 }
5528
5529 Binder.restoreCallingIdentity(origId);
5530 }
5531 }
5532
5533 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005534 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005535 synchronized (mSelf) {
5536 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5537 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005538 if (providers != null) {
5539 for (int i=providers.size()-1; i>=0; i--) {
5540 ProviderInfo pi = (ProviderInfo)providers.get(i);
5541 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5542 Slog.w(TAG, "Not installing system proc provider " + pi.name
5543 + ": not system .apk");
5544 providers.remove(i);
5545 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005546 }
5547 }
5548 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005549 if (providers != null) {
5550 mSystemThread.installSystemProviders(providers);
5551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005552 }
5553
5554 // =========================================================
5555 // GLOBAL MANAGEMENT
5556 // =========================================================
5557
5558 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5559 ApplicationInfo info, String customProcess) {
5560 String proc = customProcess != null ? customProcess : info.processName;
5561 BatteryStatsImpl.Uid.Proc ps = null;
5562 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5563 synchronized (stats) {
5564 ps = stats.getProcessStatsLocked(info.uid, proc);
5565 }
5566 return new ProcessRecord(ps, thread, info, proc);
5567 }
5568
5569 final ProcessRecord addAppLocked(ApplicationInfo info) {
5570 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5571
5572 if (app == null) {
5573 app = newProcessRecordLocked(null, info, null);
5574 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005575 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 }
5577
5578 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5579 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5580 app.persistent = true;
5581 app.maxAdj = CORE_SERVER_ADJ;
5582 }
5583 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5584 mPersistentStartingProcesses.add(app);
5585 startProcessLocked(app, "added application", app.processName);
5586 }
5587
5588 return app;
5589 }
5590
5591 public void unhandledBack() {
5592 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5593 "unhandledBack()");
5594
5595 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005596 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005597 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005598 TAG, "Performing unhandledBack(): stack size = " + count);
5599 if (count > 1) {
5600 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005601 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005602 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5603 Binder.restoreCallingIdentity(origId);
5604 }
5605 }
5606 }
5607
5608 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5609 String name = uri.getAuthority();
5610 ContentProviderHolder cph = getContentProviderExternal(name);
5611 ParcelFileDescriptor pfd = null;
5612 if (cph != null) {
5613 // We record the binder invoker's uid in thread-local storage before
5614 // going to the content provider to open the file. Later, in the code
5615 // that handles all permissions checks, we look for this uid and use
5616 // that rather than the Activity Manager's own uid. The effect is that
5617 // we do the check against the caller's permissions even though it looks
5618 // to the content provider like the Activity Manager itself is making
5619 // the request.
5620 sCallerIdentity.set(new Identity(
5621 Binder.getCallingPid(), Binder.getCallingUid()));
5622 try {
5623 pfd = cph.provider.openFile(uri, "r");
5624 } catch (FileNotFoundException e) {
5625 // do nothing; pfd will be returned null
5626 } finally {
5627 // Ensure that whatever happens, we clean up the identity state
5628 sCallerIdentity.remove();
5629 }
5630
5631 // We've got the fd now, so we're done with the provider.
5632 removeContentProviderExternal(name);
5633 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005634 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 }
5636 return pfd;
5637 }
5638
5639 public void goingToSleep() {
5640 synchronized(this) {
5641 mSleeping = true;
5642 mWindowManager.setEventDispatching(false);
5643
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005644 if (mMainStack.mResumedActivity != null) {
5645 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005646 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005647 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005648 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005649
5650 // Initialize the wake times of all processes.
5651 checkExcessiveWakeLocksLocked(false);
5652 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5653 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5654 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 }
5656 }
5657
Dianne Hackborn55280a92009-05-07 15:53:46 -07005658 public boolean shutdown(int timeout) {
5659 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5660 != PackageManager.PERMISSION_GRANTED) {
5661 throw new SecurityException("Requires permission "
5662 + android.Manifest.permission.SHUTDOWN);
5663 }
5664
5665 boolean timedout = false;
5666
5667 synchronized(this) {
5668 mShuttingDown = true;
5669 mWindowManager.setEventDispatching(false);
5670
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005671 if (mMainStack.mResumedActivity != null) {
5672 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005673 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005674 while (mMainStack.mResumedActivity != null
5675 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005676 long delay = endTime - System.currentTimeMillis();
5677 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005678 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005679 timedout = true;
5680 break;
5681 }
5682 try {
5683 this.wait();
5684 } catch (InterruptedException e) {
5685 }
5686 }
5687 }
5688 }
5689
5690 mUsageStatsService.shutdown();
5691 mBatteryStatsService.shutdown();
5692
5693 return timedout;
5694 }
5695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005696 public void wakingUp() {
5697 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005698 if (mMainStack.mGoingToSleep.isHeld()) {
5699 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 }
5701 mWindowManager.setEventDispatching(true);
5702 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005703 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005704 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005705 }
5706 }
5707
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005708 public void stopAppSwitches() {
5709 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5710 != PackageManager.PERMISSION_GRANTED) {
5711 throw new SecurityException("Requires permission "
5712 + android.Manifest.permission.STOP_APP_SWITCHES);
5713 }
5714
5715 synchronized(this) {
5716 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5717 + APP_SWITCH_DELAY_TIME;
5718 mDidAppSwitch = false;
5719 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5720 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5721 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5722 }
5723 }
5724
5725 public void resumeAppSwitches() {
5726 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5727 != PackageManager.PERMISSION_GRANTED) {
5728 throw new SecurityException("Requires permission "
5729 + android.Manifest.permission.STOP_APP_SWITCHES);
5730 }
5731
5732 synchronized(this) {
5733 // Note that we don't execute any pending app switches... we will
5734 // let those wait until either the timeout, or the next start
5735 // activity request.
5736 mAppSwitchesAllowedTime = 0;
5737 }
5738 }
5739
5740 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5741 String name) {
5742 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5743 return true;
5744 }
5745
5746 final int perm = checkComponentPermission(
5747 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5748 callingUid, -1);
5749 if (perm == PackageManager.PERMISSION_GRANTED) {
5750 return true;
5751 }
5752
Joe Onorato8a9b2202010-02-26 18:56:32 -08005753 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005754 return false;
5755 }
5756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005757 public void setDebugApp(String packageName, boolean waitForDebugger,
5758 boolean persistent) {
5759 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5760 "setDebugApp()");
5761
5762 // Note that this is not really thread safe if there are multiple
5763 // callers into it at the same time, but that's not a situation we
5764 // care about.
5765 if (persistent) {
5766 final ContentResolver resolver = mContext.getContentResolver();
5767 Settings.System.putString(
5768 resolver, Settings.System.DEBUG_APP,
5769 packageName);
5770 Settings.System.putInt(
5771 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5772 waitForDebugger ? 1 : 0);
5773 }
5774
5775 synchronized (this) {
5776 if (!persistent) {
5777 mOrigDebugApp = mDebugApp;
5778 mOrigWaitForDebugger = mWaitForDebugger;
5779 }
5780 mDebugApp = packageName;
5781 mWaitForDebugger = waitForDebugger;
5782 mDebugTransient = !persistent;
5783 if (packageName != null) {
5784 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005785 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 Binder.restoreCallingIdentity(origId);
5787 }
5788 }
5789 }
5790
5791 public void setAlwaysFinish(boolean enabled) {
5792 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5793 "setAlwaysFinish()");
5794
5795 Settings.System.putInt(
5796 mContext.getContentResolver(),
5797 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5798
5799 synchronized (this) {
5800 mAlwaysFinishActivities = enabled;
5801 }
5802 }
5803
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005804 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005805 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005806 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005807 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005808 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 }
5810 }
5811
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005812 public boolean isUserAMonkey() {
5813 // For now the fact that there is a controller implies
5814 // we have a monkey.
5815 synchronized (this) {
5816 return mController != null;
5817 }
5818 }
5819
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005820 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005821 synchronized (this) {
5822 mWatchers.register(watcher);
5823 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005824 }
5825
5826 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005827 synchronized (this) {
5828 mWatchers.unregister(watcher);
5829 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005830 }
5831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 public final void enterSafeMode() {
5833 synchronized(this) {
5834 // It only makes sense to do this before the system is ready
5835 // and started launching other packages.
5836 if (!mSystemReady) {
5837 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005838 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005839 } catch (RemoteException e) {
5840 }
5841
5842 View v = LayoutInflater.from(mContext).inflate(
5843 com.android.internal.R.layout.safe_mode, null);
5844 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5845 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5846 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5847 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5848 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5849 lp.format = v.getBackground().getOpacity();
5850 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5851 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5852 ((WindowManager)mContext.getSystemService(
5853 Context.WINDOW_SERVICE)).addView(v, lp);
5854 }
5855 }
5856 }
5857
5858 public void noteWakeupAlarm(IIntentSender sender) {
5859 if (!(sender instanceof PendingIntentRecord)) {
5860 return;
5861 }
5862 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5863 synchronized (stats) {
5864 if (mBatteryStatsService.isOnBattery()) {
5865 mBatteryStatsService.enforceCallingPermission();
5866 PendingIntentRecord rec = (PendingIntentRecord)sender;
5867 int MY_UID = Binder.getCallingUid();
5868 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5869 BatteryStatsImpl.Uid.Pkg pkg =
5870 stats.getPackageStatsLocked(uid, rec.key.packageName);
5871 pkg.incWakeupsLocked();
5872 }
5873 }
5874 }
5875
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005876 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005878 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005880 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 // XXX Note: don't acquire main activity lock here, because the window
5882 // manager calls in with its locks held.
5883
5884 boolean killed = false;
5885 synchronized (mPidsSelfLocked) {
5886 int[] types = new int[pids.length];
5887 int worstType = 0;
5888 for (int i=0; i<pids.length; i++) {
5889 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5890 if (proc != null) {
5891 int type = proc.setAdj;
5892 types[i] = type;
5893 if (type > worstType) {
5894 worstType = type;
5895 }
5896 }
5897 }
5898
5899 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5900 // then constrain it so we will kill all hidden procs.
5901 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5902 worstType = HIDDEN_APP_MIN_ADJ;
5903 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005904 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 for (int i=0; i<pids.length; i++) {
5906 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5907 if (proc == null) {
5908 continue;
5909 }
5910 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005911 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005912 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005913 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5914 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005916 proc.killedBackground = true;
5917 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918 }
5919 }
5920 }
5921 return killed;
5922 }
5923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005924 public final void startRunning(String pkg, String cls, String action,
5925 String data) {
5926 synchronized(this) {
5927 if (mStartRunning) {
5928 return;
5929 }
5930 mStartRunning = true;
5931 mTopComponent = pkg != null && cls != null
5932 ? new ComponentName(pkg, cls) : null;
5933 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5934 mTopData = data;
5935 if (!mSystemReady) {
5936 return;
5937 }
5938 }
5939
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005940 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 }
5942
5943 private void retrieveSettings() {
5944 final ContentResolver resolver = mContext.getContentResolver();
5945 String debugApp = Settings.System.getString(
5946 resolver, Settings.System.DEBUG_APP);
5947 boolean waitForDebugger = Settings.System.getInt(
5948 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5949 boolean alwaysFinishActivities = Settings.System.getInt(
5950 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5951
5952 Configuration configuration = new Configuration();
5953 Settings.System.getConfiguration(resolver, configuration);
5954
5955 synchronized (this) {
5956 mDebugApp = mOrigDebugApp = debugApp;
5957 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5958 mAlwaysFinishActivities = alwaysFinishActivities;
5959 // This happens before any activities are started, so we can
5960 // change mConfiguration in-place.
5961 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005962 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005963 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 }
5965 }
5966
5967 public boolean testIsSystemReady() {
5968 // no need to synchronize(this) just to read & return the value
5969 return mSystemReady;
5970 }
5971
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005972 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005973 // In the simulator, startRunning will never have been called, which
5974 // normally sets a few crucial variables. Do it here instead.
5975 if (!Process.supportsProcesses()) {
5976 mStartRunning = true;
5977 mTopAction = Intent.ACTION_MAIN;
5978 }
5979
5980 synchronized(this) {
5981 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005982 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005983 return;
5984 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005985
5986 // Check to see if there are any update receivers to run.
5987 if (!mDidUpdate) {
5988 if (mWaitingUpdate) {
5989 return;
5990 }
5991 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5992 List<ResolveInfo> ris = null;
5993 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005994 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005995 intent, null, 0);
5996 } catch (RemoteException e) {
5997 }
5998 if (ris != null) {
5999 for (int i=ris.size()-1; i>=0; i--) {
6000 if ((ris.get(i).activityInfo.applicationInfo.flags
6001 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6002 ris.remove(i);
6003 }
6004 }
6005 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
6006 for (int i=0; i<ris.size(); i++) {
6007 ActivityInfo ai = ris.get(i).activityInfo;
6008 intent.setComponent(new ComponentName(ai.packageName, ai.name));
6009 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006010 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006011 finisher = new IIntentReceiver.Stub() {
6012 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006013 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006014 boolean sticky) {
6015 // The raw IIntentReceiver interface is called
6016 // with the AM lock held, so redispatch to
6017 // execute our code without the lock.
6018 mHandler.post(new Runnable() {
6019 public void run() {
6020 synchronized (ActivityManagerService.this) {
6021 mDidUpdate = true;
6022 }
6023 systemReady(goingCallback);
6024 }
6025 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006026 }
6027 };
6028 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006029 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006030 broadcastIntentLocked(null, null, intent, null, finisher,
6031 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006032 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006033 mWaitingUpdate = true;
6034 }
6035 }
6036 }
6037 if (mWaitingUpdate) {
6038 return;
6039 }
6040 mDidUpdate = true;
6041 }
6042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 mSystemReady = true;
6044 if (!mStartRunning) {
6045 return;
6046 }
6047 }
6048
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006049 ArrayList<ProcessRecord> procsToKill = null;
6050 synchronized(mPidsSelfLocked) {
6051 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6052 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6053 if (!isAllowedWhileBooting(proc.info)){
6054 if (procsToKill == null) {
6055 procsToKill = new ArrayList<ProcessRecord>();
6056 }
6057 procsToKill.add(proc);
6058 }
6059 }
6060 }
6061
6062 if (procsToKill != null) {
6063 synchronized(this) {
6064 for (int i=procsToKill.size()-1; i>=0; i--) {
6065 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006066 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006067 removeProcessLocked(proc, true);
6068 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07006069
6070 // Now that we have cleaned up any update processes, we
6071 // are ready to start launching real processes and know that
6072 // we won't trample on them any more.
6073 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006074 }
6075 }
6076
Joe Onorato8a9b2202010-02-26 18:56:32 -08006077 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006078 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 SystemClock.uptimeMillis());
6080
6081 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006082 // Make sure we have no pre-ready processes sitting around.
6083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6085 ResolveInfo ri = mContext.getPackageManager()
6086 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006087 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006088 CharSequence errorMsg = null;
6089 if (ri != null) {
6090 ActivityInfo ai = ri.activityInfo;
6091 ApplicationInfo app = ai.applicationInfo;
6092 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6093 mTopAction = Intent.ACTION_FACTORY_TEST;
6094 mTopData = null;
6095 mTopComponent = new ComponentName(app.packageName,
6096 ai.name);
6097 } else {
6098 errorMsg = mContext.getResources().getText(
6099 com.android.internal.R.string.factorytest_not_system);
6100 }
6101 } else {
6102 errorMsg = mContext.getResources().getText(
6103 com.android.internal.R.string.factorytest_no_action);
6104 }
6105 if (errorMsg != null) {
6106 mTopAction = null;
6107 mTopData = null;
6108 mTopComponent = null;
6109 Message msg = Message.obtain();
6110 msg.what = SHOW_FACTORY_ERROR_MSG;
6111 msg.getData().putCharSequence("msg", errorMsg);
6112 mHandler.sendMessage(msg);
6113 }
6114 }
6115 }
6116
6117 retrieveSettings();
6118
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006119 if (goingCallback != null) goingCallback.run();
6120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006121 synchronized (this) {
6122 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6123 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006124 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006125 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006126 if (apps != null) {
6127 int N = apps.size();
6128 int i;
6129 for (i=0; i<N; i++) {
6130 ApplicationInfo info
6131 = (ApplicationInfo)apps.get(i);
6132 if (info != null &&
6133 !info.packageName.equals("android")) {
6134 addAppLocked(info);
6135 }
6136 }
6137 }
6138 } catch (RemoteException ex) {
6139 // pm is in same process, this will never happen.
6140 }
6141 }
6142
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006143 // Start up initial activity.
6144 mBooting = true;
6145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006146 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006147 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 Message msg = Message.obtain();
6149 msg.what = SHOW_UID_ERROR_MSG;
6150 mHandler.sendMessage(msg);
6151 }
6152 } catch (RemoteException e) {
6153 }
6154
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006155 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006156 }
6157 }
6158
Dan Egnorb7f03672009-12-09 16:22:32 -08006159 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006160 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006161 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006162 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006163 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006164 startAppProblemLocked(app);
6165 app.stopFreezingAllLocked();
6166 return handleAppCrashLocked(app);
6167 }
6168
Dan Egnorb7f03672009-12-09 16:22:32 -08006169 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006170 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006171 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006172 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006173 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6174 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006175 startAppProblemLocked(app);
6176 app.stopFreezingAllLocked();
6177 }
6178
6179 /**
6180 * Generate a process error record, suitable for attachment to a ProcessRecord.
6181 *
6182 * @param app The ProcessRecord in which the error occurred.
6183 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6184 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006185 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 * @param shortMsg Short message describing the crash.
6187 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006188 * @param stackTrace Full crash stack trace, may be null.
6189 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006190 * @return Returns a fully-formed AppErrorStateInfo record.
6191 */
6192 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006193 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006194 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006196 report.condition = condition;
6197 report.processName = app.processName;
6198 report.pid = app.pid;
6199 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006200 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 report.shortMsg = shortMsg;
6202 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006203 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006204
6205 return report;
6206 }
6207
Dan Egnor42471dd2010-01-07 17:25:22 -08006208 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006209 synchronized (this) {
6210 app.crashing = false;
6211 app.crashingReport = null;
6212 app.notResponding = false;
6213 app.notRespondingReport = null;
6214 if (app.anrDialog == fromDialog) {
6215 app.anrDialog = null;
6216 }
6217 if (app.waitDialog == fromDialog) {
6218 app.waitDialog = null;
6219 }
6220 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006221 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006222 Slog.i(ActivityManagerService.TAG, "Killing "
6223 + app.processName + " (pid=" + app.pid + "): user's request");
6224 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6225 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006226 Process.killProcess(app.pid);
6227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006228 }
6229 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006230
Dan Egnorb7f03672009-12-09 16:22:32 -08006231 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006232 long now = SystemClock.uptimeMillis();
6233
6234 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6235 app.info.uid);
6236 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6237 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006238 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006239 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006240 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006241 app.info.processName, app.info.uid);
6242 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006243 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6244 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006245 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006246 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006247 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006248 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006249 }
6250 }
6251 if (!app.persistent) {
6252 // We don't want to start this process again until the user
6253 // explicitly does so... but for persistent process, we really
6254 // need to keep it running. If a persistent process is actually
6255 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006256 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006257 app.info.processName);
6258 mBadProcesses.put(app.info.processName, app.info.uid, now);
6259 app.bad = true;
6260 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6261 app.removed = true;
6262 removeProcessLocked(app, false);
6263 return false;
6264 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006265 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006266 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006267 if (r.app == app) {
6268 // If the top running activity is from this crashing
6269 // process, then terminate it to avoid getting in a loop.
6270 Slog.w(TAG, " Force finishing activity "
6271 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006272 int index = mMainStack.indexOfTokenLocked(r);
6273 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006274 Activity.RESULT_CANCELED, null, "crashed");
6275 // Also terminate an activities below it that aren't yet
6276 // stopped, to avoid a situation where one will get
6277 // re-start our crashing activity once it gets resumed again.
6278 index--;
6279 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006280 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006281 if (r.state == ActivityState.RESUMED
6282 || r.state == ActivityState.PAUSING
6283 || r.state == ActivityState.PAUSED) {
6284 if (!r.isHomeActivity) {
6285 Slog.w(TAG, " Force finishing activity "
6286 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006287 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006288 Activity.RESULT_CANCELED, null, "crashed");
6289 }
6290 }
6291 }
6292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 }
6294
6295 // Bump up the crash count of any services currently running in the proc.
6296 if (app.services.size() != 0) {
6297 // Any services running in the application need to be placed
6298 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006299 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006300 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006301 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 sr.crashCount++;
6303 }
6304 }
6305
6306 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6307 return true;
6308 }
6309
6310 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006311 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6312 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006313 skipCurrentReceiverLocked(app);
6314 }
6315
6316 void skipCurrentReceiverLocked(ProcessRecord app) {
6317 boolean reschedule = false;
6318 BroadcastRecord r = app.curReceiver;
6319 if (r != null) {
6320 // The current broadcast is waiting for this app's receiver
6321 // to be finished. Looks like that's not going to happen, so
6322 // let the broadcast continue.
6323 logBroadcastReceiverDiscard(r);
6324 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6325 r.resultExtras, r.resultAbort, true);
6326 reschedule = true;
6327 }
6328 r = mPendingBroadcast;
6329 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006330 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 "skip & discard pending app " + r);
6332 logBroadcastReceiverDiscard(r);
6333 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6334 r.resultExtras, r.resultAbort, true);
6335 reschedule = true;
6336 }
6337 if (reschedule) {
6338 scheduleBroadcastsLocked();
6339 }
6340 }
6341
Dan Egnor60d87622009-12-16 16:32:58 -08006342 /**
6343 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6344 * The application process will exit immediately after this call returns.
6345 * @param app object of the crashing app, null for the system server
6346 * @param crashInfo describing the exception
6347 */
6348 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6349 ProcessRecord r = findAppProcess(app);
6350
6351 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6352 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006353 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006354 crashInfo.exceptionClassName,
6355 crashInfo.exceptionMessage,
6356 crashInfo.throwFileName,
6357 crashInfo.throwLineNumber);
6358
Dan Egnor42471dd2010-01-07 17:25:22 -08006359 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006360
6361 crashApplication(r, crashInfo);
6362 }
6363
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006364 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006365 IBinder app,
6366 int violationMask,
6367 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006368 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006369
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006370 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006371 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006372 boolean logIt = true;
6373 synchronized (mAlreadyLoggedViolatedStacks) {
6374 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6375 logIt = false;
6376 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006377 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006378 // the relative pain numbers, without logging all
6379 // the stack traces repeatedly. We'd want to do
6380 // likewise in the client code, which also does
6381 // dup suppression, before the Binder call.
6382 } else {
6383 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6384 mAlreadyLoggedViolatedStacks.clear();
6385 }
6386 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6387 }
6388 }
6389 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006390 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006391 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006392 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006393
6394 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6395 AppErrorResult result = new AppErrorResult();
6396 synchronized (this) {
6397 final long origId = Binder.clearCallingIdentity();
6398
6399 Message msg = Message.obtain();
6400 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6401 HashMap<String, Object> data = new HashMap<String, Object>();
6402 data.put("result", result);
6403 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006404 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006405 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006406 msg.obj = data;
6407 mHandler.sendMessage(msg);
6408
6409 Binder.restoreCallingIdentity(origId);
6410 }
6411 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006412 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006413 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006414 }
6415
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006416 // Depending on the policy in effect, there could be a bunch of
6417 // these in quick succession so we try to batch these together to
6418 // minimize disk writes, number of dropbox entries, and maximize
6419 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006420 private void logStrictModeViolationToDropBox(
6421 ProcessRecord process,
6422 StrictMode.ViolationInfo info) {
6423 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006424 return;
6425 }
6426 final boolean isSystemApp = process == null ||
6427 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6428 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6429 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6430 final DropBoxManager dbox = (DropBoxManager)
6431 mContext.getSystemService(Context.DROPBOX_SERVICE);
6432
6433 // Exit early if the dropbox isn't configured to accept this report type.
6434 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6435
6436 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006437 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006438 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6439 synchronized (sb) {
6440 bufferWasEmpty = sb.length() == 0;
6441 appendDropBoxProcessHeaders(process, sb);
6442 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6443 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006444 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6445 if (info.violationNumThisLoop != 0) {
6446 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6447 }
6448 if (info != null && info.durationMillis != -1) {
6449 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006450 }
6451 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006452 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6453 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006454 }
6455 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006456
6457 // Only buffer up to ~64k. Various logging bits truncate
6458 // things at 128k.
6459 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006460 }
6461
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006462 // Flush immediately if the buffer's grown too large, or this
6463 // is a non-system app. Non-system apps are isolated with a
6464 // different tag & policy and not batched.
6465 //
6466 // Batching is useful during internal testing with
6467 // StrictMode settings turned up high. Without batching,
6468 // thousands of separate files could be created on boot.
6469 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006470 new Thread("Error dump: " + dropboxTag) {
6471 @Override
6472 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006473 String report;
6474 synchronized (sb) {
6475 report = sb.toString();
6476 sb.delete(0, sb.length());
6477 sb.trimToSize();
6478 }
6479 if (report.length() != 0) {
6480 dbox.addText(dropboxTag, report);
6481 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006482 }
6483 }.start();
6484 return;
6485 }
6486
6487 // System app batching:
6488 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006489 // An existing dropbox-writing thread is outstanding, so
6490 // we don't need to start it up. The existing thread will
6491 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006492 return;
6493 }
6494
6495 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6496 // (After this point, we shouldn't access AMS internal data structures.)
6497 new Thread("Error dump: " + dropboxTag) {
6498 @Override
6499 public void run() {
6500 // 5 second sleep to let stacks arrive and be batched together
6501 try {
6502 Thread.sleep(5000); // 5 seconds
6503 } catch (InterruptedException e) {}
6504
6505 String errorReport;
6506 synchronized (mStrictModeBuffer) {
6507 errorReport = mStrictModeBuffer.toString();
6508 if (errorReport.length() == 0) {
6509 return;
6510 }
6511 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6512 mStrictModeBuffer.trimToSize();
6513 }
6514 dbox.addText(dropboxTag, errorReport);
6515 }
6516 }.start();
6517 }
6518
Dan Egnor60d87622009-12-16 16:32:58 -08006519 /**
6520 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6521 * @param app object of the crashing app, null for the system server
6522 * @param tag reported by the caller
6523 * @param crashInfo describing the context of the error
6524 * @return true if the process should exit immediately (WTF is fatal)
6525 */
6526 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006527 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006528 ProcessRecord r = findAppProcess(app);
6529
6530 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6531 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006532 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006533 tag, crashInfo.exceptionMessage);
6534
Dan Egnor42471dd2010-01-07 17:25:22 -08006535 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006536
Doug Zongker43866e02010-01-07 12:09:54 -08006537 if (Settings.Secure.getInt(mContext.getContentResolver(),
6538 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006539 crashApplication(r, crashInfo);
6540 return true;
6541 } else {
6542 return false;
6543 }
6544 }
6545
6546 /**
6547 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6548 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6549 */
6550 private ProcessRecord findAppProcess(IBinder app) {
6551 if (app == null) {
6552 return null;
6553 }
6554
6555 synchronized (this) {
6556 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6557 final int NA = apps.size();
6558 for (int ia=0; ia<NA; ia++) {
6559 ProcessRecord p = apps.valueAt(ia);
6560 if (p.thread != null && p.thread.asBinder() == app) {
6561 return p;
6562 }
6563 }
6564 }
6565
Joe Onorato8a9b2202010-02-26 18:56:32 -08006566 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006567 return null;
6568 }
6569 }
6570
6571 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006572 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6573 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006574 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006575 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6576 // Note: ProcessRecord 'process' is guarded by the service
6577 // instance. (notably process.pkgList, which could otherwise change
6578 // concurrently during execution of this method)
6579 synchronized (this) {
6580 if (process == null || process.pid == MY_PID) {
6581 sb.append("Process: system_server\n");
6582 } else {
6583 sb.append("Process: ").append(process.processName).append("\n");
6584 }
6585 if (process == null) {
6586 return;
6587 }
Dan Egnora455d192010-03-12 08:52:28 -08006588 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006589 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006590 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6591 for (String pkg : process.pkgList) {
6592 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006593 try {
Dan Egnora455d192010-03-12 08:52:28 -08006594 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6595 if (pi != null) {
6596 sb.append(" v").append(pi.versionCode);
6597 if (pi.versionName != null) {
6598 sb.append(" (").append(pi.versionName).append(")");
6599 }
6600 }
6601 } catch (RemoteException e) {
6602 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006603 }
Dan Egnora455d192010-03-12 08:52:28 -08006604 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006605 }
Dan Egnora455d192010-03-12 08:52:28 -08006606 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006607 }
6608
6609 private static String processClass(ProcessRecord process) {
6610 if (process == null || process.pid == MY_PID) {
6611 return "system_server";
6612 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6613 return "system_app";
6614 } else {
6615 return "data_app";
6616 }
6617 }
6618
6619 /**
6620 * Write a description of an error (crash, WTF, ANR) to the drop box.
6621 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6622 * @param process which caused the error, null means the system server
6623 * @param activity which triggered the error, null if unknown
6624 * @param parent activity related to the error, null if unknown
6625 * @param subject line related to the error, null if absent
6626 * @param report in long form describing the error, null if absent
6627 * @param logFile to include in the report, null if none
6628 * @param crashInfo giving an application stack trace, null if absent
6629 */
6630 public void addErrorToDropBox(String eventType,
6631 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6632 final String report, final File logFile,
6633 final ApplicationErrorReport.CrashInfo crashInfo) {
6634 // NOTE -- this must never acquire the ActivityManagerService lock,
6635 // otherwise the watchdog may be prevented from resetting the system.
6636
6637 final String dropboxTag = processClass(process) + "_" + eventType;
6638 final DropBoxManager dbox = (DropBoxManager)
6639 mContext.getSystemService(Context.DROPBOX_SERVICE);
6640
6641 // Exit early if the dropbox isn't configured to accept this report type.
6642 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6643
6644 final StringBuilder sb = new StringBuilder(1024);
6645 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006646 if (activity != null) {
6647 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6648 }
6649 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6650 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6651 }
6652 if (parent != null && parent != activity) {
6653 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6654 }
6655 if (subject != null) {
6656 sb.append("Subject: ").append(subject).append("\n");
6657 }
6658 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6659 sb.append("\n");
6660
6661 // Do the rest in a worker thread to avoid blocking the caller on I/O
6662 // (After this point, we shouldn't access AMS internal data structures.)
6663 Thread worker = new Thread("Error dump: " + dropboxTag) {
6664 @Override
6665 public void run() {
6666 if (report != null) {
6667 sb.append(report);
6668 }
6669 if (logFile != null) {
6670 try {
6671 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6672 } catch (IOException e) {
6673 Slog.e(TAG, "Error reading " + logFile, e);
6674 }
6675 }
6676 if (crashInfo != null && crashInfo.stackTrace != null) {
6677 sb.append(crashInfo.stackTrace);
6678 }
6679
6680 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6681 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6682 if (lines > 0) {
6683 sb.append("\n");
6684
6685 // Merge several logcat streams, and take the last N lines
6686 InputStreamReader input = null;
6687 try {
6688 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6689 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6690 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6691
6692 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6693 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6694 input = new InputStreamReader(logcat.getInputStream());
6695
6696 int num;
6697 char[] buf = new char[8192];
6698 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6699 } catch (IOException e) {
6700 Slog.e(TAG, "Error running logcat", e);
6701 } finally {
6702 if (input != null) try { input.close(); } catch (IOException e) {}
6703 }
6704 }
6705
6706 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006707 }
Dan Egnora455d192010-03-12 08:52:28 -08006708 };
6709
6710 if (process == null || process.pid == MY_PID) {
6711 worker.run(); // We may be about to die -- need to run this synchronously
6712 } else {
6713 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006714 }
6715 }
6716
6717 /**
6718 * Bring up the "unexpected error" dialog box for a crashing app.
6719 * Deal with edge cases (intercepts from instrumented applications,
6720 * ActivityController, error intent receivers, that sort of thing).
6721 * @param r the application crashing
6722 * @param crashInfo describing the failure
6723 */
6724 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006725 long timeMillis = System.currentTimeMillis();
6726 String shortMsg = crashInfo.exceptionClassName;
6727 String longMsg = crashInfo.exceptionMessage;
6728 String stackTrace = crashInfo.stackTrace;
6729 if (shortMsg != null && longMsg != null) {
6730 longMsg = shortMsg + ": " + longMsg;
6731 } else if (shortMsg != null) {
6732 longMsg = shortMsg;
6733 }
6734
Dan Egnor60d87622009-12-16 16:32:58 -08006735 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006736 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006737 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006738 try {
6739 String name = r != null ? r.processName : null;
6740 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006741 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006742 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006743 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006744 + " at watcher's request");
6745 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006746 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006747 }
6748 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006749 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006750 }
6751 }
6752
6753 final long origId = Binder.clearCallingIdentity();
6754
6755 // If this process is running instrumentation, finish it.
6756 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006757 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006758 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006759 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6760 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006761 Bundle info = new Bundle();
6762 info.putString("shortMsg", shortMsg);
6763 info.putString("longMsg", longMsg);
6764 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6765 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006766 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006767 }
6768
Dan Egnor60d87622009-12-16 16:32:58 -08006769 // If we can't identify the process or it's already exceeded its crash quota,
6770 // quit right away without showing a crash dialog.
6771 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006773 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 }
6775
6776 Message msg = Message.obtain();
6777 msg.what = SHOW_ERROR_MSG;
6778 HashMap data = new HashMap();
6779 data.put("result", result);
6780 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006781 msg.obj = data;
6782 mHandler.sendMessage(msg);
6783
6784 Binder.restoreCallingIdentity(origId);
6785 }
6786
6787 int res = result.get();
6788
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006789 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006790 synchronized (this) {
6791 if (r != null) {
6792 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6793 SystemClock.uptimeMillis());
6794 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006795 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006796 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006797 }
6798 }
6799
6800 if (appErrorIntent != null) {
6801 try {
6802 mContext.startActivity(appErrorIntent);
6803 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006804 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006807 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006808
6809 Intent createAppErrorIntentLocked(ProcessRecord r,
6810 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6811 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006812 if (report == null) {
6813 return null;
6814 }
6815 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6816 result.setComponent(r.errorReportReceiver);
6817 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6818 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6819 return result;
6820 }
6821
Dan Egnorb7f03672009-12-09 16:22:32 -08006822 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6823 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006824 if (r.errorReportReceiver == null) {
6825 return null;
6826 }
6827
6828 if (!r.crashing && !r.notResponding) {
6829 return null;
6830 }
6831
Dan Egnorb7f03672009-12-09 16:22:32 -08006832 ApplicationErrorReport report = new ApplicationErrorReport();
6833 report.packageName = r.info.packageName;
6834 report.installerPackageName = r.errorReportReceiver.getPackageName();
6835 report.processName = r.processName;
6836 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006837 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006838
Dan Egnorb7f03672009-12-09 16:22:32 -08006839 if (r.crashing) {
6840 report.type = ApplicationErrorReport.TYPE_CRASH;
6841 report.crashInfo = crashInfo;
6842 } else if (r.notResponding) {
6843 report.type = ApplicationErrorReport.TYPE_ANR;
6844 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006845
Dan Egnorb7f03672009-12-09 16:22:32 -08006846 report.anrInfo.activity = r.notRespondingReport.tag;
6847 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6848 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006849 }
6850
Dan Egnorb7f03672009-12-09 16:22:32 -08006851 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006852 }
6853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6855 // assume our apps are happy - lazy create the list
6856 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6857
6858 synchronized (this) {
6859
6860 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006861 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6862 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006863 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6864 // This one's in trouble, so we'll generate a report for it
6865 // crashes are higher priority (in case there's a crash *and* an anr)
6866 ActivityManager.ProcessErrorStateInfo report = null;
6867 if (app.crashing) {
6868 report = app.crashingReport;
6869 } else if (app.notResponding) {
6870 report = app.notRespondingReport;
6871 }
6872
6873 if (report != null) {
6874 if (errList == null) {
6875 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6876 }
6877 errList.add(report);
6878 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006879 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006880 " crashing = " + app.crashing +
6881 " notResponding = " + app.notResponding);
6882 }
6883 }
6884 }
6885 }
6886
6887 return errList;
6888 }
6889
6890 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6891 // Lazy instantiation of list
6892 List<ActivityManager.RunningAppProcessInfo> runList = null;
6893 synchronized (this) {
6894 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006895 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6896 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006897 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6898 // Generate process state info for running application
6899 ActivityManager.RunningAppProcessInfo currApp =
6900 new ActivityManager.RunningAppProcessInfo(app.processName,
6901 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006902 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006903 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07006904 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006907 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006908 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6909 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6910 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006911 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6912 } else if (adj >= HOME_APP_ADJ) {
6913 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6914 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006915 } else if (adj >= SECONDARY_SERVER_ADJ) {
6916 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006917 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6918 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6919 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6920 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006921 } else if (adj >= VISIBLE_APP_ADJ) {
6922 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6923 } else {
6924 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6925 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006926 currApp.importanceReasonCode = app.adjTypeCode;
6927 if (app.adjSource instanceof ProcessRecord) {
6928 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006929 } else if (app.adjSource instanceof ActivityRecord) {
6930 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006931 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6932 }
6933 if (app.adjTarget instanceof ComponentName) {
6934 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6935 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006936 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 // + " lru=" + currApp.lru);
6938 if (runList == null) {
6939 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6940 }
6941 runList.add(currApp);
6942 }
6943 }
6944 }
6945 return runList;
6946 }
6947
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006948 public List<ApplicationInfo> getRunningExternalApplications() {
6949 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6950 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6951 if (runningApps != null && runningApps.size() > 0) {
6952 Set<String> extList = new HashSet<String>();
6953 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6954 if (app.pkgList != null) {
6955 for (String pkg : app.pkgList) {
6956 extList.add(pkg);
6957 }
6958 }
6959 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006960 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006961 for (String pkg : extList) {
6962 try {
6963 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6964 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6965 retList.add(info);
6966 }
6967 } catch (RemoteException e) {
6968 }
6969 }
6970 }
6971 return retList;
6972 }
6973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974 @Override
6975 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006976 if (checkCallingPermission(android.Manifest.permission.DUMP)
6977 != PackageManager.PERMISSION_GRANTED) {
6978 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6979 + Binder.getCallingPid()
6980 + ", uid=" + Binder.getCallingUid()
6981 + " without permission "
6982 + android.Manifest.permission.DUMP);
6983 return;
6984 }
6985
6986 boolean dumpAll = false;
6987
6988 int opti = 0;
6989 while (opti < args.length) {
6990 String opt = args[opti];
6991 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6992 break;
6993 }
6994 opti++;
6995 if ("-a".equals(opt)) {
6996 dumpAll = true;
6997 } else if ("-h".equals(opt)) {
6998 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006999 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007000 pw.println(" cmd may be one of:");
7001 pw.println(" activities: activity stack state");
7002 pw.println(" broadcasts: broadcast state");
7003 pw.println(" intents: pending intent state");
7004 pw.println(" processes: process state");
7005 pw.println(" providers: content provider state");
7006 pw.println(" services: service state");
7007 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007008 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007009 } else {
7010 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007012 }
7013
7014 // Is the caller requesting to dump a particular piece of data?
7015 if (opti < args.length) {
7016 String cmd = args[opti];
7017 opti++;
7018 if ("activities".equals(cmd) || "a".equals(cmd)) {
7019 synchronized (this) {
7020 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007022 return;
7023 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7024 synchronized (this) {
7025 dumpBroadcastsLocked(fd, pw, args, opti, true);
7026 }
7027 return;
7028 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7029 synchronized (this) {
7030 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7031 }
7032 return;
7033 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7034 synchronized (this) {
7035 dumpProcessesLocked(fd, pw, args, opti, true);
7036 }
7037 return;
7038 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7039 synchronized (this) {
7040 dumpProvidersLocked(fd, pw, args, opti, true);
7041 }
7042 return;
7043 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007044 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007045 return;
7046 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7047 synchronized (this) {
7048 dumpServicesLocked(fd, pw, args, opti, true);
7049 }
7050 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007051 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007052 }
7053
7054 // No piece of data specified, dump everything.
7055 synchronized (this) {
7056 boolean needSep;
7057 if (dumpAll) {
7058 pw.println("Providers in Current Activity Manager State:");
7059 }
7060 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7061 if (needSep) {
7062 pw.println(" ");
7063 }
7064 if (dumpAll) {
7065 pw.println("-------------------------------------------------------------------------------");
7066 pw.println("Broadcasts in Current Activity Manager State:");
7067 }
7068 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7069 if (needSep) {
7070 pw.println(" ");
7071 }
7072 if (dumpAll) {
7073 pw.println("-------------------------------------------------------------------------------");
7074 pw.println("Services in Current Activity Manager State:");
7075 }
7076 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7077 if (needSep) {
7078 pw.println(" ");
7079 }
7080 if (dumpAll) {
7081 pw.println("-------------------------------------------------------------------------------");
7082 pw.println("PendingIntents in Current Activity Manager State:");
7083 }
7084 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7085 if (needSep) {
7086 pw.println(" ");
7087 }
7088 if (dumpAll) {
7089 pw.println("-------------------------------------------------------------------------------");
7090 pw.println("Activities in Current Activity Manager State:");
7091 }
7092 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7093 if (needSep) {
7094 pw.println(" ");
7095 }
7096 if (dumpAll) {
7097 pw.println("-------------------------------------------------------------------------------");
7098 pw.println("Processes in Current Activity Manager State:");
7099 }
7100 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7101 }
7102 }
7103
7104 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7105 int opti, boolean dumpAll, boolean needHeader) {
7106 if (needHeader) {
7107 pw.println(" Activity stack:");
7108 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007109 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007110 pw.println(" ");
7111 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007112 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7113 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007115 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007116 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007117 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007118 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007119 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007120 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007121 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007122 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007123 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007124 pw.println(" ");
7125 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007126 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007128
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007129 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007130 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7131 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007132 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007133 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007134
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007135 if (dumpAll && mRecentTasks.size() > 0) {
7136 pw.println(" ");
7137 pw.println("Recent tasks in Current Activity Manager State:");
7138
7139 final int N = mRecentTasks.size();
7140 for (int i=0; i<N; i++) {
7141 TaskRecord tr = mRecentTasks.get(i);
7142 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7143 pw.println(tr);
7144 mRecentTasks.get(i).dump(pw, " ");
7145 }
7146 }
7147
7148 pw.println(" ");
7149 pw.println(" mCurTask: " + mCurTask);
7150
7151 return true;
7152 }
7153
7154 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7155 int opti, boolean dumpAll) {
7156 boolean needSep = false;
7157 int numPers = 0;
7158
7159 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007160 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7161 final int NA = procs.size();
7162 for (int ia=0; ia<NA; ia++) {
7163 if (!needSep) {
7164 pw.println(" All known processes:");
7165 needSep = true;
7166 }
7167 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007168 pw.print(r.persistent ? " *PERS*" : " *APP*");
7169 pw.print(" UID "); pw.print(procs.keyAt(ia));
7170 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007171 r.dump(pw, " ");
7172 if (r.persistent) {
7173 numPers++;
7174 }
7175 }
7176 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007177 }
7178
7179 if (mLruProcesses.size() > 0) {
7180 if (needSep) pw.println(" ");
7181 needSep = true;
7182 pw.println(" Running processes (most recent first):");
7183 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007184 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007185 needSep = true;
7186 }
7187
7188 synchronized (mPidsSelfLocked) {
7189 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007190 if (needSep) pw.println(" ");
7191 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007192 pw.println(" PID mappings:");
7193 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7194 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7195 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007196 }
7197 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007198 }
7199
7200 if (mForegroundProcesses.size() > 0) {
7201 if (needSep) pw.println(" ");
7202 needSep = true;
7203 pw.println(" Foreground Processes:");
7204 for (int i=0; i<mForegroundProcesses.size(); i++) {
7205 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7206 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007208 }
7209
7210 if (mPersistentStartingProcesses.size() > 0) {
7211 if (needSep) pw.println(" ");
7212 needSep = true;
7213 pw.println(" Persisent processes that are starting:");
7214 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
7215 "Starting Norm", "Restarting PERS", false);
7216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007218 if (mStartingProcesses.size() > 0) {
7219 if (needSep) pw.println(" ");
7220 needSep = true;
7221 pw.println(" Processes that are starting:");
7222 dumpProcessList(pw, this, mStartingProcesses, " ",
7223 "Starting Norm", "Starting PERS", false);
7224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007226 if (mRemovedProcesses.size() > 0) {
7227 if (needSep) pw.println(" ");
7228 needSep = true;
7229 pw.println(" Processes that are being removed:");
7230 dumpProcessList(pw, this, mRemovedProcesses, " ",
7231 "Removed Norm", "Removed PERS", false);
7232 }
7233
7234 if (mProcessesOnHold.size() > 0) {
7235 if (needSep) pw.println(" ");
7236 needSep = true;
7237 pw.println(" Processes that are on old until the system is ready:");
7238 dumpProcessList(pw, this, mProcessesOnHold, " ",
7239 "OnHold Norm", "OnHold PERS", false);
7240 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007242 if (mProcessesToGc.size() > 0) {
7243 if (needSep) pw.println(" ");
7244 needSep = true;
7245 pw.println(" Processes that are waiting to GC:");
7246 long now = SystemClock.uptimeMillis();
7247 for (int i=0; i<mProcessesToGc.size(); i++) {
7248 ProcessRecord proc = mProcessesToGc.get(i);
7249 pw.print(" Process "); pw.println(proc);
7250 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7251 pw.print(", last gced=");
7252 pw.print(now-proc.lastRequestedGc);
7253 pw.print(" ms ago, last lowMem=");
7254 pw.print(now-proc.lastLowMemory);
7255 pw.println(" ms ago");
7256
7257 }
7258 }
7259
7260 if (mProcessCrashTimes.getMap().size() > 0) {
7261 if (needSep) pw.println(" ");
7262 needSep = true;
7263 pw.println(" Time since processes crashed:");
7264 long now = SystemClock.uptimeMillis();
7265 for (Map.Entry<String, SparseArray<Long>> procs
7266 : mProcessCrashTimes.getMap().entrySet()) {
7267 SparseArray<Long> uids = procs.getValue();
7268 final int N = uids.size();
7269 for (int i=0; i<N; i++) {
7270 pw.print(" Process "); pw.print(procs.getKey());
7271 pw.print(" uid "); pw.print(uids.keyAt(i));
7272 pw.print(": last crashed ");
7273 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007274 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007275 }
7276 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007278
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007279 if (mBadProcesses.getMap().size() > 0) {
7280 if (needSep) pw.println(" ");
7281 needSep = true;
7282 pw.println(" Bad processes:");
7283 for (Map.Entry<String, SparseArray<Long>> procs
7284 : mBadProcesses.getMap().entrySet()) {
7285 SparseArray<Long> uids = procs.getValue();
7286 final int N = uids.size();
7287 for (int i=0; i<N; i++) {
7288 pw.print(" Bad process "); pw.print(procs.getKey());
7289 pw.print(" uid "); pw.print(uids.keyAt(i));
7290 pw.print(": crashed at time ");
7291 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007292 }
7293 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007296 pw.println(" ");
7297 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007298 if (mHeavyWeightProcess != null) {
7299 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7300 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007301 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007302 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007303 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7304 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7305 || mOrigWaitForDebugger) {
7306 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7307 + " mDebugTransient=" + mDebugTransient
7308 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7309 }
7310 if (mAlwaysFinishActivities || mController != null) {
7311 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7312 + " mController=" + mController);
7313 }
7314 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007317 + " mProcessesReady=" + mProcessesReady
7318 + " mSystemReady=" + mSystemReady);
7319 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 + " mBooted=" + mBooted
7321 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007322 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7323 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007324 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007325 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007326
7327 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007328 }
7329
7330 /**
7331 * There are three ways to call this:
7332 * - no service specified: dump all the services
7333 * - a flattened component name that matched an existing service was specified as the
7334 * first arg: dump that one service
7335 * - the first arg isn't the flattened component name of an existing service:
7336 * dump all services whose component contains the first arg as a substring
7337 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007338 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7339 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007340 String[] newArgs;
7341 String componentNameString;
7342 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007343 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007344 componentNameString = null;
7345 newArgs = EMPTY_STRING_ARRAY;
7346 r = null;
7347 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007348 componentNameString = args[opti];
7349 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007351 synchronized (this) {
7352 r = componentName != null ? mServices.get(componentName) : null;
7353 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007354 newArgs = new String[args.length - opti];
7355 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 }
7357
7358 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007359 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007361 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7362 synchronized (this) {
7363 for (ServiceRecord r1 : mServices.values()) {
7364 if (componentNameString == null
7365 || r1.name.flattenToString().contains(componentNameString)) {
7366 services.add(r1);
7367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 }
7369 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007370 for (int i=0; i<services.size(); i++) {
7371 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007373 }
7374 }
7375
7376 /**
7377 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7378 * there is a thread associated with the service.
7379 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007380 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7381 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007383 if (dumpAll) {
7384 synchronized (this) {
7385 pw.print(" * "); pw.println(r);
7386 r.dump(pw, " ");
7387 }
7388 pw.println("");
7389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 if (r.app != null && r.app.thread != null) {
7391 try {
7392 // flush anything that is already in the PrintWriter since the thread is going
7393 // to write to the file descriptor directly
7394 pw.flush();
7395 r.app.thread.dumpService(fd, r, args);
7396 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007397 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 } catch (RemoteException e) {
7399 pw.println("got a RemoteException while dumping the service");
7400 }
7401 }
7402 }
7403
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007404 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7405 int opti, boolean dumpAll) {
7406 boolean needSep = false;
7407
7408 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409 if (mRegisteredReceivers.size() > 0) {
7410 pw.println(" ");
7411 pw.println(" Registered Receivers:");
7412 Iterator it = mRegisteredReceivers.values().iterator();
7413 while (it.hasNext()) {
7414 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007415 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007416 r.dump(pw, " ");
7417 }
7418 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007420 pw.println(" ");
7421 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007422 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007423 needSep = true;
7424 }
7425
7426 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7427 || mPendingBroadcast != null) {
7428 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007429 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007430 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007432 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7433 pw.println(" Broadcast #" + i + ":");
7434 mParallelBroadcasts.get(i).dump(pw, " ");
7435 }
7436 if (mOrderedBroadcasts.size() > 0) {
7437 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007438 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007439 }
7440 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7441 pw.println(" Serialized Broadcast #" + i + ":");
7442 mOrderedBroadcasts.get(i).dump(pw, " ");
7443 }
7444 pw.println(" ");
7445 pw.println(" Pending broadcast:");
7446 if (mPendingBroadcast != null) {
7447 mPendingBroadcast.dump(pw, " ");
7448 } else {
7449 pw.println(" (null)");
7450 }
7451 needSep = true;
7452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007453
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007454 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007456 pw.println(" Historical broadcasts:");
7457 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7458 BroadcastRecord r = mBroadcastHistory[i];
7459 if (r == null) {
7460 break;
7461 }
7462 pw.println(" Historical Broadcast #" + i + ":");
7463 r.dump(pw, " ");
7464 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007465 needSep = true;
7466 }
7467
7468 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007469 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007470 pw.println(" Sticky broadcasts:");
7471 StringBuilder sb = new StringBuilder(128);
7472 for (Map.Entry<String, ArrayList<Intent>> ent
7473 : mStickyBroadcasts.entrySet()) {
7474 pw.print(" * Sticky action "); pw.print(ent.getKey());
7475 pw.println(":");
7476 ArrayList<Intent> intents = ent.getValue();
7477 final int N = intents.size();
7478 for (int i=0; i<N; i++) {
7479 sb.setLength(0);
7480 sb.append(" Intent: ");
7481 intents.get(i).toShortString(sb, true, false);
7482 pw.println(sb.toString());
7483 Bundle bundle = intents.get(i).getExtras();
7484 if (bundle != null) {
7485 pw.print(" ");
7486 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 }
7488 }
7489 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007490 needSep = true;
7491 }
7492
7493 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007495 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007496 pw.println(" mHandler:");
7497 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007498 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007499 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007500
7501 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502 }
7503
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007504 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7505 int opti, boolean dumpAll) {
7506 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007507
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007508 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007509 if (mServices.size() > 0) {
7510 pw.println(" Active services:");
7511 Iterator<ServiceRecord> it = mServices.values().iterator();
7512 while (it.hasNext()) {
7513 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007514 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 r.dump(pw, " ");
7516 }
7517 needSep = true;
7518 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007520
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007521 if (mPendingServices.size() > 0) {
7522 if (needSep) pw.println(" ");
7523 pw.println(" Pending services:");
7524 for (int i=0; i<mPendingServices.size(); i++) {
7525 ServiceRecord r = mPendingServices.get(i);
7526 pw.print(" * Pending "); pw.println(r);
7527 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007529 needSep = true;
7530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007532 if (mRestartingServices.size() > 0) {
7533 if (needSep) pw.println(" ");
7534 pw.println(" Restarting services:");
7535 for (int i=0; i<mRestartingServices.size(); i++) {
7536 ServiceRecord r = mRestartingServices.get(i);
7537 pw.print(" * Restarting "); pw.println(r);
7538 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007539 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007540 needSep = true;
7541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007543 if (mStoppingServices.size() > 0) {
7544 if (needSep) pw.println(" ");
7545 pw.println(" Stopping services:");
7546 for (int i=0; i<mStoppingServices.size(); i++) {
7547 ServiceRecord r = mStoppingServices.get(i);
7548 pw.print(" * Stopping "); pw.println(r);
7549 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007550 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007551 needSep = true;
7552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007553
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007554 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007555 if (mServiceConnections.size() > 0) {
7556 if (needSep) pw.println(" ");
7557 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007558 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 = mServiceConnections.values().iterator();
7560 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007561 ArrayList<ConnectionRecord> r = it.next();
7562 for (int i=0; i<r.size(); i++) {
7563 pw.print(" * "); pw.println(r.get(i));
7564 r.get(i).dump(pw, " ");
7565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007566 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007567 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 }
7569 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007570
7571 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007572 }
7573
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007574 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7575 int opti, boolean dumpAll) {
7576 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007577
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007578 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 if (mProvidersByClass.size() > 0) {
7580 if (needSep) pw.println(" ");
7581 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007582 Iterator<Map.Entry<String, ContentProviderRecord>> it
7583 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007584 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007585 Map.Entry<String, ContentProviderRecord> e = it.next();
7586 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007587 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007588 r.dump(pw, " ");
7589 }
7590 needSep = true;
7591 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007592
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007593 if (mProvidersByName.size() > 0) {
7594 pw.println(" ");
7595 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007596 Iterator<Map.Entry<String, ContentProviderRecord>> it
7597 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007598 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007599 Map.Entry<String, ContentProviderRecord> e = it.next();
7600 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007601 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7602 pw.println(r);
7603 }
7604 needSep = true;
7605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007607
7608 if (mLaunchingProviders.size() > 0) {
7609 if (needSep) pw.println(" ");
7610 pw.println(" Launching content providers:");
7611 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7612 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7613 pw.println(mLaunchingProviders.get(i));
7614 }
7615 needSep = true;
7616 }
7617
7618 if (mGrantedUriPermissions.size() > 0) {
7619 pw.println();
7620 pw.println("Granted Uri Permissions:");
7621 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7622 int uid = mGrantedUriPermissions.keyAt(i);
7623 HashMap<Uri, UriPermission> perms
7624 = mGrantedUriPermissions.valueAt(i);
7625 pw.print(" * UID "); pw.print(uid);
7626 pw.println(" holds:");
7627 for (UriPermission perm : perms.values()) {
7628 pw.print(" "); pw.println(perm);
7629 perm.dump(pw, " ");
7630 }
7631 }
7632 needSep = true;
7633 }
7634
7635 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636 }
7637
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007638 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7639 int opti, boolean dumpAll) {
7640 boolean needSep = false;
7641
7642 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007643 if (this.mIntentSenderRecords.size() > 0) {
7644 Iterator<WeakReference<PendingIntentRecord>> it
7645 = mIntentSenderRecords.values().iterator();
7646 while (it.hasNext()) {
7647 WeakReference<PendingIntentRecord> ref = it.next();
7648 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007649 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007651 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 rec.dump(pw, " ");
7653 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007654 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007655 }
7656 }
7657 }
7658 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007659
7660 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007661 }
7662
7663 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007664 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 TaskRecord lastTask = null;
7666 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007667 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007668 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 if (lastTask != r.task) {
7670 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007671 pw.print(prefix);
7672 pw.print(full ? "* " : " ");
7673 pw.println(lastTask);
7674 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007675 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007676 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007678 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7679 pw.print(" #"); pw.print(i); pw.print(": ");
7680 pw.println(r);
7681 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007682 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 }
7685 }
7686
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007687 private static String buildOomTag(String prefix, String space, int val, int base) {
7688 if (val == base) {
7689 if (space == null) return prefix;
7690 return prefix + " ";
7691 }
7692 return prefix + "+" + Integer.toString(val-base);
7693 }
7694
7695 private static final int dumpProcessList(PrintWriter pw,
7696 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 String prefix, String normalLabel, String persistentLabel,
7698 boolean inclOomAdj) {
7699 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007700 final int N = list.size()-1;
7701 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702 ProcessRecord r = (ProcessRecord)list.get(i);
7703 if (false) {
7704 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7705 + " #" + i + ":");
7706 r.dump(pw, prefix + " ");
7707 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007708 String oomAdj;
7709 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007710 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007711 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007712 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7713 } else if (r.setAdj >= HOME_APP_ADJ) {
7714 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7715 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7716 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7717 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7718 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007719 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7720 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7721 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7722 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007723 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7724 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7725 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7726 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007727 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007728 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007729 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007730 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007731 } else {
7732 oomAdj = Integer.toString(r.setAdj);
7733 }
7734 String schedGroup;
7735 switch (r.setSchedGroup) {
7736 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7737 schedGroup = "B";
7738 break;
7739 case Process.THREAD_GROUP_DEFAULT:
7740 schedGroup = "F";
7741 break;
7742 default:
7743 schedGroup = Integer.toString(r.setSchedGroup);
7744 break;
7745 }
7746 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007747 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007748 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007749 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007750 pw.print(prefix);
7751 pw.print(" ");
7752 if (r.adjTarget instanceof ComponentName) {
7753 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7754 } else if (r.adjTarget != null) {
7755 pw.print(r.adjTarget.toString());
7756 } else {
7757 pw.print("{null}");
7758 }
7759 pw.print("<=");
7760 if (r.adjSource instanceof ProcessRecord) {
7761 pw.print("Proc{");
7762 pw.print(((ProcessRecord)r.adjSource).toShortString());
7763 pw.println("}");
7764 } else if (r.adjSource != null) {
7765 pw.println(r.adjSource.toString());
7766 } else {
7767 pw.println("{null}");
7768 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007770 } else {
7771 pw.println(String.format("%s%s #%2d: %s",
7772 prefix, (r.persistent ? persistentLabel : normalLabel),
7773 i, r.toString()));
7774 }
7775 if (r.persistent) {
7776 numPers++;
7777 }
7778 }
7779 return numPers;
7780 }
7781
Dianne Hackborn472ad872010-04-07 17:31:48 -07007782 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007783 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007784 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 long uptime = SystemClock.uptimeMillis();
7786 long realtime = SystemClock.elapsedRealtime();
7787
7788 if (isCheckinRequest) {
7789 // short checkin version
7790 pw.println(uptime + "," + realtime);
7791 pw.flush();
7792 } else {
7793 pw.println("Applications Memory Usage (kB):");
7794 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7795 }
7796 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7797 ProcessRecord r = (ProcessRecord)list.get(i);
7798 if (r.thread != null) {
7799 if (!isCheckinRequest) {
7800 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7801 pw.flush();
7802 }
7803 try {
7804 r.thread.asBinder().dump(fd, args);
7805 } catch (RemoteException e) {
7806 if (!isCheckinRequest) {
7807 pw.println("Got RemoteException!");
7808 pw.flush();
7809 }
7810 }
7811 }
7812 }
7813 }
7814
7815 /**
7816 * Searches array of arguments for the specified string
7817 * @param args array of argument strings
7818 * @param value value to search for
7819 * @return true if the value is contained in the array
7820 */
7821 private static boolean scanArgs(String[] args, String value) {
7822 if (args != null) {
7823 for (String arg : args) {
7824 if (value.equals(arg)) {
7825 return true;
7826 }
7827 }
7828 }
7829 return false;
7830 }
7831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007832 private final void killServicesLocked(ProcessRecord app,
7833 boolean allowRestart) {
7834 // Report disconnected services.
7835 if (false) {
7836 // XXX we are letting the client link to the service for
7837 // death notifications.
7838 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007839 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007841 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007843 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007844 = r.connections.values().iterator();
7845 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007846 ArrayList<ConnectionRecord> cl = jt.next();
7847 for (int i=0; i<cl.size(); i++) {
7848 ConnectionRecord c = cl.get(i);
7849 if (c.binding.client != app) {
7850 try {
7851 //c.conn.connected(r.className, null);
7852 } catch (Exception e) {
7853 // todo: this should be asynchronous!
7854 Slog.w(TAG, "Exception thrown disconnected servce "
7855 + r.shortName
7856 + " from app " + app.processName, e);
7857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007858 }
7859 }
7860 }
7861 }
7862 }
7863 }
7864 }
7865
7866 // Clean up any connections this application has to other services.
7867 if (app.connections.size() > 0) {
7868 Iterator<ConnectionRecord> it = app.connections.iterator();
7869 while (it.hasNext()) {
7870 ConnectionRecord r = it.next();
7871 removeConnectionLocked(r, app, null);
7872 }
7873 }
7874 app.connections.clear();
7875
7876 if (app.services.size() != 0) {
7877 // Any services running in the application need to be placed
7878 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007879 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007881 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 synchronized (sr.stats.getBatteryStats()) {
7883 sr.stats.stopLaunchedLocked();
7884 }
7885 sr.app = null;
7886 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007887 if (mStoppingServices.remove(sr)) {
7888 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
7889 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007890
7891 boolean hasClients = sr.bindings.size() > 0;
7892 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007893 Iterator<IntentBindRecord> bindings
7894 = sr.bindings.values().iterator();
7895 while (bindings.hasNext()) {
7896 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007897 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007898 + ": shouldUnbind=" + b.hasBound);
7899 b.binder = null;
7900 b.requested = b.received = b.hasBound = false;
7901 }
7902 }
7903
7904 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007905 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007907 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 sr.crashCount, sr.shortName, app.pid);
7909 bringDownServiceLocked(sr, true);
7910 } else if (!allowRestart) {
7911 bringDownServiceLocked(sr, true);
7912 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007913 boolean canceled = scheduleServiceRestartLocked(sr, true);
7914
7915 // Should the service remain running? Note that in the
7916 // extreme case of so many attempts to deliver a command
7917 // that it failed, that we also will stop it here.
7918 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7919 if (sr.pendingStarts.size() == 0) {
7920 sr.startRequested = false;
7921 if (!hasClients) {
7922 // Whoops, no reason to restart!
7923 bringDownServiceLocked(sr, true);
7924 }
7925 }
7926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927 }
7928 }
7929
7930 if (!allowRestart) {
7931 app.services.clear();
7932 }
7933 }
7934
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007935 // Make sure we have no more records on the stopping list.
7936 int i = mStoppingServices.size();
7937 while (i > 0) {
7938 i--;
7939 ServiceRecord sr = mStoppingServices.get(i);
7940 if (sr.app == app) {
7941 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007942 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007943 }
7944 }
7945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 app.executingServices.clear();
7947 }
7948
7949 private final void removeDyingProviderLocked(ProcessRecord proc,
7950 ContentProviderRecord cpr) {
7951 synchronized (cpr) {
7952 cpr.launchingApp = null;
7953 cpr.notifyAll();
7954 }
7955
7956 mProvidersByClass.remove(cpr.info.name);
7957 String names[] = cpr.info.authority.split(";");
7958 for (int j = 0; j < names.length; j++) {
7959 mProvidersByName.remove(names[j]);
7960 }
7961
7962 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7963 while (cit.hasNext()) {
7964 ProcessRecord capp = cit.next();
7965 if (!capp.persistent && capp.thread != null
7966 && capp.pid != 0
7967 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007968 Slog.i(TAG, "Kill " + capp.processName
7969 + " (pid " + capp.pid + "): provider " + cpr.info.name
7970 + " in dying process " + proc.processName);
7971 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7972 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007973 Process.killProcess(capp.pid);
7974 }
7975 }
7976
7977 mLaunchingProviders.remove(cpr);
7978 }
7979
7980 /**
7981 * Main code for cleaning up a process when it has gone away. This is
7982 * called both as a result of the process dying, or directly when stopping
7983 * a process when running in single process mode.
7984 */
7985 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7986 boolean restarting, int index) {
7987 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007988 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007989 }
7990
Dianne Hackborn36124872009-10-08 16:22:03 -07007991 mProcessesToGc.remove(app);
7992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007993 // Dismiss any open dialogs.
7994 if (app.crashDialog != null) {
7995 app.crashDialog.dismiss();
7996 app.crashDialog = null;
7997 }
7998 if (app.anrDialog != null) {
7999 app.anrDialog.dismiss();
8000 app.anrDialog = null;
8001 }
8002 if (app.waitDialog != null) {
8003 app.waitDialog.dismiss();
8004 app.waitDialog = null;
8005 }
8006
8007 app.crashing = false;
8008 app.notResponding = false;
8009
8010 app.resetPackageList();
8011 app.thread = null;
8012 app.forcingToForeground = null;
8013 app.foregroundServices = false;
8014
8015 killServicesLocked(app, true);
8016
8017 boolean restart = false;
8018
8019 int NL = mLaunchingProviders.size();
8020
8021 // Remove published content providers.
8022 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008023 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008025 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 cpr.provider = null;
8027 cpr.app = null;
8028
8029 // See if someone is waiting for this provider... in which
8030 // case we don't remove it, but just let it restart.
8031 int i = 0;
8032 if (!app.bad) {
8033 for (; i<NL; i++) {
8034 if (mLaunchingProviders.get(i) == cpr) {
8035 restart = true;
8036 break;
8037 }
8038 }
8039 } else {
8040 i = NL;
8041 }
8042
8043 if (i >= NL) {
8044 removeDyingProviderLocked(app, cpr);
8045 NL = mLaunchingProviders.size();
8046 }
8047 }
8048 app.pubProviders.clear();
8049 }
8050
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008051 // Take care of any launching providers waiting for this process.
8052 if (checkAppInLaunchingProvidersLocked(app, false)) {
8053 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008054 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008056 // Unregister from connected content providers.
8057 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008058 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008059 while (it.hasNext()) {
8060 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8061 cpr.clients.remove(app);
8062 }
8063 app.conProviders.clear();
8064 }
8065
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008066 // At this point there may be remaining entries in mLaunchingProviders
8067 // where we were the only one waiting, so they are no longer of use.
8068 // Look for these and clean up if found.
8069 // XXX Commented out for now. Trying to figure out a way to reproduce
8070 // the actual situation to identify what is actually going on.
8071 if (false) {
8072 for (int i=0; i<NL; i++) {
8073 ContentProviderRecord cpr = (ContentProviderRecord)
8074 mLaunchingProviders.get(i);
8075 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8076 synchronized (cpr) {
8077 cpr.launchingApp = null;
8078 cpr.notifyAll();
8079 }
8080 }
8081 }
8082 }
8083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008084 skipCurrentReceiverLocked(app);
8085
8086 // Unregister any receivers.
8087 if (app.receivers.size() > 0) {
8088 Iterator<ReceiverList> it = app.receivers.iterator();
8089 while (it.hasNext()) {
8090 removeReceiverLocked(it.next());
8091 }
8092 app.receivers.clear();
8093 }
8094
Christopher Tate181fafa2009-05-14 11:12:14 -07008095 // If the app is undergoing backup, tell the backup manager about it
8096 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008097 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008098 try {
8099 IBackupManager bm = IBackupManager.Stub.asInterface(
8100 ServiceManager.getService(Context.BACKUP_SERVICE));
8101 bm.agentDisconnected(app.info.packageName);
8102 } catch (RemoteException e) {
8103 // can't happen; backup manager is local
8104 }
8105 }
8106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008107 // If the caller is restarting this app, then leave it in its
8108 // current lists and let the caller take care of it.
8109 if (restarting) {
8110 return;
8111 }
8112
8113 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008114 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115 "Removing non-persistent process during cleanup: " + app);
8116 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008117 if (mHeavyWeightProcess == app) {
8118 mHeavyWeightProcess = null;
8119 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 } else if (!app.removed) {
8122 // This app is persistent, so we need to keep its record around.
8123 // If it is not already on the pending app list, add it there
8124 // and start a new process for it.
8125 app.thread = null;
8126 app.forcingToForeground = null;
8127 app.foregroundServices = false;
8128 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8129 mPersistentStartingProcesses.add(app);
8130 restart = true;
8131 }
8132 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008133 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8134 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008135 mProcessesOnHold.remove(app);
8136
The Android Open Source Project4df24232009-03-05 14:34:35 -08008137 if (app == mHomeProcess) {
8138 mHomeProcess = null;
8139 }
8140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008141 if (restart) {
8142 // We have components that still need to be running in the
8143 // process, so re-launch it.
8144 mProcessNames.put(app.processName, app.info.uid, app);
8145 startProcessLocked(app, "restart", app.processName);
8146 } else if (app.pid > 0 && app.pid != MY_PID) {
8147 // Goodbye!
8148 synchronized (mPidsSelfLocked) {
8149 mPidsSelfLocked.remove(app.pid);
8150 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8151 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008152 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008153 }
8154 }
8155
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008156 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8157 // Look through the content providers we are waiting to have launched,
8158 // and if any run in this process then either schedule a restart of
8159 // the process or kill the client waiting for it if this process has
8160 // gone bad.
8161 int NL = mLaunchingProviders.size();
8162 boolean restart = false;
8163 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008164 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008165 if (cpr.launchingApp == app) {
8166 if (!alwaysBad && !app.bad) {
8167 restart = true;
8168 } else {
8169 removeDyingProviderLocked(app, cpr);
8170 NL = mLaunchingProviders.size();
8171 }
8172 }
8173 }
8174 return restart;
8175 }
8176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008177 // =========================================================
8178 // SERVICES
8179 // =========================================================
8180
8181 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8182 ActivityManager.RunningServiceInfo info =
8183 new ActivityManager.RunningServiceInfo();
8184 info.service = r.name;
8185 if (r.app != null) {
8186 info.pid = r.app.pid;
8187 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008188 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189 info.process = r.processName;
8190 info.foreground = r.isForeground;
8191 info.activeSince = r.createTime;
8192 info.started = r.startRequested;
8193 info.clientCount = r.connections.size();
8194 info.crashCount = r.crashCount;
8195 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008196 if (r.isForeground) {
8197 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8198 }
8199 if (r.startRequested) {
8200 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8201 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008202 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008203 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8204 }
8205 if (r.app != null && r.app.persistent) {
8206 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8207 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008208
8209 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8210 for (int i=0; i<connl.size(); i++) {
8211 ConnectionRecord conn = connl.get(i);
8212 if (conn.clientLabel != 0) {
8213 info.clientPackage = conn.binding.client.info.packageName;
8214 info.clientLabel = conn.clientLabel;
8215 return info;
8216 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008217 }
8218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 return info;
8220 }
8221
8222 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8223 int flags) {
8224 synchronized (this) {
8225 ArrayList<ActivityManager.RunningServiceInfo> res
8226 = new ArrayList<ActivityManager.RunningServiceInfo>();
8227
8228 if (mServices.size() > 0) {
8229 Iterator<ServiceRecord> it = mServices.values().iterator();
8230 while (it.hasNext() && res.size() < maxNum) {
8231 res.add(makeRunningServiceInfoLocked(it.next()));
8232 }
8233 }
8234
8235 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8236 ServiceRecord r = mRestartingServices.get(i);
8237 ActivityManager.RunningServiceInfo info =
8238 makeRunningServiceInfoLocked(r);
8239 info.restarting = r.nextRestartTime;
8240 res.add(info);
8241 }
8242
8243 return res;
8244 }
8245 }
8246
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008247 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8248 synchronized (this) {
8249 ServiceRecord r = mServices.get(name);
8250 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008251 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8252 for (int i=0; i<conn.size(); i++) {
8253 if (conn.get(i).clientIntent != null) {
8254 return conn.get(i).clientIntent;
8255 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008256 }
8257 }
8258 }
8259 }
8260 return null;
8261 }
8262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008263 private final ServiceRecord findServiceLocked(ComponentName name,
8264 IBinder token) {
8265 ServiceRecord r = mServices.get(name);
8266 return r == token ? r : null;
8267 }
8268
8269 private final class ServiceLookupResult {
8270 final ServiceRecord record;
8271 final String permission;
8272
8273 ServiceLookupResult(ServiceRecord _record, String _permission) {
8274 record = _record;
8275 permission = _permission;
8276 }
8277 };
8278
8279 private ServiceLookupResult findServiceLocked(Intent service,
8280 String resolvedType) {
8281 ServiceRecord r = null;
8282 if (service.getComponent() != null) {
8283 r = mServices.get(service.getComponent());
8284 }
8285 if (r == null) {
8286 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8287 r = mServicesByIntent.get(filter);
8288 }
8289
8290 if (r == null) {
8291 try {
8292 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008293 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008294 service, resolvedType, 0);
8295 ServiceInfo sInfo =
8296 rInfo != null ? rInfo.serviceInfo : null;
8297 if (sInfo == null) {
8298 return null;
8299 }
8300
8301 ComponentName name = new ComponentName(
8302 sInfo.applicationInfo.packageName, sInfo.name);
8303 r = mServices.get(name);
8304 } catch (RemoteException ex) {
8305 // pm is in same process, this will never happen.
8306 }
8307 }
8308 if (r != null) {
8309 int callingPid = Binder.getCallingPid();
8310 int callingUid = Binder.getCallingUid();
8311 if (checkComponentPermission(r.permission,
8312 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8313 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008314 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008315 + " from pid=" + callingPid
8316 + ", uid=" + callingUid
8317 + " requires " + r.permission);
8318 return new ServiceLookupResult(null, r.permission);
8319 }
8320 return new ServiceLookupResult(r, null);
8321 }
8322 return null;
8323 }
8324
8325 private class ServiceRestarter implements Runnable {
8326 private ServiceRecord mService;
8327
8328 void setService(ServiceRecord service) {
8329 mService = service;
8330 }
8331
8332 public void run() {
8333 synchronized(ActivityManagerService.this) {
8334 performServiceRestartLocked(mService);
8335 }
8336 }
8337 }
8338
8339 private ServiceLookupResult retrieveServiceLocked(Intent service,
8340 String resolvedType, int callingPid, int callingUid) {
8341 ServiceRecord r = null;
8342 if (service.getComponent() != null) {
8343 r = mServices.get(service.getComponent());
8344 }
8345 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8346 r = mServicesByIntent.get(filter);
8347 if (r == null) {
8348 try {
8349 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008350 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008351 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008352 ServiceInfo sInfo =
8353 rInfo != null ? rInfo.serviceInfo : null;
8354 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008355 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008356 ": not found");
8357 return null;
8358 }
8359
8360 ComponentName name = new ComponentName(
8361 sInfo.applicationInfo.packageName, sInfo.name);
8362 r = mServices.get(name);
8363 if (r == null) {
8364 filter = new Intent.FilterComparison(service.cloneFilter());
8365 ServiceRestarter res = new ServiceRestarter();
8366 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8367 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8368 synchronized (stats) {
8369 ss = stats.getServiceStatsLocked(
8370 sInfo.applicationInfo.uid, sInfo.packageName,
8371 sInfo.name);
8372 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008373 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008374 res.setService(r);
8375 mServices.put(name, r);
8376 mServicesByIntent.put(filter, r);
8377
8378 // Make sure this component isn't in the pending list.
8379 int N = mPendingServices.size();
8380 for (int i=0; i<N; i++) {
8381 ServiceRecord pr = mPendingServices.get(i);
8382 if (pr.name.equals(name)) {
8383 mPendingServices.remove(i);
8384 i--;
8385 N--;
8386 }
8387 }
8388 }
8389 } catch (RemoteException ex) {
8390 // pm is in same process, this will never happen.
8391 }
8392 }
8393 if (r != null) {
8394 if (checkComponentPermission(r.permission,
8395 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8396 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008397 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 + " from pid=" + Binder.getCallingPid()
8399 + ", uid=" + Binder.getCallingUid()
8400 + " requires " + r.permission);
8401 return new ServiceLookupResult(null, r.permission);
8402 }
8403 return new ServiceLookupResult(r, null);
8404 }
8405 return null;
8406 }
8407
8408 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8409 long now = SystemClock.uptimeMillis();
8410 if (r.executeNesting == 0 && r.app != null) {
8411 if (r.app.executingServices.size() == 0) {
8412 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8413 msg.obj = r.app;
8414 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8415 }
8416 r.app.executingServices.add(r);
8417 }
8418 r.executeNesting++;
8419 r.executingStart = now;
8420 }
8421
8422 private final void sendServiceArgsLocked(ServiceRecord r,
8423 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008424 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 if (N == 0) {
8426 return;
8427 }
8428
Dianne Hackborn39792d22010-08-19 18:01:52 -07008429 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008430 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008431 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008432 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8433 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008434 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008435 // If somehow we got a dummy start at the front, then
8436 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008437 continue;
8438 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008439 si.deliveredTime = SystemClock.uptimeMillis();
8440 r.deliveredStarts.add(si);
8441 si.deliveryCount++;
8442 if (si.targetPermissionUid >= 0) {
8443 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008444 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008445 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008446 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008447 bumpServiceExecutingLocked(r);
8448 if (!oomAdjusted) {
8449 oomAdjusted = true;
8450 updateOomAdjLocked(r.app);
8451 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008452 int flags = 0;
8453 if (si.deliveryCount > 0) {
8454 flags |= Service.START_FLAG_RETRY;
8455 }
8456 if (si.doneExecutingCount > 0) {
8457 flags |= Service.START_FLAG_REDELIVERY;
8458 }
8459 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008460 } catch (RemoteException e) {
8461 // Remote process gone... we'll let the normal cleanup take
8462 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008463 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008464 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008465 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008466 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008467 break;
8468 }
8469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008470 }
8471
8472 private final boolean requestServiceBindingLocked(ServiceRecord r,
8473 IntentBindRecord i, boolean rebind) {
8474 if (r.app == null || r.app.thread == null) {
8475 // If service is not currently running, can't yet bind.
8476 return false;
8477 }
8478 if ((!i.requested || rebind) && i.apps.size() > 0) {
8479 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008480 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
8481 + " in " + i + ": shouldUnbind=" + i.hasBound);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008482 bumpServiceExecutingLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008483 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8484 if (!rebind) {
8485 i.requested = true;
8486 }
8487 i.hasBound = true;
8488 i.doRebind = false;
8489 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008490 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008491 return false;
8492 }
8493 }
8494 return true;
8495 }
8496
8497 private final void requestServiceBindingsLocked(ServiceRecord r) {
8498 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8499 while (bindings.hasNext()) {
8500 IntentBindRecord i = bindings.next();
8501 if (!requestServiceBindingLocked(r, i, false)) {
8502 break;
8503 }
8504 }
8505 }
8506
8507 private final void realStartServiceLocked(ServiceRecord r,
8508 ProcessRecord app) throws RemoteException {
8509 if (app.thread == null) {
8510 throw new RemoteException();
8511 }
8512
8513 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008514 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515
8516 app.services.add(r);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008517 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008519 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520
8521 boolean created = false;
8522 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008523 mStringBuilder.setLength(0);
8524 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008525 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008526 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008527 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 synchronized (r.stats.getBatteryStats()) {
8529 r.stats.startLaunchedLocked();
8530 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008531 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008533 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008534 created = true;
8535 } finally {
8536 if (!created) {
8537 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008538 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008539 }
8540 }
8541
8542 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008543
8544 // If the service is in the started state, and there are no
8545 // pending arguments, then fake up one so its onStartCommand() will
8546 // be called.
8547 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8548 r.lastStartId++;
8549 if (r.lastStartId < 1) {
8550 r.lastStartId = 1;
8551 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008552 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008553 }
8554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 sendServiceArgsLocked(r, true);
8556 }
8557
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008558 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8559 boolean allowCancel) {
8560 boolean canceled = false;
8561
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008562 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008563 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008564 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008565
8566 // Any delivered but not yet finished starts should be put back
8567 // on the pending list.
8568 final int N = r.deliveredStarts.size();
8569 if (N > 0) {
8570 for (int i=N-1; i>=0; i--) {
8571 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008572 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008573 if (si.intent == null) {
8574 // We'll generate this again if needed.
8575 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8576 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8577 r.pendingStarts.add(0, si);
8578 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8579 dur *= 2;
8580 if (minDuration < dur) minDuration = dur;
8581 if (resetTime < dur) resetTime = dur;
8582 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008583 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008584 + r.name);
8585 canceled = true;
8586 }
8587 }
8588 r.deliveredStarts.clear();
8589 }
8590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008591 r.totalRestartCount++;
8592 if (r.restartDelay == 0) {
8593 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008594 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008595 } else {
8596 // If it has been a "reasonably long time" since the service
8597 // was started, then reset our restart duration back to
8598 // the beginning, so we don't infinitely increase the duration
8599 // on a service that just occasionally gets killed (which is
8600 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008601 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008602 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008603 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008604 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008605 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008606 if (r.restartDelay < minDuration) {
8607 r.restartDelay = minDuration;
8608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008609 }
8610 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008611
8612 r.nextRestartTime = now + r.restartDelay;
8613
8614 // Make sure that we don't end up restarting a bunch of services
8615 // all at the same time.
8616 boolean repeat;
8617 do {
8618 repeat = false;
8619 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8620 ServiceRecord r2 = mRestartingServices.get(i);
8621 if (r2 != r && r.nextRestartTime
8622 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8623 && r.nextRestartTime
8624 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8625 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8626 r.restartDelay = r.nextRestartTime - now;
8627 repeat = true;
8628 break;
8629 }
8630 }
8631 } while (repeat);
8632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 if (!mRestartingServices.contains(r)) {
8634 mRestartingServices.add(r);
8635 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008636
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008637 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008640 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008641 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008642 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008644 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008645 r.shortName, r.restartDelay);
8646
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008647 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008648 }
8649
8650 final void performServiceRestartLocked(ServiceRecord r) {
8651 if (!mRestartingServices.contains(r)) {
8652 return;
8653 }
8654 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8655 }
8656
8657 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8658 if (r.restartDelay == 0) {
8659 return false;
8660 }
8661 r.resetRestartCounter();
8662 mRestartingServices.remove(r);
8663 mHandler.removeCallbacks(r.restarter);
8664 return true;
8665 }
8666
8667 private final boolean bringUpServiceLocked(ServiceRecord r,
8668 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008669 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008670 //r.dump(" ");
8671
Dianne Hackborn36124872009-10-08 16:22:03 -07008672 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008673 sendServiceArgsLocked(r, false);
8674 return true;
8675 }
8676
8677 if (!whileRestarting && r.restartDelay > 0) {
8678 // If waiting for a restart, then do nothing.
8679 return true;
8680 }
8681
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008682 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008684 // We are now bringing the service up, so no longer in the
8685 // restarting state.
8686 mRestartingServices.remove(r);
8687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008688 final String appName = r.processName;
8689 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8690 if (app != null && app.thread != null) {
8691 try {
8692 realStartServiceLocked(r, app);
8693 return true;
8694 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008695 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008696 }
8697
8698 // If a dead object exception was thrown -- fall through to
8699 // restart the application.
8700 }
8701
Dianne Hackborn36124872009-10-08 16:22:03 -07008702 // Not running -- get it started, and enqueue this service record
8703 // to be executed when the app comes up.
8704 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8705 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008706 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008707 + r.appInfo.packageName + "/"
8708 + r.appInfo.uid + " for service "
8709 + r.intent.getIntent() + ": process is bad");
8710 bringDownServiceLocked(r, true);
8711 return false;
8712 }
8713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008714 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008715 mPendingServices.add(r);
8716 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 return true;
8719 }
8720
8721 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008722 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 //r.dump(" ");
8724
8725 // Does it still need to run?
8726 if (!force && r.startRequested) {
8727 return;
8728 }
8729 if (r.connections.size() > 0) {
8730 if (!force) {
8731 // XXX should probably keep a count of the number of auto-create
8732 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008733 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008734 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008735 ArrayList<ConnectionRecord> cr = it.next();
8736 for (int i=0; i<cr.size(); i++) {
8737 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8738 return;
8739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008740 }
8741 }
8742 }
8743
8744 // Report to all of the connections that the service is no longer
8745 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008746 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008748 ArrayList<ConnectionRecord> c = it.next();
8749 for (int i=0; i<c.size(); i++) {
8750 try {
8751 c.get(i).conn.connected(r.name, null);
8752 } catch (Exception e) {
8753 Slog.w(TAG, "Failure disconnecting service " + r.name +
8754 " to connection " + c.get(i).conn.asBinder() +
8755 " (in " + c.get(i).binding.client.processName + ")", e);
8756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 }
8758 }
8759 }
8760
8761 // Tell the service that it has been unbound.
8762 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8763 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8764 while (it.hasNext()) {
8765 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008766 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008767 + ": hasBound=" + ibr.hasBound);
8768 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8769 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008770 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
8771 + " for " + ibr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008772 bumpServiceExecutingLocked(r);
8773 updateOomAdjLocked(r.app);
8774 ibr.hasBound = false;
8775 r.app.thread.scheduleUnbindService(r,
8776 ibr.intent.getIntent());
8777 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008778 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008779 + r.shortName, e);
8780 serviceDoneExecutingLocked(r, true);
8781 }
8782 }
8783 }
8784 }
8785
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008786 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008787 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 System.identityHashCode(r), r.shortName,
8789 (r.app != null) ? r.app.pid : -1);
8790
8791 mServices.remove(r.name);
8792 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008793 r.totalRestartCount = 0;
8794 unscheduleServiceRestartLocked(r);
8795
8796 // Also make sure it is not on the pending list.
8797 int N = mPendingServices.size();
8798 for (int i=0; i<N; i++) {
8799 if (mPendingServices.get(i) == r) {
8800 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008801 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008802 i--;
8803 N--;
8804 }
8805 }
8806
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008807 r.cancelNotification();
8808 r.isForeground = false;
8809 r.foregroundId = 0;
8810 r.foregroundNoti = null;
8811
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008812 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008813 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008814 r.pendingStarts.clear();
8815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 if (r.app != null) {
8817 synchronized (r.stats.getBatteryStats()) {
8818 r.stats.stopLaunchedLocked();
8819 }
8820 r.app.services.remove(r);
8821 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008822 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008823 if (DEBUG_SERVICE) {
8824 RuntimeException here = new RuntimeException();
8825 here.fillInStackTrace();
8826 Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
8827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008828 bumpServiceExecutingLocked(r);
8829 mStoppingServices.add(r);
8830 updateOomAdjLocked(r.app);
8831 r.app.thread.scheduleStopService(r);
8832 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008833 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 + r.shortName, e);
8835 serviceDoneExecutingLocked(r, true);
8836 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008837 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008839 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008840 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008841 }
8842 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008843 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008844 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008845 }
8846 }
8847
8848 ComponentName startServiceLocked(IApplicationThread caller,
8849 Intent service, String resolvedType,
8850 int callingPid, int callingUid) {
8851 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008852 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008853 + " type=" + resolvedType + " args=" + service.getExtras());
8854
8855 if (caller != null) {
8856 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8857 if (callerApp == null) {
8858 throw new SecurityException(
8859 "Unable to find app for caller " + caller
8860 + " (pid=" + Binder.getCallingPid()
8861 + ") when starting service " + service);
8862 }
8863 }
8864
8865 ServiceLookupResult res =
8866 retrieveServiceLocked(service, resolvedType,
8867 callingPid, callingUid);
8868 if (res == null) {
8869 return null;
8870 }
8871 if (res.record == null) {
8872 return new ComponentName("!", res.permission != null
8873 ? res.permission : "private to package");
8874 }
8875 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07008876 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
8877 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008878 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008879 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008880 }
8881 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008882 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008883 r.lastStartId++;
8884 if (r.lastStartId < 1) {
8885 r.lastStartId = 1;
8886 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008887 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
8888 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008889 r.lastActivity = SystemClock.uptimeMillis();
8890 synchronized (r.stats.getBatteryStats()) {
8891 r.stats.startRunningLocked();
8892 }
8893 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8894 return new ComponentName("!", "Service process is bad");
8895 }
8896 return r.name;
8897 }
8898 }
8899
8900 public ComponentName startService(IApplicationThread caller, Intent service,
8901 String resolvedType) {
8902 // Refuse possible leaked file descriptors
8903 if (service != null && service.hasFileDescriptors() == true) {
8904 throw new IllegalArgumentException("File descriptors passed in Intent");
8905 }
8906
8907 synchronized(this) {
8908 final int callingPid = Binder.getCallingPid();
8909 final int callingUid = Binder.getCallingUid();
8910 final long origId = Binder.clearCallingIdentity();
8911 ComponentName res = startServiceLocked(caller, service,
8912 resolvedType, callingPid, callingUid);
8913 Binder.restoreCallingIdentity(origId);
8914 return res;
8915 }
8916 }
8917
8918 ComponentName startServiceInPackage(int uid,
8919 Intent service, String resolvedType) {
8920 synchronized(this) {
8921 final long origId = Binder.clearCallingIdentity();
8922 ComponentName res = startServiceLocked(null, service,
8923 resolvedType, -1, uid);
8924 Binder.restoreCallingIdentity(origId);
8925 return res;
8926 }
8927 }
8928
8929 public int stopService(IApplicationThread caller, Intent service,
8930 String resolvedType) {
8931 // Refuse possible leaked file descriptors
8932 if (service != null && service.hasFileDescriptors() == true) {
8933 throw new IllegalArgumentException("File descriptors passed in Intent");
8934 }
8935
8936 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008937 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008938 + " type=" + resolvedType);
8939
8940 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8941 if (caller != null && callerApp == null) {
8942 throw new SecurityException(
8943 "Unable to find app for caller " + caller
8944 + " (pid=" + Binder.getCallingPid()
8945 + ") when stopping service " + service);
8946 }
8947
8948 // If this service is active, make sure it is stopped.
8949 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8950 if (r != null) {
8951 if (r.record != null) {
8952 synchronized (r.record.stats.getBatteryStats()) {
8953 r.record.stats.stopRunningLocked();
8954 }
8955 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008956 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008957 final long origId = Binder.clearCallingIdentity();
8958 bringDownServiceLocked(r.record, false);
8959 Binder.restoreCallingIdentity(origId);
8960 return 1;
8961 }
8962 return -1;
8963 }
8964 }
8965
8966 return 0;
8967 }
8968
8969 public IBinder peekService(Intent service, String resolvedType) {
8970 // Refuse possible leaked file descriptors
8971 if (service != null && service.hasFileDescriptors() == true) {
8972 throw new IllegalArgumentException("File descriptors passed in Intent");
8973 }
8974
8975 IBinder ret = null;
8976
8977 synchronized(this) {
8978 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8979
8980 if (r != null) {
8981 // r.record is null if findServiceLocked() failed the caller permission check
8982 if (r.record == null) {
8983 throw new SecurityException(
8984 "Permission Denial: Accessing service " + r.record.name
8985 + " from pid=" + Binder.getCallingPid()
8986 + ", uid=" + Binder.getCallingUid()
8987 + " requires " + r.permission);
8988 }
8989 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8990 if (ib != null) {
8991 ret = ib.binder;
8992 }
8993 }
8994 }
8995
8996 return ret;
8997 }
8998
8999 public boolean stopServiceToken(ComponentName className, IBinder token,
9000 int startId) {
9001 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009002 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009003 + " " + token + " startId=" + startId);
9004 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009005 if (r != null) {
9006 if (startId >= 0) {
9007 // Asked to only stop if done with all work. Note that
9008 // to avoid leaks, we will take this as dropping all
9009 // start items up to and including this one.
9010 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9011 if (si != null) {
9012 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009013 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9014 cur.removeUriPermissionsLocked();
9015 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009016 break;
9017 }
9018 }
9019 }
9020
9021 if (r.lastStartId != startId) {
9022 return false;
9023 }
9024
9025 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009026 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009027 + " is last, but have " + r.deliveredStarts.size()
9028 + " remaining args");
9029 }
9030 }
9031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009032 synchronized (r.stats.getBatteryStats()) {
9033 r.stats.stopRunningLocked();
9034 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009035 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009036 }
9037 final long origId = Binder.clearCallingIdentity();
9038 bringDownServiceLocked(r, false);
9039 Binder.restoreCallingIdentity(origId);
9040 return true;
9041 }
9042 }
9043 return false;
9044 }
9045
9046 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009047 int id, Notification notification, boolean removeNotification) {
9048 final long origId = Binder.clearCallingIdentity();
9049 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 synchronized(this) {
9051 ServiceRecord r = findServiceLocked(className, token);
9052 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009053 if (id != 0) {
9054 if (notification == null) {
9055 throw new IllegalArgumentException("null notification");
9056 }
9057 if (r.foregroundId != id) {
9058 r.cancelNotification();
9059 r.foregroundId = id;
9060 }
9061 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9062 r.foregroundNoti = notification;
9063 r.isForeground = true;
9064 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009065 if (r.app != null) {
9066 updateServiceForegroundLocked(r.app, true);
9067 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009068 } else {
9069 if (r.isForeground) {
9070 r.isForeground = false;
9071 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009072 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009073 updateServiceForegroundLocked(r.app, true);
9074 }
9075 }
9076 if (removeNotification) {
9077 r.cancelNotification();
9078 r.foregroundId = 0;
9079 r.foregroundNoti = null;
9080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 }
9082 }
9083 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009084 } finally {
9085 Binder.restoreCallingIdentity(origId);
9086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 }
9088
9089 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9090 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009091 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 if (sr.isForeground) {
9093 anyForeground = true;
9094 break;
9095 }
9096 }
9097 if (anyForeground != proc.foregroundServices) {
9098 proc.foregroundServices = anyForeground;
9099 if (oomAdj) {
9100 updateOomAdjLocked();
9101 }
9102 }
9103 }
9104
9105 public int bindService(IApplicationThread caller, IBinder token,
9106 Intent service, String resolvedType,
9107 IServiceConnection connection, int flags) {
9108 // Refuse possible leaked file descriptors
9109 if (service != null && service.hasFileDescriptors() == true) {
9110 throw new IllegalArgumentException("File descriptors passed in Intent");
9111 }
9112
9113 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009114 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009115 + " type=" + resolvedType + " conn=" + connection.asBinder()
9116 + " flags=0x" + Integer.toHexString(flags));
9117 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9118 if (callerApp == null) {
9119 throw new SecurityException(
9120 "Unable to find app for caller " + caller
9121 + " (pid=" + Binder.getCallingPid()
9122 + ") when binding service " + service);
9123 }
9124
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009125 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009126 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009127 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009128 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009129 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130 return 0;
9131 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009132 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009133 }
9134
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009135 int clientLabel = 0;
9136 PendingIntent clientIntent = null;
9137
9138 if (callerApp.info.uid == Process.SYSTEM_UID) {
9139 // Hacky kind of thing -- allow system stuff to tell us
9140 // what they are, so we can report this elsewhere for
9141 // others to know why certain services are running.
9142 try {
9143 clientIntent = (PendingIntent)service.getParcelableExtra(
9144 Intent.EXTRA_CLIENT_INTENT);
9145 } catch (RuntimeException e) {
9146 }
9147 if (clientIntent != null) {
9148 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9149 if (clientLabel != 0) {
9150 // There are no useful extras in the intent, trash them.
9151 // System code calling with this stuff just needs to know
9152 // this will happen.
9153 service = service.cloneFilter();
9154 }
9155 }
9156 }
9157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 ServiceLookupResult res =
9159 retrieveServiceLocked(service, resolvedType,
9160 Binder.getCallingPid(), Binder.getCallingUid());
9161 if (res == null) {
9162 return 0;
9163 }
9164 if (res.record == null) {
9165 return -1;
9166 }
9167 ServiceRecord s = res.record;
9168
9169 final long origId = Binder.clearCallingIdentity();
9170
9171 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009172 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009173 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009174 }
9175
9176 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9177 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009178 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179
9180 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009181 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9182 if (clist == null) {
9183 clist = new ArrayList<ConnectionRecord>();
9184 s.connections.put(binder, clist);
9185 }
9186 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009187 b.connections.add(c);
9188 if (activity != null) {
9189 if (activity.connections == null) {
9190 activity.connections = new HashSet<ConnectionRecord>();
9191 }
9192 activity.connections.add(c);
9193 }
9194 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009195 clist = mServiceConnections.get(binder);
9196 if (clist == null) {
9197 clist = new ArrayList<ConnectionRecord>();
9198 mServiceConnections.put(binder, clist);
9199 }
9200 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009201
9202 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9203 s.lastActivity = SystemClock.uptimeMillis();
9204 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9205 return 0;
9206 }
9207 }
9208
9209 if (s.app != null) {
9210 // This could have made the service more important.
9211 updateOomAdjLocked(s.app);
9212 }
9213
Joe Onorato8a9b2202010-02-26 18:56:32 -08009214 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 + ": received=" + b.intent.received
9216 + " apps=" + b.intent.apps.size()
9217 + " doRebind=" + b.intent.doRebind);
9218
9219 if (s.app != null && b.intent.received) {
9220 // Service is already running, so we can immediately
9221 // publish the connection.
9222 try {
9223 c.conn.connected(s.name, b.intent.binder);
9224 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009225 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 + " to connection " + c.conn.asBinder()
9227 + " (in " + c.binding.client.processName + ")", e);
9228 }
9229
9230 // If this is the first app connected back to this binding,
9231 // and the service had previously asked to be told when
9232 // rebound, then do so.
9233 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9234 requestServiceBindingLocked(s, b.intent, true);
9235 }
9236 } else if (!b.intent.requested) {
9237 requestServiceBindingLocked(s, b.intent, false);
9238 }
9239
9240 Binder.restoreCallingIdentity(origId);
9241 }
9242
9243 return 1;
9244 }
9245
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009246 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009247 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009248 IBinder binder = c.conn.asBinder();
9249 AppBindRecord b = c.binding;
9250 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009251 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9252 if (clist != null) {
9253 clist.remove(c);
9254 if (clist.size() == 0) {
9255 s.connections.remove(binder);
9256 }
9257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009258 b.connections.remove(c);
9259 if (c.activity != null && c.activity != skipAct) {
9260 if (c.activity.connections != null) {
9261 c.activity.connections.remove(c);
9262 }
9263 }
9264 if (b.client != skipApp) {
9265 b.client.connections.remove(c);
9266 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009267 clist = mServiceConnections.get(binder);
9268 if (clist != null) {
9269 clist.remove(c);
9270 if (clist.size() == 0) {
9271 mServiceConnections.remove(binder);
9272 }
9273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009274
9275 if (b.connections.size() == 0) {
9276 b.intent.apps.remove(b.client);
9277 }
9278
Joe Onorato8a9b2202010-02-26 18:56:32 -08009279 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009280 + ": shouldUnbind=" + b.intent.hasBound);
9281 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9282 && b.intent.hasBound) {
9283 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009284 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
9285 + " from " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 bumpServiceExecutingLocked(s);
9287 updateOomAdjLocked(s.app);
9288 b.intent.hasBound = false;
9289 // Assume the client doesn't want to know about a rebind;
9290 // we will deal with that later if it asks for one.
9291 b.intent.doRebind = false;
9292 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9293 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009294 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 serviceDoneExecutingLocked(s, true);
9296 }
9297 }
9298
9299 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9300 bringDownServiceLocked(s, false);
9301 }
9302 }
9303
9304 public boolean unbindService(IServiceConnection connection) {
9305 synchronized (this) {
9306 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009307 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009308 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9309 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009310 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009311 + connection.asBinder());
9312 return false;
9313 }
9314
9315 final long origId = Binder.clearCallingIdentity();
9316
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009317 while (clist.size() > 0) {
9318 ConnectionRecord r = clist.get(0);
9319 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009320
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009321 if (r.binding.service.app != null) {
9322 // This could have made the service less important.
9323 updateOomAdjLocked(r.binding.service.app);
9324 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 }
9326
9327 Binder.restoreCallingIdentity(origId);
9328 }
9329
9330 return true;
9331 }
9332
9333 public void publishService(IBinder token, Intent intent, IBinder service) {
9334 // Refuse possible leaked file descriptors
9335 if (intent != null && intent.hasFileDescriptors() == true) {
9336 throw new IllegalArgumentException("File descriptors passed in Intent");
9337 }
9338
9339 synchronized(this) {
9340 if (!(token instanceof ServiceRecord)) {
9341 throw new IllegalArgumentException("Invalid service token");
9342 }
9343 ServiceRecord r = (ServiceRecord)token;
9344
9345 final long origId = Binder.clearCallingIdentity();
9346
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009347 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009348 + " " + intent + ": " + service);
9349 if (r != null) {
9350 Intent.FilterComparison filter
9351 = new Intent.FilterComparison(intent);
9352 IntentBindRecord b = r.bindings.get(filter);
9353 if (b != null && !b.received) {
9354 b.binder = service;
9355 b.requested = true;
9356 b.received = true;
9357 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009358 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009359 = r.connections.values().iterator();
9360 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009361 ArrayList<ConnectionRecord> clist = it.next();
9362 for (int i=0; i<clist.size(); i++) {
9363 ConnectionRecord c = clist.get(i);
9364 if (!filter.equals(c.binding.intent.intent)) {
9365 if (DEBUG_SERVICE) Slog.v(
9366 TAG, "Not publishing to: " + c);
9367 if (DEBUG_SERVICE) Slog.v(
9368 TAG, "Bound intent: " + c.binding.intent.intent);
9369 if (DEBUG_SERVICE) Slog.v(
9370 TAG, "Published intent: " + intent);
9371 continue;
9372 }
9373 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9374 try {
9375 c.conn.connected(r.name, service);
9376 } catch (Exception e) {
9377 Slog.w(TAG, "Failure sending service " + r.name +
9378 " to connection " + c.conn.asBinder() +
9379 " (in " + c.binding.client.processName + ")", e);
9380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009381 }
9382 }
9383 }
9384 }
9385
9386 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9387
9388 Binder.restoreCallingIdentity(origId);
9389 }
9390 }
9391 }
9392
9393 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9394 // Refuse possible leaked file descriptors
9395 if (intent != null && intent.hasFileDescriptors() == true) {
9396 throw new IllegalArgumentException("File descriptors passed in Intent");
9397 }
9398
9399 synchronized(this) {
9400 if (!(token instanceof ServiceRecord)) {
9401 throw new IllegalArgumentException("Invalid service token");
9402 }
9403 ServiceRecord r = (ServiceRecord)token;
9404
9405 final long origId = Binder.clearCallingIdentity();
9406
9407 if (r != null) {
9408 Intent.FilterComparison filter
9409 = new Intent.FilterComparison(intent);
9410 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009411 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009412 + " at " + b + ": apps="
9413 + (b != null ? b.apps.size() : 0));
9414 if (b != null) {
9415 if (b.apps.size() > 0) {
9416 // Applications have already bound since the last
9417 // unbind, so just rebind right here.
9418 requestServiceBindingLocked(r, b, true);
9419 } else {
9420 // Note to tell the service the next time there is
9421 // a new client.
9422 b.doRebind = true;
9423 }
9424 }
9425
9426 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9427
9428 Binder.restoreCallingIdentity(origId);
9429 }
9430 }
9431 }
9432
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009433 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009434 synchronized(this) {
9435 if (!(token instanceof ServiceRecord)) {
9436 throw new IllegalArgumentException("Invalid service token");
9437 }
9438 ServiceRecord r = (ServiceRecord)token;
9439 boolean inStopping = mStoppingServices.contains(token);
9440 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009441 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009442 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009443 + " with incorrect token: given " + token
9444 + ", expected " + r);
9445 return;
9446 }
9447
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009448 if (type == 1) {
9449 // This is a call from a service start... take care of
9450 // book-keeping.
9451 r.callStart = true;
9452 switch (res) {
9453 case Service.START_STICKY_COMPATIBILITY:
9454 case Service.START_STICKY: {
9455 // We are done with the associated start arguments.
9456 r.findDeliveredStart(startId, true);
9457 // Don't stop if killed.
9458 r.stopIfKilled = false;
9459 break;
9460 }
9461 case Service.START_NOT_STICKY: {
9462 // We are done with the associated start arguments.
9463 r.findDeliveredStart(startId, true);
9464 if (r.lastStartId == startId) {
9465 // There is no more work, and this service
9466 // doesn't want to hang around if killed.
9467 r.stopIfKilled = true;
9468 }
9469 break;
9470 }
9471 case Service.START_REDELIVER_INTENT: {
9472 // We'll keep this item until they explicitly
9473 // call stop for it, but keep track of the fact
9474 // that it was delivered.
9475 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9476 if (si != null) {
9477 si.deliveryCount = 0;
9478 si.doneExecutingCount++;
9479 // Don't stop if killed.
9480 r.stopIfKilled = true;
9481 }
9482 break;
9483 }
9484 default:
9485 throw new IllegalArgumentException(
9486 "Unknown service start result: " + res);
9487 }
9488 if (res == Service.START_STICKY_COMPATIBILITY) {
9489 r.callStart = false;
9490 }
9491 }
9492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009493 final long origId = Binder.clearCallingIdentity();
9494 serviceDoneExecutingLocked(r, inStopping);
9495 Binder.restoreCallingIdentity(origId);
9496 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009497 Slog.w(TAG, "Done executing unknown service from pid "
9498 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009499 }
9500 }
9501 }
9502
9503 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009504 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9505 + ": nesting=" + r.executeNesting
9506 + ", inStopping=" + inStopping + ", app=" + r.app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009507 r.executeNesting--;
9508 if (r.executeNesting <= 0 && r.app != null) {
9509 r.app.executingServices.remove(r);
9510 if (r.app.executingServices.size() == 0) {
9511 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9512 }
9513 if (inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009514 if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009515 mStoppingServices.remove(r);
9516 }
9517 updateOomAdjLocked(r.app);
9518 }
9519 }
9520
9521 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009522 String anrMessage = null;
9523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009524 synchronized(this) {
9525 if (proc.executingServices.size() == 0 || proc.thread == null) {
9526 return;
9527 }
9528 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9529 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9530 ServiceRecord timeout = null;
9531 long nextTime = 0;
9532 while (it.hasNext()) {
9533 ServiceRecord sr = it.next();
9534 if (sr.executingStart < maxTime) {
9535 timeout = sr;
9536 break;
9537 }
9538 if (sr.executingStart > nextTime) {
9539 nextTime = sr.executingStart;
9540 }
9541 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009542 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009543 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009544 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 } else {
9546 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9547 msg.obj = proc;
9548 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9549 }
9550 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009551
9552 if (anrMessage != null) {
9553 appNotResponding(proc, null, null, anrMessage);
9554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009555 }
9556
9557 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009558 // BACKUP AND RESTORE
9559 // =========================================================
9560
9561 // Cause the target app to be launched if necessary and its backup agent
9562 // instantiated. The backup agent will invoke backupAgentCreated() on the
9563 // activity manager to announce its creation.
9564 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009565 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009566 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9567
9568 synchronized(this) {
9569 // !!! TODO: currently no check here that we're already bound
9570 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9571 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9572 synchronized (stats) {
9573 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9574 }
9575
9576 BackupRecord r = new BackupRecord(ss, app, backupMode);
9577 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9578 // startProcessLocked() returns existing proc's record if it's already running
9579 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009580 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009581 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009582 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009583 return false;
9584 }
9585
9586 r.app = proc;
9587 mBackupTarget = r;
9588 mBackupAppName = app.packageName;
9589
Christopher Tate6fa95972009-06-05 18:43:55 -07009590 // Try not to kill the process during backup
9591 updateOomAdjLocked(proc);
9592
Christopher Tate181fafa2009-05-14 11:12:14 -07009593 // If the process is already attached, schedule the creation of the backup agent now.
9594 // If it is not yet live, this will be done when it attaches to the framework.
9595 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009596 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009597 try {
9598 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9599 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009600 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009601 }
9602 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009603 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009604 }
9605 // Invariants: at this point, the target app process exists and the application
9606 // is either already running or in the process of coming up. mBackupTarget and
9607 // mBackupAppName describe the app, so that when it binds back to the AM we
9608 // know that it's scheduled for a backup-agent operation.
9609 }
9610
9611 return true;
9612 }
9613
9614 // A backup agent has just come up
9615 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009616 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009617 + " = " + agent);
9618
9619 synchronized(this) {
9620 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009621 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009622 return;
9623 }
9624
Christopher Tate043dadc2009-06-02 16:11:00 -07009625 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009626 try {
9627 IBackupManager bm = IBackupManager.Stub.asInterface(
9628 ServiceManager.getService(Context.BACKUP_SERVICE));
9629 bm.agentConnected(agentPackageName, agent);
9630 } catch (RemoteException e) {
9631 // can't happen; the backup manager service is local
9632 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009633 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009634 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009635 } finally {
9636 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009637 }
9638 }
9639 }
9640
9641 // done with this agent
9642 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009643 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009644 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009645 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009646 return;
9647 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009648
9649 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009650 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009651 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009652 return;
9653 }
9654
Christopher Tate181fafa2009-05-14 11:12:14 -07009655 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009656 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009657 return;
9658 }
9659
Christopher Tate6fa95972009-06-05 18:43:55 -07009660 ProcessRecord proc = mBackupTarget.app;
9661 mBackupTarget = null;
9662 mBackupAppName = null;
9663
9664 // Not backing this app up any more; reset its OOM adjustment
9665 updateOomAdjLocked(proc);
9666
Christopher Tatec7b31e32009-06-10 15:49:30 -07009667 // If the app crashed during backup, 'thread' will be null here
9668 if (proc.thread != null) {
9669 try {
9670 proc.thread.scheduleDestroyBackupAgent(appInfo);
9671 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009672 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009673 e.printStackTrace();
9674 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009675 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009676 }
9677 }
9678 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679 // BROADCASTS
9680 // =========================================================
9681
Josh Bartel7f208742010-02-25 11:01:44 -06009682 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 List cur) {
9684 final ContentResolver resolver = mContext.getContentResolver();
9685 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9686 if (list == null) {
9687 return cur;
9688 }
9689 int N = list.size();
9690 for (int i=0; i<N; i++) {
9691 Intent intent = list.get(i);
9692 if (filter.match(resolver, intent, true, TAG) >= 0) {
9693 if (cur == null) {
9694 cur = new ArrayList<Intent>();
9695 }
9696 cur.add(intent);
9697 }
9698 }
9699 return cur;
9700 }
9701
9702 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009703 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704 + mBroadcastsScheduled);
9705
9706 if (mBroadcastsScheduled) {
9707 return;
9708 }
9709 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9710 mBroadcastsScheduled = true;
9711 }
9712
9713 public Intent registerReceiver(IApplicationThread caller,
9714 IIntentReceiver receiver, IntentFilter filter, String permission) {
9715 synchronized(this) {
9716 ProcessRecord callerApp = null;
9717 if (caller != null) {
9718 callerApp = getRecordForAppLocked(caller);
9719 if (callerApp == null) {
9720 throw new SecurityException(
9721 "Unable to find app for caller " + caller
9722 + " (pid=" + Binder.getCallingPid()
9723 + ") when registering receiver " + receiver);
9724 }
9725 }
9726
9727 List allSticky = null;
9728
9729 // Look for any matching sticky broadcasts...
9730 Iterator actions = filter.actionsIterator();
9731 if (actions != null) {
9732 while (actions.hasNext()) {
9733 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009734 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009735 }
9736 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009737 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009738 }
9739
9740 // The first sticky in the list is returned directly back to
9741 // the client.
9742 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9743
Joe Onorato8a9b2202010-02-26 18:56:32 -08009744 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009745 + ": " + sticky);
9746
9747 if (receiver == null) {
9748 return sticky;
9749 }
9750
9751 ReceiverList rl
9752 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9753 if (rl == null) {
9754 rl = new ReceiverList(this, callerApp,
9755 Binder.getCallingPid(),
9756 Binder.getCallingUid(), receiver);
9757 if (rl.app != null) {
9758 rl.app.receivers.add(rl);
9759 } else {
9760 try {
9761 receiver.asBinder().linkToDeath(rl, 0);
9762 } catch (RemoteException e) {
9763 return sticky;
9764 }
9765 rl.linkedToDeath = true;
9766 }
9767 mRegisteredReceivers.put(receiver.asBinder(), rl);
9768 }
9769 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9770 rl.add(bf);
9771 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009772 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009773 }
9774 mReceiverResolver.addFilter(bf);
9775
9776 // Enqueue broadcasts for all existing stickies that match
9777 // this filter.
9778 if (allSticky != null) {
9779 ArrayList receivers = new ArrayList();
9780 receivers.add(bf);
9781
9782 int N = allSticky.size();
9783 for (int i=0; i<N; i++) {
9784 Intent intent = (Intent)allSticky.get(i);
9785 BroadcastRecord r = new BroadcastRecord(intent, null,
9786 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009787 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 if (mParallelBroadcasts.size() == 0) {
9789 scheduleBroadcastsLocked();
9790 }
9791 mParallelBroadcasts.add(r);
9792 }
9793 }
9794
9795 return sticky;
9796 }
9797 }
9798
9799 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009800 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009801
9802 boolean doNext = false;
9803
9804 synchronized(this) {
9805 ReceiverList rl
9806 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9807 if (rl != null) {
9808 if (rl.curBroadcast != null) {
9809 BroadcastRecord r = rl.curBroadcast;
9810 doNext = finishReceiverLocked(
9811 receiver.asBinder(), r.resultCode, r.resultData,
9812 r.resultExtras, r.resultAbort, true);
9813 }
9814
9815 if (rl.app != null) {
9816 rl.app.receivers.remove(rl);
9817 }
9818 removeReceiverLocked(rl);
9819 if (rl.linkedToDeath) {
9820 rl.linkedToDeath = false;
9821 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9822 }
9823 }
9824 }
9825
9826 if (!doNext) {
9827 return;
9828 }
9829
9830 final long origId = Binder.clearCallingIdentity();
9831 processNextBroadcast(false);
9832 trimApplications();
9833 Binder.restoreCallingIdentity(origId);
9834 }
9835
9836 void removeReceiverLocked(ReceiverList rl) {
9837 mRegisteredReceivers.remove(rl.receiver.asBinder());
9838 int N = rl.size();
9839 for (int i=0; i<N; i++) {
9840 mReceiverResolver.removeFilter(rl.get(i));
9841 }
9842 }
9843
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009844 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9845 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9846 ProcessRecord r = mLruProcesses.get(i);
9847 if (r.thread != null) {
9848 try {
9849 r.thread.dispatchPackageBroadcast(cmd, packages);
9850 } catch (RemoteException ex) {
9851 }
9852 }
9853 }
9854 }
9855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009856 private final int broadcastIntentLocked(ProcessRecord callerApp,
9857 String callerPackage, Intent intent, String resolvedType,
9858 IIntentReceiver resultTo, int resultCode, String resultData,
9859 Bundle map, String requiredPermission,
9860 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9861 intent = new Intent(intent);
9862
Joe Onorato8a9b2202010-02-26 18:56:32 -08009863 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009864 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9865 + " ordered=" + ordered);
9866 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009867 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868 }
9869
9870 // Handle special intents: if this broadcast is from the package
9871 // manager about a package being removed, we need to remove all of
9872 // its activities from the history stack.
9873 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9874 intent.getAction());
9875 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9876 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009877 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878 || uidRemoved) {
9879 if (checkComponentPermission(
9880 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9881 callingPid, callingUid, -1)
9882 == PackageManager.PERMISSION_GRANTED) {
9883 if (uidRemoved) {
9884 final Bundle intentExtras = intent.getExtras();
9885 final int uid = intentExtras != null
9886 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9887 if (uid >= 0) {
9888 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9889 synchronized (bs) {
9890 bs.removeUidStatsLocked(uid);
9891 }
9892 }
9893 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009894 // If resources are unvailble just force stop all
9895 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009896 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009897 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9898 if (list != null && (list.length > 0)) {
9899 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009900 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009901 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009902 sendPackageBroadcastLocked(
9903 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009904 }
9905 } else {
9906 Uri data = intent.getData();
9907 String ssp;
9908 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9909 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9910 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009911 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009912 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009913 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9914 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9915 new String[] {ssp});
9916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009917 }
9918 }
9919 }
9920 } else {
9921 String msg = "Permission Denial: " + intent.getAction()
9922 + " broadcast from " + callerPackage + " (pid=" + callingPid
9923 + ", uid=" + callingUid + ")"
9924 + " requires "
9925 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009926 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009927 throw new SecurityException(msg);
9928 }
9929 }
9930
9931 /*
9932 * If this is the time zone changed action, queue up a message that will reset the timezone
9933 * of all currently running processes. This message will get queued up before the broadcast
9934 * happens.
9935 */
9936 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9937 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9938 }
9939
Dianne Hackborn854060af2009-07-09 18:14:31 -07009940 /*
9941 * Prevent non-system code (defined here to be non-persistent
9942 * processes) from sending protected broadcasts.
9943 */
9944 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9945 || callingUid == Process.SHELL_UID || callingUid == 0) {
9946 // Always okay.
9947 } else if (callerApp == null || !callerApp.persistent) {
9948 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009949 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009950 intent.getAction())) {
9951 String msg = "Permission Denial: not allowed to send broadcast "
9952 + intent.getAction() + " from pid="
9953 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009954 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009955 throw new SecurityException(msg);
9956 }
9957 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009958 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009959 return BROADCAST_SUCCESS;
9960 }
9961 }
9962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009963 // Add to the sticky list if requested.
9964 if (sticky) {
9965 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9966 callingPid, callingUid)
9967 != PackageManager.PERMISSION_GRANTED) {
9968 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9969 + callingPid + ", uid=" + callingUid
9970 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009971 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009972 throw new SecurityException(msg);
9973 }
9974 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009975 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 + " and enforce permission " + requiredPermission);
9977 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9978 }
9979 if (intent.getComponent() != null) {
9980 throw new SecurityException(
9981 "Sticky broadcasts can't target a specific component");
9982 }
9983 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9984 if (list == null) {
9985 list = new ArrayList<Intent>();
9986 mStickyBroadcasts.put(intent.getAction(), list);
9987 }
9988 int N = list.size();
9989 int i;
9990 for (i=0; i<N; i++) {
9991 if (intent.filterEquals(list.get(i))) {
9992 // This sticky already exists, replace it.
9993 list.set(i, new Intent(intent));
9994 break;
9995 }
9996 }
9997 if (i >= N) {
9998 list.add(new Intent(intent));
9999 }
10000 }
10001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 // Figure out who all will receive this broadcast.
10003 List receivers = null;
10004 List<BroadcastFilter> registeredReceivers = null;
10005 try {
10006 if (intent.getComponent() != null) {
10007 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010008 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010009 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010010 if (ai != null) {
10011 receivers = new ArrayList();
10012 ResolveInfo ri = new ResolveInfo();
10013 ri.activityInfo = ai;
10014 receivers.add(ri);
10015 }
10016 } else {
10017 // Need to resolve the intent to interested receivers...
10018 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10019 == 0) {
10020 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010021 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010022 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010023 }
Mihai Preda074edef2009-05-18 17:13:31 +020010024 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025 }
10026 } catch (RemoteException ex) {
10027 // pm is in same process, this will never happen.
10028 }
10029
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010030 final boolean replacePending =
10031 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10032
Joe Onorato8a9b2202010-02-26 18:56:32 -080010033 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010034 + " replacePending=" + replacePending);
10035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010036 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10037 if (!ordered && NR > 0) {
10038 // If we are not serializing this broadcast, then send the
10039 // registered receivers separately so they don't wait for the
10040 // components to be launched.
10041 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10042 callerPackage, callingPid, callingUid, requiredPermission,
10043 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010044 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010045 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010046 TAG, "Enqueueing parallel broadcast " + r
10047 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010048 boolean replaced = false;
10049 if (replacePending) {
10050 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10051 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010052 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010053 "***** DROPPING PARALLEL: " + intent);
10054 mParallelBroadcasts.set(i, r);
10055 replaced = true;
10056 break;
10057 }
10058 }
10059 }
10060 if (!replaced) {
10061 mParallelBroadcasts.add(r);
10062 scheduleBroadcastsLocked();
10063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 registeredReceivers = null;
10065 NR = 0;
10066 }
10067
10068 // Merge into one list.
10069 int ir = 0;
10070 if (receivers != null) {
10071 // A special case for PACKAGE_ADDED: do not allow the package
10072 // being added to see this broadcast. This prevents them from
10073 // using this as a back door to get run as soon as they are
10074 // installed. Maybe in the future we want to have a special install
10075 // broadcast or such for apps, but we'd like to deliberately make
10076 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010077 String skipPackages[] = null;
10078 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10079 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10080 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10081 Uri data = intent.getData();
10082 if (data != null) {
10083 String pkgName = data.getSchemeSpecificPart();
10084 if (pkgName != null) {
10085 skipPackages = new String[] { pkgName };
10086 }
10087 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010088 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010089 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010090 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010091 if (skipPackages != null && (skipPackages.length > 0)) {
10092 for (String skipPackage : skipPackages) {
10093 if (skipPackage != null) {
10094 int NT = receivers.size();
10095 for (int it=0; it<NT; it++) {
10096 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10097 if (curt.activityInfo.packageName.equals(skipPackage)) {
10098 receivers.remove(it);
10099 it--;
10100 NT--;
10101 }
10102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010103 }
10104 }
10105 }
10106
10107 int NT = receivers != null ? receivers.size() : 0;
10108 int it = 0;
10109 ResolveInfo curt = null;
10110 BroadcastFilter curr = null;
10111 while (it < NT && ir < NR) {
10112 if (curt == null) {
10113 curt = (ResolveInfo)receivers.get(it);
10114 }
10115 if (curr == null) {
10116 curr = registeredReceivers.get(ir);
10117 }
10118 if (curr.getPriority() >= curt.priority) {
10119 // Insert this broadcast record into the final list.
10120 receivers.add(it, curr);
10121 ir++;
10122 curr = null;
10123 it++;
10124 NT++;
10125 } else {
10126 // Skip to the next ResolveInfo in the final list.
10127 it++;
10128 curt = null;
10129 }
10130 }
10131 }
10132 while (ir < NR) {
10133 if (receivers == null) {
10134 receivers = new ArrayList();
10135 }
10136 receivers.add(registeredReceivers.get(ir));
10137 ir++;
10138 }
10139
10140 if ((receivers != null && receivers.size() > 0)
10141 || resultTo != null) {
10142 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10143 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010144 receivers, resultTo, resultCode, resultData, map, ordered,
10145 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010146 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010147 TAG, "Enqueueing ordered broadcast " + r
10148 + ": prev had " + mOrderedBroadcasts.size());
10149 if (DEBUG_BROADCAST) {
10150 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010151 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010152 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010153 boolean replaced = false;
10154 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010155 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010156 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010157 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010158 "***** DROPPING ORDERED: " + intent);
10159 mOrderedBroadcasts.set(i, r);
10160 replaced = true;
10161 break;
10162 }
10163 }
10164 }
10165 if (!replaced) {
10166 mOrderedBroadcasts.add(r);
10167 scheduleBroadcastsLocked();
10168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010169 }
10170
10171 return BROADCAST_SUCCESS;
10172 }
10173
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010174 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010175 // Refuse possible leaked file descriptors
10176 if (intent != null && intent.hasFileDescriptors() == true) {
10177 throw new IllegalArgumentException("File descriptors passed in Intent");
10178 }
10179
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010180 int flags = intent.getFlags();
10181
10182 if (!mProcessesReady) {
10183 // if the caller really truly claims to know what they're doing, go
10184 // ahead and allow the broadcast without launching any receivers
10185 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10186 intent = new Intent(intent);
10187 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10188 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10189 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10190 + " before boot completion");
10191 throw new IllegalStateException("Cannot broadcast before boot completed");
10192 }
10193 }
10194
10195 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10196 throw new IllegalArgumentException(
10197 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10198 }
10199
10200 return intent;
10201 }
10202
10203 public final int broadcastIntent(IApplicationThread caller,
10204 Intent intent, String resolvedType, IIntentReceiver resultTo,
10205 int resultCode, String resultData, Bundle map,
10206 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010207 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010208 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010210 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10211 final int callingPid = Binder.getCallingPid();
10212 final int callingUid = Binder.getCallingUid();
10213 final long origId = Binder.clearCallingIdentity();
10214 int res = broadcastIntentLocked(callerApp,
10215 callerApp != null ? callerApp.info.packageName : null,
10216 intent, resolvedType, resultTo,
10217 resultCode, resultData, map, requiredPermission, serialized,
10218 sticky, callingPid, callingUid);
10219 Binder.restoreCallingIdentity(origId);
10220 return res;
10221 }
10222 }
10223
10224 int broadcastIntentInPackage(String packageName, int uid,
10225 Intent intent, String resolvedType, IIntentReceiver resultTo,
10226 int resultCode, String resultData, Bundle map,
10227 String requiredPermission, boolean serialized, boolean sticky) {
10228 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010229 intent = verifyBroadcastLocked(intent);
10230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 final long origId = Binder.clearCallingIdentity();
10232 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10233 resultTo, resultCode, resultData, map, requiredPermission,
10234 serialized, sticky, -1, uid);
10235 Binder.restoreCallingIdentity(origId);
10236 return res;
10237 }
10238 }
10239
10240 public final void unbroadcastIntent(IApplicationThread caller,
10241 Intent intent) {
10242 // Refuse possible leaked file descriptors
10243 if (intent != null && intent.hasFileDescriptors() == true) {
10244 throw new IllegalArgumentException("File descriptors passed in Intent");
10245 }
10246
10247 synchronized(this) {
10248 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10249 != PackageManager.PERMISSION_GRANTED) {
10250 String msg = "Permission Denial: unbroadcastIntent() from pid="
10251 + Binder.getCallingPid()
10252 + ", uid=" + Binder.getCallingUid()
10253 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010254 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010255 throw new SecurityException(msg);
10256 }
10257 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10258 if (list != null) {
10259 int N = list.size();
10260 int i;
10261 for (i=0; i<N; i++) {
10262 if (intent.filterEquals(list.get(i))) {
10263 list.remove(i);
10264 break;
10265 }
10266 }
10267 }
10268 }
10269 }
10270
10271 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10272 String resultData, Bundle resultExtras, boolean resultAbort,
10273 boolean explicit) {
10274 if (mOrderedBroadcasts.size() == 0) {
10275 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010276 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010277 }
10278 return false;
10279 }
10280 BroadcastRecord r = mOrderedBroadcasts.get(0);
10281 if (r.receiver == null) {
10282 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010283 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 }
10285 return false;
10286 }
10287 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010288 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010289 return false;
10290 }
10291 int state = r.state;
10292 r.state = r.IDLE;
10293 if (state == r.IDLE) {
10294 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010295 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 }
10297 }
10298 r.receiver = null;
10299 r.intent.setComponent(null);
10300 if (r.curApp != null) {
10301 r.curApp.curReceiver = null;
10302 }
10303 if (r.curFilter != null) {
10304 r.curFilter.receiverList.curBroadcast = null;
10305 }
10306 r.curFilter = null;
10307 r.curApp = null;
10308 r.curComponent = null;
10309 r.curReceiver = null;
10310 mPendingBroadcast = null;
10311
10312 r.resultCode = resultCode;
10313 r.resultData = resultData;
10314 r.resultExtras = resultExtras;
10315 r.resultAbort = resultAbort;
10316
10317 // We will process the next receiver right now if this is finishing
10318 // an app receiver (which is always asynchronous) or after we have
10319 // come back from calling a receiver.
10320 return state == BroadcastRecord.APP_RECEIVE
10321 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10322 }
10323
10324 public void finishReceiver(IBinder who, int resultCode, String resultData,
10325 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010326 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327
10328 // Refuse possible leaked file descriptors
10329 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10330 throw new IllegalArgumentException("File descriptors passed in Bundle");
10331 }
10332
10333 boolean doNext;
10334
10335 final long origId = Binder.clearCallingIdentity();
10336
10337 synchronized(this) {
10338 doNext = finishReceiverLocked(
10339 who, resultCode, resultData, resultExtras, resultAbort, true);
10340 }
10341
10342 if (doNext) {
10343 processNextBroadcast(false);
10344 }
10345 trimApplications();
10346
10347 Binder.restoreCallingIdentity(origId);
10348 }
10349
10350 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10351 if (r.nextReceiver > 0) {
10352 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10353 if (curReceiver instanceof BroadcastFilter) {
10354 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010355 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010356 System.identityHashCode(r),
10357 r.intent.getAction(),
10358 r.nextReceiver - 1,
10359 System.identityHashCode(bf));
10360 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010361 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010362 System.identityHashCode(r),
10363 r.intent.getAction(),
10364 r.nextReceiver - 1,
10365 ((ResolveInfo)curReceiver).toString());
10366 }
10367 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010368 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010369 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010370 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 System.identityHashCode(r),
10372 r.intent.getAction(),
10373 r.nextReceiver,
10374 "NONE");
10375 }
10376 }
10377
10378 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010379 ProcessRecord app = null;
10380 String anrMessage = null;
10381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010382 synchronized (this) {
10383 if (mOrderedBroadcasts.size() == 0) {
10384 return;
10385 }
10386 long now = SystemClock.uptimeMillis();
10387 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010388 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010389 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010390 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010391 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010392 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010393 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010394 return;
10395 }
10396
Joe Onorato8a9b2202010-02-26 18:56:32 -080010397 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010398 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010399 r.anrCount++;
10400
10401 // Current receiver has passed its expiration date.
10402 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010403 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010404 return;
10405 }
10406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010407 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010408 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010409 logBroadcastReceiverDiscard(r);
10410 if (curReceiver instanceof BroadcastFilter) {
10411 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10412 if (bf.receiverList.pid != 0
10413 && bf.receiverList.pid != MY_PID) {
10414 synchronized (this.mPidsSelfLocked) {
10415 app = this.mPidsSelfLocked.get(
10416 bf.receiverList.pid);
10417 }
10418 }
10419 } else {
10420 app = r.curApp;
10421 }
10422
10423 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010424 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 }
10426
10427 if (mPendingBroadcast == r) {
10428 mPendingBroadcast = null;
10429 }
10430
10431 // Move on to the next receiver.
10432 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10433 r.resultExtras, r.resultAbort, true);
10434 scheduleBroadcastsLocked();
10435 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010436
10437 if (anrMessage != null) {
10438 appNotResponding(app, null, null, anrMessage);
10439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010440 }
10441
10442 private final void processCurBroadcastLocked(BroadcastRecord r,
10443 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010444 if (DEBUG_BROADCAST) Slog.v(TAG,
10445 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 if (app.thread == null) {
10447 throw new RemoteException();
10448 }
10449 r.receiver = app.thread.asBinder();
10450 r.curApp = app;
10451 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010452 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010453
10454 // Tell the application to launch this receiver.
10455 r.intent.setComponent(r.curComponent);
10456
10457 boolean started = false;
10458 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010459 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 "Delivering to component " + r.curComponent
10461 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010462 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010463 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10464 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010465 if (DEBUG_BROADCAST) Slog.v(TAG,
10466 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010467 started = true;
10468 } finally {
10469 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010470 if (DEBUG_BROADCAST) Slog.v(TAG,
10471 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010472 r.receiver = null;
10473 r.curApp = null;
10474 app.curReceiver = null;
10475 }
10476 }
10477
10478 }
10479
10480 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010481 Intent intent, int resultCode, String data, Bundle extras,
10482 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010483 if (app != null && app.thread != null) {
10484 // If we have an app thread, do the call through that so it is
10485 // correctly ordered with other one-way calls.
10486 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010487 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010488 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010489 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 }
10491 }
10492
10493 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10494 BroadcastFilter filter, boolean ordered) {
10495 boolean skip = false;
10496 if (filter.requiredPermission != null) {
10497 int perm = checkComponentPermission(filter.requiredPermission,
10498 r.callingPid, r.callingUid, -1);
10499 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010500 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 + r.intent.toString()
10502 + " from " + r.callerPackage + " (pid="
10503 + r.callingPid + ", uid=" + r.callingUid + ")"
10504 + " requires " + filter.requiredPermission
10505 + " due to registered receiver " + filter);
10506 skip = true;
10507 }
10508 }
10509 if (r.requiredPermission != null) {
10510 int perm = checkComponentPermission(r.requiredPermission,
10511 filter.receiverList.pid, filter.receiverList.uid, -1);
10512 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010513 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010514 + r.intent.toString()
10515 + " to " + filter.receiverList.app
10516 + " (pid=" + filter.receiverList.pid
10517 + ", uid=" + filter.receiverList.uid + ")"
10518 + " requires " + r.requiredPermission
10519 + " due to sender " + r.callerPackage
10520 + " (uid " + r.callingUid + ")");
10521 skip = true;
10522 }
10523 }
10524
10525 if (!skip) {
10526 // If this is not being sent as an ordered broadcast, then we
10527 // don't want to touch the fields that keep track of the current
10528 // state of ordered broadcasts.
10529 if (ordered) {
10530 r.receiver = filter.receiverList.receiver.asBinder();
10531 r.curFilter = filter;
10532 filter.receiverList.curBroadcast = r;
10533 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010534 if (filter.receiverList.app != null) {
10535 // Bump hosting application to no longer be in background
10536 // scheduling class. Note that we can't do that if there
10537 // isn't an app... but we can only be in that case for
10538 // things that directly call the IActivityManager API, which
10539 // are already core system stuff so don't matter for this.
10540 r.curApp = filter.receiverList.app;
10541 filter.receiverList.app.curReceiver = r;
10542 updateOomAdjLocked();
10543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010544 }
10545 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010546 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010547 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010548 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010549 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010550 }
10551 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10552 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010553 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010554 if (ordered) {
10555 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10556 }
10557 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010558 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010559 if (ordered) {
10560 r.receiver = null;
10561 r.curFilter = null;
10562 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010563 if (filter.receiverList.app != null) {
10564 filter.receiverList.app.curReceiver = null;
10565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010566 }
10567 }
10568 }
10569 }
10570
Dianne Hackborn12527f92009-11-11 17:39:50 -080010571 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10572 if (r.callingUid < 0) {
10573 // This was from a registerReceiver() call; ignore it.
10574 return;
10575 }
10576 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10577 MAX_BROADCAST_HISTORY-1);
10578 r.finishTime = SystemClock.uptimeMillis();
10579 mBroadcastHistory[0] = r;
10580 }
10581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010582 private final void processNextBroadcast(boolean fromMsg) {
10583 synchronized(this) {
10584 BroadcastRecord r;
10585
Joe Onorato8a9b2202010-02-26 18:56:32 -080010586 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010587 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010588 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010589
10590 updateCpuStats();
10591
10592 if (fromMsg) {
10593 mBroadcastsScheduled = false;
10594 }
10595
10596 // First, deliver any non-serialized broadcasts right away.
10597 while (mParallelBroadcasts.size() > 0) {
10598 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010599 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010600 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010601 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010602 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010603 for (int i=0; i<N; i++) {
10604 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010605 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010606 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010607 + target + ": " + r);
10608 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10609 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010610 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010611 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010612 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010613 }
10614
10615 // Now take care of the next serialized one...
10616
10617 // If we are waiting for a process to come up to handle the next
10618 // broadcast, then do nothing at this point. Just in case, we
10619 // check that the process we're waiting for still exists.
10620 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010621 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010622 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010623 + mPendingBroadcast.curApp);
10624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010625
10626 boolean isDead;
10627 synchronized (mPidsSelfLocked) {
10628 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10629 }
10630 if (!isDead) {
10631 // It's still alive, so keep waiting
10632 return;
10633 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010634 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010636 mPendingBroadcast.state = BroadcastRecord.IDLE;
10637 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010638 mPendingBroadcast = null;
10639 }
10640 }
10641
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010642 boolean looped = false;
10643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010644 do {
10645 if (mOrderedBroadcasts.size() == 0) {
10646 // No more broadcasts pending, so all done!
10647 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010648 if (looped) {
10649 // If we had finished the last ordered broadcast, then
10650 // make sure all processes have correct oom and sched
10651 // adjustments.
10652 updateOomAdjLocked();
10653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010654 return;
10655 }
10656 r = mOrderedBroadcasts.get(0);
10657 boolean forceReceive = false;
10658
10659 // Ensure that even if something goes awry with the timeout
10660 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010661 // and continue to make progress.
10662 //
10663 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10664 // receivers don't get executed with with timeouts. They're intended for
10665 // one time heavy lifting after system upgrades and can take
10666 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010668 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010669 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010670 if ((numReceivers > 0) &&
10671 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010672 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673 + " now=" + now
10674 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010675 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010676 + " intent=" + r.intent
10677 + " numReceivers=" + numReceivers
10678 + " nextReceiver=" + r.nextReceiver
10679 + " state=" + r.state);
10680 broadcastTimeout(); // forcibly finish this broadcast
10681 forceReceive = true;
10682 r.state = BroadcastRecord.IDLE;
10683 }
10684 }
10685
10686 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010687 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010688 "processNextBroadcast() called when not idle (state="
10689 + r.state + ")");
10690 return;
10691 }
10692
10693 if (r.receivers == null || r.nextReceiver >= numReceivers
10694 || r.resultAbort || forceReceive) {
10695 // No more receivers for this broadcast! Send the final
10696 // result if requested...
10697 if (r.resultTo != null) {
10698 try {
10699 if (DEBUG_BROADCAST) {
10700 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010701 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 + " seq=" + seq + " app=" + r.callerApp);
10703 }
10704 performReceive(r.callerApp, r.resultTo,
10705 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010706 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010708 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010709 }
10710 }
10711
Joe Onorato8a9b2202010-02-26 18:56:32 -080010712 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010713 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10714
Joe Onorato8a9b2202010-02-26 18:56:32 -080010715 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010716 + r);
10717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010718 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010719 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 mOrderedBroadcasts.remove(0);
10721 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010722 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010723 continue;
10724 }
10725 } while (r == null);
10726
10727 // Get the next receiver...
10728 int recIdx = r.nextReceiver++;
10729
10730 // Keep track of when this receiver started, and make sure there
10731 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010732 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010733 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010734 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735
Joe Onorato8a9b2202010-02-26 18:56:32 -080010736 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010737 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010738 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010739 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010740 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010741 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010742 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010743 }
10744
10745 Object nextReceiver = r.receivers.get(recIdx);
10746 if (nextReceiver instanceof BroadcastFilter) {
10747 // Simple case: this is a registered receiver who gets
10748 // a direct call.
10749 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010750 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010751 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010752 + filter + ": " + r);
10753 deliverToRegisteredReceiver(r, filter, r.ordered);
10754 if (r.receiver == null || !r.ordered) {
10755 // The receiver has already finished, so schedule to
10756 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010757 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10758 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010759 r.state = BroadcastRecord.IDLE;
10760 scheduleBroadcastsLocked();
10761 }
10762 return;
10763 }
10764
10765 // Hard case: need to instantiate the receiver, possibly
10766 // starting its application process to host it.
10767
10768 ResolveInfo info =
10769 (ResolveInfo)nextReceiver;
10770
10771 boolean skip = false;
10772 int perm = checkComponentPermission(info.activityInfo.permission,
10773 r.callingPid, r.callingUid,
10774 info.activityInfo.exported
10775 ? -1 : info.activityInfo.applicationInfo.uid);
10776 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010777 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 + r.intent.toString()
10779 + " from " + r.callerPackage + " (pid=" + r.callingPid
10780 + ", uid=" + r.callingUid + ")"
10781 + " requires " + info.activityInfo.permission
10782 + " due to receiver " + info.activityInfo.packageName
10783 + "/" + info.activityInfo.name);
10784 skip = true;
10785 }
10786 if (r.callingUid != Process.SYSTEM_UID &&
10787 r.requiredPermission != null) {
10788 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010789 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010790 checkPermission(r.requiredPermission,
10791 info.activityInfo.applicationInfo.packageName);
10792 } catch (RemoteException e) {
10793 perm = PackageManager.PERMISSION_DENIED;
10794 }
10795 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010796 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 + r.intent + " to "
10798 + info.activityInfo.applicationInfo.packageName
10799 + " requires " + r.requiredPermission
10800 + " due to sender " + r.callerPackage
10801 + " (uid " + r.callingUid + ")");
10802 skip = true;
10803 }
10804 }
10805 if (r.curApp != null && r.curApp.crashing) {
10806 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010807 if (DEBUG_BROADCAST) Slog.v(TAG,
10808 "Skipping deliver ordered " + r + " to " + r.curApp
10809 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810 skip = true;
10811 }
10812
10813 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010814 if (DEBUG_BROADCAST) Slog.v(TAG,
10815 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010816 r.receiver = null;
10817 r.curFilter = null;
10818 r.state = BroadcastRecord.IDLE;
10819 scheduleBroadcastsLocked();
10820 return;
10821 }
10822
10823 r.state = BroadcastRecord.APP_RECEIVE;
10824 String targetProcess = info.activityInfo.processName;
10825 r.curComponent = new ComponentName(
10826 info.activityInfo.applicationInfo.packageName,
10827 info.activityInfo.name);
10828 r.curReceiver = info.activityInfo;
10829
10830 // Is this receiver's application already running?
10831 ProcessRecord app = getProcessRecordLocked(targetProcess,
10832 info.activityInfo.applicationInfo.uid);
10833 if (app != null && app.thread != null) {
10834 try {
10835 processCurBroadcastLocked(r, app);
10836 return;
10837 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010838 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 + r.curComponent, e);
10840 }
10841
10842 // If a dead object exception was thrown -- fall through to
10843 // restart the application.
10844 }
10845
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010846 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010847 if (DEBUG_BROADCAST) Slog.v(TAG,
10848 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010849 if ((r.curApp=startProcessLocked(targetProcess,
10850 info.activityInfo.applicationInfo, true,
10851 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010852 "broadcast", r.curComponent,
10853 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10854 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010855 // Ah, this recipient is unavailable. Finish it if necessary,
10856 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010857 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010858 + info.activityInfo.applicationInfo.packageName + "/"
10859 + info.activityInfo.applicationInfo.uid + " for broadcast "
10860 + r.intent + ": process is bad");
10861 logBroadcastReceiverDiscard(r);
10862 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10863 r.resultExtras, r.resultAbort, true);
10864 scheduleBroadcastsLocked();
10865 r.state = BroadcastRecord.IDLE;
10866 return;
10867 }
10868
10869 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010870 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010871 }
10872 }
10873
10874 // =========================================================
10875 // INSTRUMENTATION
10876 // =========================================================
10877
10878 public boolean startInstrumentation(ComponentName className,
10879 String profileFile, int flags, Bundle arguments,
10880 IInstrumentationWatcher watcher) {
10881 // Refuse possible leaked file descriptors
10882 if (arguments != null && arguments.hasFileDescriptors()) {
10883 throw new IllegalArgumentException("File descriptors passed in Bundle");
10884 }
10885
10886 synchronized(this) {
10887 InstrumentationInfo ii = null;
10888 ApplicationInfo ai = null;
10889 try {
10890 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010891 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010893 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 } catch (PackageManager.NameNotFoundException e) {
10895 }
10896 if (ii == null) {
10897 reportStartInstrumentationFailure(watcher, className,
10898 "Unable to find instrumentation info for: " + className);
10899 return false;
10900 }
10901 if (ai == null) {
10902 reportStartInstrumentationFailure(watcher, className,
10903 "Unable to find instrumentation target package: " + ii.targetPackage);
10904 return false;
10905 }
10906
10907 int match = mContext.getPackageManager().checkSignatures(
10908 ii.targetPackage, ii.packageName);
10909 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10910 String msg = "Permission Denial: starting instrumentation "
10911 + className + " from pid="
10912 + Binder.getCallingPid()
10913 + ", uid=" + Binder.getCallingPid()
10914 + " not allowed because package " + ii.packageName
10915 + " does not have a signature matching the target "
10916 + ii.targetPackage;
10917 reportStartInstrumentationFailure(watcher, className, msg);
10918 throw new SecurityException(msg);
10919 }
10920
10921 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010922 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 ProcessRecord app = addAppLocked(ai);
10924 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010925 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 app.instrumentationProfileFile = profileFile;
10927 app.instrumentationArguments = arguments;
10928 app.instrumentationWatcher = watcher;
10929 app.instrumentationResultClass = className;
10930 Binder.restoreCallingIdentity(origId);
10931 }
10932
10933 return true;
10934 }
10935
10936 /**
10937 * Report errors that occur while attempting to start Instrumentation. Always writes the
10938 * error to the logs, but if somebody is watching, send the report there too. This enables
10939 * the "am" command to report errors with more information.
10940 *
10941 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10942 * @param cn The component name of the instrumentation.
10943 * @param report The error report.
10944 */
10945 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10946 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010947 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 try {
10949 if (watcher != null) {
10950 Bundle results = new Bundle();
10951 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10952 results.putString("Error", report);
10953 watcher.instrumentationStatus(cn, -1, results);
10954 }
10955 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010956 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 }
10958 }
10959
10960 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10961 if (app.instrumentationWatcher != null) {
10962 try {
10963 // NOTE: IInstrumentationWatcher *must* be oneway here
10964 app.instrumentationWatcher.instrumentationFinished(
10965 app.instrumentationClass,
10966 resultCode,
10967 results);
10968 } catch (RemoteException e) {
10969 }
10970 }
10971 app.instrumentationWatcher = null;
10972 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010973 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010974 app.instrumentationProfileFile = null;
10975 app.instrumentationArguments = null;
10976
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010977 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 }
10979
10980 public void finishInstrumentation(IApplicationThread target,
10981 int resultCode, Bundle results) {
10982 // Refuse possible leaked file descriptors
10983 if (results != null && results.hasFileDescriptors()) {
10984 throw new IllegalArgumentException("File descriptors passed in Intent");
10985 }
10986
10987 synchronized(this) {
10988 ProcessRecord app = getRecordForAppLocked(target);
10989 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010990 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010991 return;
10992 }
10993 final long origId = Binder.clearCallingIdentity();
10994 finishInstrumentationLocked(app, resultCode, results);
10995 Binder.restoreCallingIdentity(origId);
10996 }
10997 }
10998
10999 // =========================================================
11000 // CONFIGURATION
11001 // =========================================================
11002
11003 public ConfigurationInfo getDeviceConfigurationInfo() {
11004 ConfigurationInfo config = new ConfigurationInfo();
11005 synchronized (this) {
11006 config.reqTouchScreen = mConfiguration.touchscreen;
11007 config.reqKeyboardType = mConfiguration.keyboard;
11008 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011009 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11010 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11012 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011013 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11014 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011015 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11016 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011017 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 }
11019 return config;
11020 }
11021
11022 public Configuration getConfiguration() {
11023 Configuration ci;
11024 synchronized(this) {
11025 ci = new Configuration(mConfiguration);
11026 }
11027 return ci;
11028 }
11029
11030 public void updateConfiguration(Configuration values) {
11031 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11032 "updateConfiguration()");
11033
11034 synchronized(this) {
11035 if (values == null && mWindowManager != null) {
11036 // sentinel: fetch the current configuration from the window manager
11037 values = mWindowManager.computeNewConfiguration();
11038 }
11039
11040 final long origId = Binder.clearCallingIdentity();
11041 updateConfigurationLocked(values, null);
11042 Binder.restoreCallingIdentity(origId);
11043 }
11044 }
11045
11046 /**
11047 * Do either or both things: (1) change the current configuration, and (2)
11048 * make sure the given activity is running with the (now) current
11049 * configuration. Returns true if the activity has been left running, or
11050 * false if <var>starting</var> is being destroyed to match the new
11051 * configuration.
11052 */
11053 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011054 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011055 int changes = 0;
11056
11057 boolean kept = true;
11058
11059 if (values != null) {
11060 Configuration newConfig = new Configuration(mConfiguration);
11061 changes = newConfig.updateFrom(values);
11062 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011063 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011064 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 }
11066
Doug Zongker2bec3d42009-12-04 12:52:44 -080011067 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011068
11069 if (values.locale != null) {
11070 saveLocaleLocked(values.locale,
11071 !values.locale.equals(mConfiguration.locale),
11072 values.userSetLocale);
11073 }
11074
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011075 mConfigurationSeq++;
11076 if (mConfigurationSeq <= 0) {
11077 mConfigurationSeq = 1;
11078 }
11079 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011081 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011082
11083 AttributeCache ac = AttributeCache.instance();
11084 if (ac != null) {
11085 ac.updateConfiguration(mConfiguration);
11086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011088 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11089 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11090 msg.obj = new Configuration(mConfiguration);
11091 mHandler.sendMessage(msg);
11092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011093
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011094 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11095 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011096 try {
11097 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011098 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011099 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100 app.thread.scheduleConfigurationChanged(mConfiguration);
11101 }
11102 } catch (Exception e) {
11103 }
11104 }
11105 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011106 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11107 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011108 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11109 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011110 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11111 broadcastIntentLocked(null, null,
11112 new Intent(Intent.ACTION_LOCALE_CHANGED),
11113 null, null, 0, null, null,
11114 null, false, false, MY_PID, Process.SYSTEM_UID);
11115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 }
11117 }
11118
11119 if (changes != 0 && starting == null) {
11120 // If the configuration changed, and the caller is not already
11121 // in the process of starting an activity, then find the top
11122 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011123 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011124 }
11125
11126 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011127 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 if (kept) {
11129 // If this didn't result in the starting activity being
11130 // destroyed, then we need to make sure at this point that all
11131 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011132 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011133 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011134 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011135 }
11136 }
11137
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011138 if (values != null && mWindowManager != null) {
11139 mWindowManager.setNewConfiguration(mConfiguration);
11140 }
11141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 return kept;
11143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144
11145 /**
11146 * Save the locale. You must be inside a synchronized (this) block.
11147 */
11148 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11149 if(isDiff) {
11150 SystemProperties.set("user.language", l.getLanguage());
11151 SystemProperties.set("user.region", l.getCountry());
11152 }
11153
11154 if(isPersist) {
11155 SystemProperties.set("persist.sys.language", l.getLanguage());
11156 SystemProperties.set("persist.sys.country", l.getCountry());
11157 SystemProperties.set("persist.sys.localevar", l.getVariant());
11158 }
11159 }
11160
11161 // =========================================================
11162 // LIFETIME MANAGEMENT
11163 // =========================================================
11164
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011165 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11166 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011167 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011168 // This adjustment has already been computed. If we are calling
11169 // from the top, we may have already computed our adjustment with
11170 // an earlier hidden adjustment that isn't really for us... if
11171 // so, use the new hidden adjustment.
11172 if (!recursed && app.hidden) {
11173 app.curAdj = hiddenAdj;
11174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011175 return app.curAdj;
11176 }
11177
11178 if (app.thread == null) {
11179 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011180 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011181 return (app.curAdj=EMPTY_APP_ADJ);
11182 }
11183
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011184 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11185 // The max adjustment doesn't allow this app to be anything
11186 // below foreground, so it is not worth doing work for it.
11187 app.adjType = "fixed";
11188 app.adjSeq = mAdjSeq;
11189 app.curRawAdj = app.maxAdj;
11190 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11191 return (app.curAdj=app.maxAdj);
11192 }
11193
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011194 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011195 app.adjSource = null;
11196 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011197 app.empty = false;
11198 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199
The Android Open Source Project4df24232009-03-05 14:34:35 -080011200 // Determine the importance of the process, starting with most
11201 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011203 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011205 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011206 // The last app on the list is the foreground app.
11207 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011208 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011209 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011210 } else if (app.instrumentationClass != null) {
11211 // Don't want to kill running instrumentation.
11212 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011213 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011214 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011215 } else if (app.persistentActivities > 0) {
11216 // Special persistent activities... shouldn't be used these days.
11217 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011218 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011219 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 } else if (app.curReceiver != null ||
11221 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11222 // An app that is currently receiving a broadcast also
11223 // counts as being in the foreground.
11224 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011225 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011226 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 } else if (app.executingServices.size() > 0) {
11228 // An app that is currently executing a service callback also
11229 // counts as being in the foreground.
11230 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011231 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011232 app.adjType = "exec-service";
11233 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011234 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011235 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011236 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011237 app.adjType = "foreground-service";
11238 } else if (app.forcingToForeground != null) {
11239 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011240 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011241 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011242 app.adjType = "force-foreground";
11243 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011244 } else if (app == mHeavyWeightProcess) {
11245 // We don't want to kill the current heavy-weight process.
11246 adj = HEAVY_WEIGHT_APP_ADJ;
11247 schedGroup = Process.THREAD_GROUP_DEFAULT;
11248 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011249 } else if (app == mHomeProcess) {
11250 // This process is hosting what we currently consider to be the
11251 // home app, so we don't want to let it go into the background.
11252 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011253 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011254 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011255 } else if ((N=app.activities.size()) != 0) {
11256 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011257 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011259 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011260 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011261 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011263 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011265 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011267 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011268 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 break;
11270 }
11271 }
11272 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011273 // A very not-needed process. If this is lower in the lru list,
11274 // we will push it in to the empty bucket.
11275 app.hidden = true;
11276 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011277 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011278 adj = hiddenAdj;
11279 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011280 }
11281
Joe Onorato8a9b2202010-02-26 18:56:32 -080011282 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011283
The Android Open Source Project4df24232009-03-05 14:34:35 -080011284 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 // there are applications dependent on our services or providers, but
11286 // this gives us a baseline and makes sure we don't get into an
11287 // infinite recursion.
11288 app.adjSeq = mAdjSeq;
11289 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011290
Christopher Tate6fa95972009-06-05 18:43:55 -070011291 if (mBackupTarget != null && app == mBackupTarget.app) {
11292 // If possible we want to avoid killing apps while they're being backed up
11293 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011294 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011295 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011296 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011297 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011298 }
11299 }
11300
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011301 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11302 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011303 final long now = SystemClock.uptimeMillis();
11304 // This process is more important if the top activity is
11305 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011306 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011307 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011308 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011309 if (s.startRequested) {
11310 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11311 // This service has seen some activity within
11312 // recent memory, so we will keep its process ahead
11313 // of the background processes.
11314 if (adj > SECONDARY_SERVER_ADJ) {
11315 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011316 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011317 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011318 }
11319 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011320 // If we have let the service slide into the background
11321 // state, still have some text describing what it is doing
11322 // even though the service no longer has an impact.
11323 if (adj > SECONDARY_SERVER_ADJ) {
11324 app.adjType = "started-bg-services";
11325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011326 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011327 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11328 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011329 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011330 = s.connections.values().iterator();
11331 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011332 ArrayList<ConnectionRecord> clist = kt.next();
11333 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11334 // XXX should compute this based on the max of
11335 // all connected clients.
11336 ConnectionRecord cr = clist.get(i);
11337 if (cr.binding.client == app) {
11338 // Binding to ourself is not interesting.
11339 continue;
11340 }
11341 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11342 ProcessRecord client = cr.binding.client;
11343 int myHiddenAdj = hiddenAdj;
11344 if (myHiddenAdj > client.hiddenAdj) {
11345 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11346 myHiddenAdj = client.hiddenAdj;
11347 } else {
11348 myHiddenAdj = VISIBLE_APP_ADJ;
11349 }
11350 }
11351 int clientAdj = computeOomAdjLocked(
11352 client, myHiddenAdj, TOP_APP, true);
11353 if (adj > clientAdj) {
11354 adj = clientAdj >= VISIBLE_APP_ADJ
11355 ? clientAdj : VISIBLE_APP_ADJ;
11356 if (!client.hidden) {
11357 app.hidden = false;
11358 }
11359 app.adjType = "service";
11360 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11361 .REASON_SERVICE_IN_USE;
11362 app.adjSource = cr.binding.client;
11363 app.adjTarget = s.name;
11364 }
11365 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11366 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11367 schedGroup = Process.THREAD_GROUP_DEFAULT;
11368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 }
11370 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011371 ActivityRecord a = cr.activity;
11372 //if (a != null) {
11373 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11374 //}
11375 if (a != null && adj > FOREGROUND_APP_ADJ &&
11376 (a.state == ActivityState.RESUMED
11377 || a.state == ActivityState.PAUSING)) {
11378 adj = FOREGROUND_APP_ADJ;
11379 schedGroup = Process.THREAD_GROUP_DEFAULT;
11380 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011381 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011382 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11383 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011384 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011385 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 }
11388 }
11389 }
11390 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011391
11392 // Finally, f this process has active services running in it, we
11393 // would like to avoid killing it unless it would prevent the current
11394 // application from running. By default we put the process in
11395 // with the rest of the background processes; as we scan through
11396 // its services we may bump it up from there.
11397 if (adj > hiddenAdj) {
11398 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011399 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011400 app.adjType = "bg-services";
11401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011402 }
11403
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011404 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11405 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011406 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011407 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11408 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011409 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410 if (cpr.clients.size() != 0) {
11411 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11412 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11413 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011414 if (client == app) {
11415 // Being our own client is not interesting.
11416 continue;
11417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 int myHiddenAdj = hiddenAdj;
11419 if (myHiddenAdj > client.hiddenAdj) {
11420 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11421 myHiddenAdj = client.hiddenAdj;
11422 } else {
11423 myHiddenAdj = FOREGROUND_APP_ADJ;
11424 }
11425 }
11426 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011427 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011428 if (adj > clientAdj) {
11429 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011430 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011431 if (!client.hidden) {
11432 app.hidden = false;
11433 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011434 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011435 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11436 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011437 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011438 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011439 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011440 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11441 schedGroup = Process.THREAD_GROUP_DEFAULT;
11442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011443 }
11444 }
11445 // If the provider has external (non-framework) process
11446 // dependencies, ensure that its adjustment is at least
11447 // FOREGROUND_APP_ADJ.
11448 if (cpr.externals != 0) {
11449 if (adj > FOREGROUND_APP_ADJ) {
11450 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011451 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011452 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011453 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011454 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011455 }
11456 }
11457 }
11458 }
11459
11460 app.curRawAdj = adj;
11461
Joe Onorato8a9b2202010-02-26 18:56:32 -080011462 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011463 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11464 if (adj > app.maxAdj) {
11465 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011466 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011467 schedGroup = Process.THREAD_GROUP_DEFAULT;
11468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011469 }
11470
11471 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011472 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 return adj;
11475 }
11476
11477 /**
11478 * Ask a given process to GC right now.
11479 */
11480 final void performAppGcLocked(ProcessRecord app) {
11481 try {
11482 app.lastRequestedGc = SystemClock.uptimeMillis();
11483 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011484 if (app.reportLowMemory) {
11485 app.reportLowMemory = false;
11486 app.thread.scheduleLowMemory();
11487 } else {
11488 app.thread.processInBackground();
11489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011490 }
11491 } catch (Exception e) {
11492 // whatever.
11493 }
11494 }
11495
11496 /**
11497 * Returns true if things are idle enough to perform GCs.
11498 */
Josh Bartel7f208742010-02-25 11:01:44 -060011499 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 return mParallelBroadcasts.size() == 0
11501 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011502 && (mSleeping || (mMainStack.mResumedActivity != null &&
11503 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011504 }
11505
11506 /**
11507 * Perform GCs on all processes that are waiting for it, but only
11508 * if things are idle.
11509 */
11510 final void performAppGcsLocked() {
11511 final int N = mProcessesToGc.size();
11512 if (N <= 0) {
11513 return;
11514 }
Josh Bartel7f208742010-02-25 11:01:44 -060011515 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011516 while (mProcessesToGc.size() > 0) {
11517 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011518 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011519 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11520 <= SystemClock.uptimeMillis()) {
11521 // To avoid spamming the system, we will GC processes one
11522 // at a time, waiting a few seconds between each.
11523 performAppGcLocked(proc);
11524 scheduleAppGcsLocked();
11525 return;
11526 } else {
11527 // It hasn't been long enough since we last GCed this
11528 // process... put it in the list to wait for its time.
11529 addProcessToGcListLocked(proc);
11530 break;
11531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 }
11533 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011534
11535 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 }
11537 }
11538
11539 /**
11540 * If all looks good, perform GCs on all processes waiting for them.
11541 */
11542 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011543 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544 performAppGcsLocked();
11545 return;
11546 }
11547 // Still not idle, wait some more.
11548 scheduleAppGcsLocked();
11549 }
11550
11551 /**
11552 * Schedule the execution of all pending app GCs.
11553 */
11554 final void scheduleAppGcsLocked() {
11555 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011556
11557 if (mProcessesToGc.size() > 0) {
11558 // Schedule a GC for the time to the next process.
11559 ProcessRecord proc = mProcessesToGc.get(0);
11560 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11561
11562 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11563 long now = SystemClock.uptimeMillis();
11564 if (when < (now+GC_TIMEOUT)) {
11565 when = now + GC_TIMEOUT;
11566 }
11567 mHandler.sendMessageAtTime(msg, when);
11568 }
11569 }
11570
11571 /**
11572 * Add a process to the array of processes waiting to be GCed. Keeps the
11573 * list in sorted order by the last GC time. The process can't already be
11574 * on the list.
11575 */
11576 final void addProcessToGcListLocked(ProcessRecord proc) {
11577 boolean added = false;
11578 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11579 if (mProcessesToGc.get(i).lastRequestedGc <
11580 proc.lastRequestedGc) {
11581 added = true;
11582 mProcessesToGc.add(i+1, proc);
11583 break;
11584 }
11585 }
11586 if (!added) {
11587 mProcessesToGc.add(0, proc);
11588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011589 }
11590
11591 /**
11592 * Set up to ask a process to GC itself. This will either do it
11593 * immediately, or put it on the list of processes to gc the next
11594 * time things are idle.
11595 */
11596 final void scheduleAppGcLocked(ProcessRecord app) {
11597 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011598 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599 return;
11600 }
11601 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011602 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011603 scheduleAppGcsLocked();
11604 }
11605 }
11606
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011607 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11608 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11609 if (mLastWakeLockCheckTime == 0) {
11610 doKills = false;
11611 }
11612 if (stats.isScreenOn()) {
11613 doKills = false;
11614 }
11615 final long curRealtime = SystemClock.elapsedRealtime();
11616 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11617 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011618 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011619 doKills = false;
11620 }
11621 int i = mLruProcesses.size();
11622 while (i > 0) {
11623 i--;
11624 ProcessRecord app = mLruProcesses.get(i);
11625 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11626 long wtime;
11627 synchronized (stats) {
11628 wtime = stats.getProcessWakeTime(app.info.uid,
11629 app.pid, curRealtime);
11630 }
11631 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011632 if (false) {
11633 StringBuilder sb = new StringBuilder(128);
11634 sb.append("Wake for ");
11635 app.toShortString(sb);
11636 sb.append(": over ");
11637 TimeUtils.formatDuration(timeSince, sb);
11638 sb.append(" used ");
11639 TimeUtils.formatDuration(timeUsed, sb);
11640 sb.append(" (");
11641 sb.append((timeUsed*100)/timeSince);
11642 sb.append("%)");
11643 Slog.i(TAG, sb.toString());
11644 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011645 // If a process has held a wake lock for more
11646 // than 50% of the time during this period,
11647 // that sounds pad. Kill!
11648 if (doKills && timeSince > 0
11649 && ((timeUsed*100)/timeSince) >= 50) {
11650 Slog.i(TAG, "Excessive wake lock in " + app.processName
11651 + " (pid " + app.pid + "): held " + timeUsed
11652 + " during " + timeSince);
11653 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11654 app.processName, app.setAdj, "excessive wake lock");
11655 Process.killProcessQuiet(app.pid);
11656 } else {
11657 app.lastWakeTime = wtime;
11658 }
11659 }
11660 }
11661 }
11662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663 private final boolean updateOomAdjLocked(
11664 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11665 app.hiddenAdj = hiddenAdj;
11666
11667 if (app.thread == null) {
11668 return true;
11669 }
11670
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011671 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011673 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011674 if (app.curRawAdj != app.setRawAdj) {
11675 if (app.curRawAdj > FOREGROUND_APP_ADJ
11676 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11677 // If this app is transitioning from foreground to
11678 // non-foreground, have it do a gc.
11679 scheduleAppGcLocked(app);
11680 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11681 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11682 // Likewise do a gc when an app is moving in to the
11683 // background (such as a service stopping).
11684 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011685 // And note its current wake lock time.
11686 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11687 synchronized (stats) {
11688 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11689 app.pid, SystemClock.elapsedRealtime());
11690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011691 }
11692 app.setRawAdj = app.curRawAdj;
11693 }
11694 if (adj != app.setAdj) {
11695 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011696 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011697 TAG, "Set app " + app.processName +
11698 " oom adj to " + adj);
11699 app.setAdj = adj;
11700 } else {
11701 return false;
11702 }
11703 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011704 if (app.setSchedGroup != app.curSchedGroup) {
11705 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011706 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011707 "Setting process group of " + app.processName
11708 + " to " + app.curSchedGroup);
11709 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011710 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011711 try {
11712 Process.setProcessGroup(app.pid, app.curSchedGroup);
11713 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011714 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011715 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011716 e.printStackTrace();
11717 } finally {
11718 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011719 }
11720 }
11721 if (false) {
11722 if (app.thread != null) {
11723 try {
11724 app.thread.setSchedulingGroup(app.curSchedGroup);
11725 } catch (RemoteException e) {
11726 }
11727 }
11728 }
11729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 }
11731
11732 return true;
11733 }
11734
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011735 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011736 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011738 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011739 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011740 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011741 }
11742 }
11743 return resumedActivity;
11744 }
11745
11746 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011747 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011748 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11749 int curAdj = app.curAdj;
11750 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11751 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11752
11753 mAdjSeq++;
11754
11755 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11756 if (res) {
11757 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11758 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11759 if (nowHidden != wasHidden) {
11760 // Changed to/from hidden state, so apps after it in the LRU
11761 // list may also be changed.
11762 updateOomAdjLocked();
11763 }
11764 }
11765 return res;
11766 }
11767
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011768 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011769 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011770 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11772
11773 if (false) {
11774 RuntimeException e = new RuntimeException();
11775 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011776 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011777 }
11778
11779 mAdjSeq++;
11780
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011781 // Let's determine how many processes we have running vs.
11782 // how many slots we have for background processes; we may want
11783 // to put multiple processes in a slot of there are enough of
11784 // them.
11785 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11786 int factor = (mLruProcesses.size()-4)/numSlots;
11787 if (factor < 1) factor = 1;
11788 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011789 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011791 // First try updating the OOM adjustment for each of the
11792 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011793 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11795 while (i > 0) {
11796 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011797 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011798 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011799 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011800 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011801 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011802 step++;
11803 if (step >= factor) {
11804 step = 0;
11805 curHiddenAdj++;
11806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011808 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011809 if (!app.killedBackground) {
11810 numHidden++;
11811 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011812 Slog.i(TAG, "No longer want " + app.processName
11813 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011814 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11815 app.processName, app.setAdj, "too many background");
11816 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011817 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011818 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011819 }
11820 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011821 } else {
11822 didOomAdj = false;
11823 }
11824 }
11825
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011826 // If we return false, we will fall back on killing processes to
11827 // have a fixed limit. Do this if a limit has been requested; else
11828 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011829 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11830 }
11831
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011832 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011833 synchronized (this) {
11834 int i;
11835
11836 // First remove any unused application processes whose package
11837 // has been removed.
11838 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11839 final ProcessRecord app = mRemovedProcesses.get(i);
11840 if (app.activities.size() == 0
11841 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011842 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 TAG, "Exiting empty application process "
11844 + app.processName + " ("
11845 + (app.thread != null ? app.thread.asBinder() : null)
11846 + ")\n");
11847 if (app.pid > 0 && app.pid != MY_PID) {
11848 Process.killProcess(app.pid);
11849 } else {
11850 try {
11851 app.thread.scheduleExit();
11852 } catch (Exception e) {
11853 // Ignore exceptions.
11854 }
11855 }
11856 cleanUpApplicationRecordLocked(app, false, -1);
11857 mRemovedProcesses.remove(i);
11858
11859 if (app.persistent) {
11860 if (app.persistent) {
11861 addAppLocked(app.info);
11862 }
11863 }
11864 }
11865 }
11866
11867 // Now try updating the OOM adjustment for each of the
11868 // application processes based on their current state.
11869 // If the setOomAdj() API is not supported, then go with our
11870 // back-up plan...
11871 if (!updateOomAdjLocked()) {
11872
11873 // Count how many processes are running services.
11874 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011875 for (i=mLruProcesses.size()-1; i>=0; i--) {
11876 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011877
11878 if (app.persistent || app.services.size() != 0
11879 || app.curReceiver != null
11880 || app.persistentActivities > 0) {
11881 // Don't count processes holding services against our
11882 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011883 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011884 TAG, "Not trimming app " + app + " with services: "
11885 + app.services);
11886 numServiceProcs++;
11887 }
11888 }
11889
11890 int curMaxProcs = mProcessLimit;
11891 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11892 if (mAlwaysFinishActivities) {
11893 curMaxProcs = 1;
11894 }
11895 curMaxProcs += numServiceProcs;
11896
11897 // Quit as many processes as we can to get down to the desired
11898 // process count. First remove any processes that no longer
11899 // have activites running in them.
11900 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011901 i<mLruProcesses.size()
11902 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011904 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011905 // Quit an application only if it is not currently
11906 // running any activities.
11907 if (!app.persistent && app.activities.size() == 0
11908 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011909 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 TAG, "Exiting empty application process "
11911 + app.processName + " ("
11912 + (app.thread != null ? app.thread.asBinder() : null)
11913 + ")\n");
11914 if (app.pid > 0 && app.pid != MY_PID) {
11915 Process.killProcess(app.pid);
11916 } else {
11917 try {
11918 app.thread.scheduleExit();
11919 } catch (Exception e) {
11920 // Ignore exceptions.
11921 }
11922 }
11923 // todo: For now we assume the application is not buggy
11924 // or evil, and will quit as a result of our request.
11925 // Eventually we need to drive this off of the death
11926 // notification, and kill the process if it takes too long.
11927 cleanUpApplicationRecordLocked(app, false, i);
11928 i--;
11929 }
11930 }
11931
11932 // If we still have too many processes, now from the least
11933 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011934 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011935 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011936 " of " + curMaxProcs + " processes");
11937 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011938 i<mLruProcesses.size()
11939 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011940 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011941 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011942 // Quit the application only if we have a state saved for
11943 // all of its activities.
11944 boolean canQuit = !app.persistent && app.curReceiver == null
11945 && app.services.size() == 0
11946 && app.persistentActivities == 0;
11947 int NUMA = app.activities.size();
11948 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011949 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011950 TAG, "Looking to quit " + app.processName);
11951 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011952 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011953 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 TAG, " " + r.intent.getComponent().flattenToShortString()
11955 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11956 canQuit = (r.haveState || !r.stateNotNeeded)
11957 && !r.visible && r.stopped;
11958 }
11959 if (canQuit) {
11960 // Finish all of the activities, and then the app itself.
11961 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011962 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011963 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011964 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011965 }
11966 r.resultTo = null;
11967 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011968 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011969 + app.processName + " ("
11970 + (app.thread != null ? app.thread.asBinder() : null)
11971 + ")\n");
11972 if (app.pid > 0 && app.pid != MY_PID) {
11973 Process.killProcess(app.pid);
11974 } else {
11975 try {
11976 app.thread.scheduleExit();
11977 } catch (Exception e) {
11978 // Ignore exceptions.
11979 }
11980 }
11981 // todo: For now we assume the application is not buggy
11982 // or evil, and will quit as a result of our request.
11983 // Eventually we need to drive this off of the death
11984 // notification, and kill the process if it takes too long.
11985 cleanUpApplicationRecordLocked(app, false, i);
11986 i--;
11987 //dump();
11988 }
11989 }
11990
11991 }
11992
11993 int curMaxActivities = MAX_ACTIVITIES;
11994 if (mAlwaysFinishActivities) {
11995 curMaxActivities = 1;
11996 }
11997
11998 // Finally, if there are too many activities now running, try to
11999 // finish as many as we can to get back down to the limit.
12000 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012001 i<mMainStack.mLRUActivities.size()
12002 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012003 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012004 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012005 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012006
12007 // We can finish this one if we have its icicle saved and
12008 // it is not persistent.
12009 if ((r.haveState || !r.stateNotNeeded) && !r.visible
12010 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012011 final int origSize = mMainStack.mLRUActivities.size();
12012 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012013
12014 // This will remove it from the LRU list, so keep
12015 // our index at the same value. Note that this check to
12016 // see if the size changes is just paranoia -- if
12017 // something unexpected happens, we don't want to end up
12018 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012019 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020 i--;
12021 }
12022 }
12023 }
12024 }
12025 }
12026
12027 /** This method sends the specified signal to each of the persistent apps */
12028 public void signalPersistentProcesses(int sig) throws RemoteException {
12029 if (sig != Process.SIGNAL_USR1) {
12030 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12031 }
12032
12033 synchronized (this) {
12034 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12035 != PackageManager.PERMISSION_GRANTED) {
12036 throw new SecurityException("Requires permission "
12037 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12038 }
12039
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012040 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12041 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012042 if (r.thread != null && r.persistent) {
12043 Process.sendSignal(r.pid, sig);
12044 }
12045 }
12046 }
12047 }
12048
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012049 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012050 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012051
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012052 try {
12053 synchronized (this) {
12054 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12055 // its own permission.
12056 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12057 != PackageManager.PERMISSION_GRANTED) {
12058 throw new SecurityException("Requires permission "
12059 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012060 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012061
12062 if (start && fd == null) {
12063 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012064 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012065
12066 ProcessRecord proc = null;
12067 try {
12068 int pid = Integer.parseInt(process);
12069 synchronized (mPidsSelfLocked) {
12070 proc = mPidsSelfLocked.get(pid);
12071 }
12072 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012073 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012074
12075 if (proc == null) {
12076 HashMap<String, SparseArray<ProcessRecord>> all
12077 = mProcessNames.getMap();
12078 SparseArray<ProcessRecord> procs = all.get(process);
12079 if (procs != null && procs.size() > 0) {
12080 proc = procs.valueAt(0);
12081 }
12082 }
12083
12084 if (proc == null || proc.thread == null) {
12085 throw new IllegalArgumentException("Unknown process: " + process);
12086 }
12087
12088 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12089 if (isSecure) {
12090 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12091 throw new SecurityException("Process not debuggable: " + proc);
12092 }
12093 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012094
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012095 proc.thread.profilerControl(start, path, fd);
12096 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012097 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012098 }
12099 } catch (RemoteException e) {
12100 throw new IllegalStateException("Process disappeared");
12101 } finally {
12102 if (fd != null) {
12103 try {
12104 fd.close();
12105 } catch (IOException e) {
12106 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012107 }
12108 }
12109 }
12110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012111 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12112 public void monitor() {
12113 synchronized (this) { }
12114 }
12115}