blob: 9d31502fbca4a6df39ce808456ad927647e42379 [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
134public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
135 static final String TAG = "ActivityManager";
136 static final boolean DEBUG = false;
137 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
138 static final boolean DEBUG_SWITCH = localLOGV || false;
139 static final boolean DEBUG_TASKS = localLOGV || false;
140 static final boolean DEBUG_PAUSE = localLOGV || false;
141 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
142 static final boolean DEBUG_TRANSITION = localLOGV || false;
143 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700144 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean DEBUG_SERVICE = localLOGV || false;
146 static final boolean DEBUG_VISBILITY = localLOGV || false;
147 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700148 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800149 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700151 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700152 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700153 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean VALIDATE_TOKENS = false;
155 static final boolean SHOW_ACTIVITY_START_TIME = true;
156
157 // Control over CPU and battery monitoring.
158 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
159 static final boolean MONITOR_CPU_USAGE = true;
160 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
161 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
162 static final boolean MONITOR_THREAD_CPU_USAGE = false;
163
Dianne Hackborn1655be42009-05-08 14:29:01 -0700164 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700165 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 private static final String SYSTEM_SECURE = "ro.secure";
168
169 // This is the maximum number of application processes we would like
170 // to have running. Due to the asynchronous nature of things, we can
171 // temporarily go beyond this limit.
172 static final int MAX_PROCESSES = 2;
173
174 // Set to false to leave processes running indefinitely, relying on
175 // the kernel killing them as resources are required.
176 static final boolean ENFORCE_PROCESS_LIMIT = false;
177
178 // This is the maximum number of activities that we would like to have
179 // running at a given time.
180 static final int MAX_ACTIVITIES = 20;
181
182 // Maximum number of recent tasks that we can remember.
183 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700184
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700185 // Amount of time after a call to stopAppSwitches() during which we will
186 // prevent further untrusted switches from happening.
187 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188
189 // How long we wait for a launched process to attach to the activity manager
190 // before we decide it's never going to come up for real.
191 static final int PROC_START_TIMEOUT = 10*1000;
192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 // How long to wait after going idle before forcing apps to GC.
194 static final int GC_TIMEOUT = 5*1000;
195
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700196 // The minimum amount of time between successive GC requests for a process.
197 static final int GC_MIN_INTERVAL = 60*1000;
198
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700199 // The rate at which we check for apps using excessive wake locks -- 15 mins.
200 static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 // How long we allow a receiver to run before giving up on it.
203 static final int BROADCAST_TIMEOUT = 10*1000;
204
205 // How long we wait for a service to finish executing.
206 static final int SERVICE_TIMEOUT = 20*1000;
207
208 // How long a service needs to be running until restarting its process
209 // is no longer considered to be a relaunch of the service.
210 static final int SERVICE_RESTART_DURATION = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // How long a service needs to be running until it will start back at
213 // SERVICE_RESTART_DURATION after being killed.
214 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
215
216 // Multiplying factor to increase restart duration time by, for each time
217 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
218 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
219
220 // The minimum amount of time between restarting services that we allow.
221 // That is, when multiple services are restarting, we won't allow each
222 // to restart less than this amount of time from the last one.
223 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // Maximum amount of time for there to be no activity on a service before
226 // we consider it non-essential and allow its process to go on the
227 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700228 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
230 // How long we wait until we timeout on key dispatching.
231 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
232
233 // The minimum time we allow between crashes, for us to consider this
234 // application to be bad and stop and its services and reject broadcasts.
235 static final int MIN_CRASH_INTERVAL = 60*1000;
236
237 // How long we wait until we timeout on key dispatching during instrumentation.
238 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
239
240 // OOM adjustments for processes in various states:
241
242 // This is a process without anything currently running in it. Definitely
243 // the first to go! Value set in system/rootdir/init.rc on startup.
244 // This value is initalized in the constructor, careful when refering to
245 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800246 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // This is a process only hosting activities that are not visible,
249 // so it can be killed without any disruption. Value set in
250 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800251 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 static int HIDDEN_APP_MIN_ADJ;
253
The Android Open Source Project4df24232009-03-05 14:34:35 -0800254 // This is a process holding the home application -- we want to try
255 // avoiding killing it, even if it would normally be in the background,
256 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800257 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800258
Christopher Tate6fa95972009-06-05 18:43:55 -0700259 // This is a process currently hosting a backup operation. Killing it
260 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800261 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 // This is a process holding a secondary server -- killing it will not
264 // have much of an impact as far as the user is concerned. Value set in
265 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800266 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700268 // This is a process with a heavy-weight application. It is in the
269 // background, but we want to try to avoid killing it. Value set in
270 // system/rootdir/init.rc on startup.
271 static final int HEAVY_WEIGHT_APP_ADJ;
272
273 // This is a process only hosting components that are perceptible to the
274 // user, and we really want to avoid killing them, but they are not
275 // immediately visible. An example is background music playback. Value set in
276 // system/rootdir/init.rc on startup.
277 static final int PERCEPTIBLE_APP_ADJ;
278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 // This is a process only hosting activities that are visible to the
280 // user, so we'd prefer they don't disappear. Value set in
281 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283
284 // This is the process running the current foreground app. We'd really
285 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
288 // This is a process running a core server, such as telephony. Definitely
289 // don't want to kill it, but doing so is not completely fatal.
290 static final int CORE_SERVER_ADJ = -12;
291
292 // The system process runs at the default adjustment.
293 static final int SYSTEM_ADJ = -16;
294
295 // Memory pages are 4K.
296 static final int PAGE_SIZE = 4*1024;
297
298 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800299 static final int EMPTY_APP_MEM;
300 static final int HIDDEN_APP_MEM;
301 static final int HOME_APP_MEM;
302 static final int BACKUP_APP_MEM;
303 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700304 static final int HEAVY_WEIGHT_APP_MEM;
305 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int VISIBLE_APP_MEM;
307 static final int FOREGROUND_APP_MEM;
308
309 // The minimum number of hidden apps we want to be able to keep around,
310 // without empty apps being able to push them out of memory.
311 static final int MIN_HIDDEN_APPS = 2;
312
Dianne Hackborn8633e682010-04-22 16:03:41 -0700313 // The maximum number of hidden processes we will keep around before
314 // killing them; this is just a control to not let us go too crazy with
315 // keeping around processes on devices with large amounts of RAM.
316 static final int MAX_HIDDEN_APPS = 15;
317
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800318 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700319 // been idle for less than 15 seconds.
320 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800321
322 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700323 // been idle for less than 120 seconds.
324 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800325
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700326 static int getIntProp(String name, boolean allowZero) {
327 String str = SystemProperties.get(name);
328 if (str == null) {
329 throw new IllegalArgumentException("Property not defined: " + name);
330 }
331 int val = Integer.valueOf(str);
332 if (val == 0 && !allowZero) {
333 throw new IllegalArgumentException("Property must not be zero: " + name);
334 }
335 return val;
336 }
337
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800338 static {
339 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700340 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
341 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
342 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
343 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
344 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
345 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
346 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
347 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
348 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
349 // These days we use the last empty slot for hidden apps as well.
350 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
351 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
352 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
353 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
354 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
355 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
356 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
357 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
358 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
359 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
Dan Egnor42471dd2010-01-07 17:25:22 -0800362 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
364 static final String[] EMPTY_STRING_ARRAY = new String[0];
365
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700366 public ActivityStack mMainStack;
367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700369 * Description of a request to start a new activity, which has been held
370 * due to app switches being disabled.
371 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700372 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700373 ActivityRecord r;
374 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700375 Uri[] grantedUriPermissions;
376 int grantedMode;
377 boolean onlyIfNeeded;
378 }
379
380 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
381 = new ArrayList<PendingActivityLaunch>();
382
383 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 * List of all active broadcasts that are to be executed immediately
385 * (without waiting for another broadcast to finish). Currently this only
386 * contains broadcasts to registered receivers, to avoid spinning up
387 * a bunch of processes to execute IntentReceiver components.
388 */
389 final ArrayList<BroadcastRecord> mParallelBroadcasts
390 = new ArrayList<BroadcastRecord>();
391
392 /**
393 * List of all active broadcasts that are to be executed one at a time.
394 * The object at the top of the list is the currently activity broadcasts;
395 * those after it are waiting for the top to finish..
396 */
397 final ArrayList<BroadcastRecord> mOrderedBroadcasts
398 = new ArrayList<BroadcastRecord>();
399
400 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800401 * Historical data of past broadcasts, for debugging.
402 */
403 static final int MAX_BROADCAST_HISTORY = 100;
404 final BroadcastRecord[] mBroadcastHistory
405 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * Set when we current have a BROADCAST_INTENT_MSG in flight.
409 */
410 boolean mBroadcastsScheduled = false;
411
412 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 * Activity we have told the window manager to have key focus.
414 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700415 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700416 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 * List of intents that were used to start the most recent tasks.
418 */
419 final ArrayList<TaskRecord> mRecentTasks
420 = new ArrayList<TaskRecord>();
421
422 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 * All of the applications we currently have running organized by name.
424 * The keys are strings of the application package name (as
425 * returned by the package manager), and the keys are ApplicationRecord
426 * objects.
427 */
428 final ProcessMap<ProcessRecord> mProcessNames
429 = new ProcessMap<ProcessRecord>();
430
431 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700432 * The currently running heavy-weight process, if any.
433 */
434 ProcessRecord mHeavyWeightProcess = null;
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * The last time that various processes have crashed.
438 */
439 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
440
441 /**
442 * Set of applications that we consider to be bad, and will reject
443 * incoming broadcasts from (which the user has no control over).
444 * Processes are added to this set when they have crashed twice within
445 * a minimum amount of time; they are removed from it when they are
446 * later restarted (hopefully due to some user action). The value is the
447 * time it was added to the list.
448 */
449 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
450
451 /**
452 * All of the processes we currently have running organized by pid.
453 * The keys are the pid running the application.
454 *
455 * <p>NOTE: This object is protected by its own lock, NOT the global
456 * activity manager lock!
457 */
458 final SparseArray<ProcessRecord> mPidsSelfLocked
459 = new SparseArray<ProcessRecord>();
460
461 /**
462 * All of the processes that have been forced to be foreground. The key
463 * is the pid of the caller who requested it (we hold a death
464 * link on it).
465 */
466 abstract class ForegroundToken implements IBinder.DeathRecipient {
467 int pid;
468 IBinder token;
469 }
470 final SparseArray<ForegroundToken> mForegroundProcesses
471 = new SparseArray<ForegroundToken>();
472
473 /**
474 * List of records for processes that someone had tried to start before the
475 * system was ready. We don't start them at that point, but ensure they
476 * are started by the time booting is complete.
477 */
478 final ArrayList<ProcessRecord> mProcessesOnHold
479 = new ArrayList<ProcessRecord>();
480
481 /**
482 * List of records for processes that we have started and are waiting
483 * for them to call back. This is really only needed when running in
484 * single processes mode, in which case we do not have a unique pid for
485 * each process.
486 */
487 final ArrayList<ProcessRecord> mStartingProcesses
488 = new ArrayList<ProcessRecord>();
489
490 /**
491 * List of persistent applications that are in the process
492 * of being started.
493 */
494 final ArrayList<ProcessRecord> mPersistentStartingProcesses
495 = new ArrayList<ProcessRecord>();
496
497 /**
498 * Processes that are being forcibly torn down.
499 */
500 final ArrayList<ProcessRecord> mRemovedProcesses
501 = new ArrayList<ProcessRecord>();
502
503 /**
504 * List of running applications, sorted by recent usage.
505 * The first entry in the list is the least recently used.
506 * It contains ApplicationRecord objects. This list does NOT include
507 * any persistent application records (since we never want to exit them).
508 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800509 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 = new ArrayList<ProcessRecord>();
511
512 /**
513 * List of processes that should gc as soon as things are idle.
514 */
515 final ArrayList<ProcessRecord> mProcessesToGc
516 = new ArrayList<ProcessRecord>();
517
518 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800519 * This is the process holding what we currently consider to be
520 * the "home" activity.
521 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700522 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800523
524 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 * Set of PendingResultRecord objects that are currently active.
526 */
527 final HashSet mPendingResultRecords = new HashSet();
528
529 /**
530 * Set of IntentSenderRecord objects that are currently active.
531 */
532 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
533 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
534
535 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700536 * Fingerprints (String.hashCode()) of stack traces that we've
537 * already logged DropBox entries for. Guarded by itself. If
538 * something (rogue user app) forces this over
539 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
540 */
541 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
542 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
543
544 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700545 * Strict Mode background batched logging state.
546 *
547 * The string buffer is guarded by itself, and its lock is also
548 * used to determine if another batched write is already
549 * in-flight.
550 */
551 private final StringBuilder mStrictModeBuffer = new StringBuilder();
552
553 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 * Intent broadcast that we have tried to start, but are
555 * waiting for its application's process to be created. We only
556 * need one (instead of a list) because we always process broadcasts
557 * one at a time, so no others can be started while waiting for this
558 * one.
559 */
560 BroadcastRecord mPendingBroadcast = null;
561
562 /**
563 * Keeps track of all IIntentReceivers that have been registered for
564 * broadcasts. Hash keys are the receiver IBinder, hash value is
565 * a ReceiverList.
566 */
567 final HashMap mRegisteredReceivers = new HashMap();
568
569 /**
570 * Resolver for broadcast intents to registered receivers.
571 * Holds BroadcastFilter (subclass of IntentFilter).
572 */
573 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
574 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
575 @Override
576 protected boolean allowFilterResult(
577 BroadcastFilter filter, List<BroadcastFilter> dest) {
578 IBinder target = filter.receiverList.receiver.asBinder();
579 for (int i=dest.size()-1; i>=0; i--) {
580 if (dest.get(i).receiverList.receiver.asBinder() == target) {
581 return false;
582 }
583 }
584 return true;
585 }
586 };
587
588 /**
589 * State of all active sticky broadcasts. Keys are the action of the
590 * sticky Intent, values are an ArrayList of all broadcasted intents with
591 * that action (which should usually be one).
592 */
593 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
594 new HashMap<String, ArrayList<Intent>>();
595
596 /**
597 * All currently running services.
598 */
599 final HashMap<ComponentName, ServiceRecord> mServices =
600 new HashMap<ComponentName, ServiceRecord>();
601
602 /**
603 * All currently running services indexed by the Intent used to start them.
604 */
605 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
606 new HashMap<Intent.FilterComparison, ServiceRecord>();
607
608 /**
609 * All currently bound service connections. Keys are the IBinder of
610 * the client's IServiceConnection.
611 */
612 final HashMap<IBinder, ConnectionRecord> mServiceConnections
613 = new HashMap<IBinder, ConnectionRecord>();
614
615 /**
616 * List of services that we have been asked to start,
617 * but haven't yet been able to. It is used to hold start requests
618 * while waiting for their corresponding application thread to get
619 * going.
620 */
621 final ArrayList<ServiceRecord> mPendingServices
622 = new ArrayList<ServiceRecord>();
623
624 /**
625 * List of services that are scheduled to restart following a crash.
626 */
627 final ArrayList<ServiceRecord> mRestartingServices
628 = new ArrayList<ServiceRecord>();
629
630 /**
631 * List of services that are in the process of being stopped.
632 */
633 final ArrayList<ServiceRecord> mStoppingServices
634 = new ArrayList<ServiceRecord>();
635
636 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700637 * Backup/restore process management
638 */
639 String mBackupAppName = null;
640 BackupRecord mBackupTarget = null;
641
642 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 * List of PendingThumbnailsRecord objects of clients who are still
644 * waiting to receive all of the thumbnails for a task.
645 */
646 final ArrayList mPendingThumbnails = new ArrayList();
647
648 /**
649 * List of HistoryRecord objects that have been finished and must
650 * still report back to a pending thumbnail receiver.
651 */
652 final ArrayList mCancelledThumbnails = new ArrayList();
653
654 /**
655 * All of the currently running global content providers. Keys are a
656 * string containing the provider name and values are a
657 * ContentProviderRecord object containing the data about it. Note
658 * that a single provider may be published under multiple names, so
659 * there may be multiple entries here for a single one in mProvidersByClass.
660 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700661 final HashMap<String, ContentProviderRecord> mProvidersByName
662 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663
664 /**
665 * All of the currently running global content providers. Keys are a
666 * string containing the provider's implementation class and values are a
667 * ContentProviderRecord object containing the data about it.
668 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700669 final HashMap<String, ContentProviderRecord> mProvidersByClass
670 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671
672 /**
673 * List of content providers who have clients waiting for them. The
674 * application is currently being launched and the provider will be
675 * removed from this list once it is published.
676 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700677 final ArrayList<ContentProviderRecord> mLaunchingProviders
678 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679
680 /**
681 * Global set of specific Uri permissions that have been granted.
682 */
683 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
684 = new SparseArray<HashMap<Uri, UriPermission>>();
685
686 /**
687 * Thread-local storage used to carry caller permissions over through
688 * indirect content-provider access.
689 * @see #ActivityManagerService.openContentUri()
690 */
691 private class Identity {
692 public int pid;
693 public int uid;
694
695 Identity(int _pid, int _uid) {
696 pid = _pid;
697 uid = _uid;
698 }
699 }
700 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
701
702 /**
703 * All information we have collected about the runtime performance of
704 * any user id that can impact battery performance.
705 */
706 final BatteryStatsService mBatteryStatsService;
707
708 /**
709 * information about component usage
710 */
711 final UsageStatsService mUsageStatsService;
712
713 /**
714 * Current configuration information. HistoryRecord objects are given
715 * a reference to this object to indicate which configuration they are
716 * currently running in, so this object must be kept immutable.
717 */
718 Configuration mConfiguration = new Configuration();
719
720 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800721 * Current sequencing integer of the configuration, for skipping old
722 * configurations.
723 */
724 int mConfigurationSeq = 0;
725
726 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700727 * Hardware-reported OpenGLES version.
728 */
729 final int GL_ES_VERSION;
730
731 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 * List of initialization arguments to pass to all processes when binding applications to them.
733 * For example, references to the commonly used services.
734 */
735 HashMap<String, IBinder> mAppBindArgs;
736
737 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700738 * Temporary to avoid allocations. Protected by main lock.
739 */
740 final StringBuilder mStringBuilder = new StringBuilder(256);
741
742 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 * Used to control how we initialize the service.
744 */
745 boolean mStartRunning = false;
746 ComponentName mTopComponent;
747 String mTopAction;
748 String mTopData;
749 boolean mSystemReady = false;
750 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700751 boolean mWaitingUpdate = false;
752 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753
754 Context mContext;
755
756 int mFactoryTest;
757
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700758 boolean mCheckedForSetup;
759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700761 * The time at which we will allow normal application switches again,
762 * after a call to {@link #stopAppSwitches()}.
763 */
764 long mAppSwitchesAllowedTime;
765
766 /**
767 * This is set to true after the first switch after mAppSwitchesAllowedTime
768 * is set; any switches after that will clear the time.
769 */
770 boolean mDidAppSwitch;
771
772 /**
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700773 * Last time (in realtime) at which we checked for wake lock usage.
774 */
775 long mLastWakeLockCheckTime;
776
777 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 * Set while we are wanting to sleep, to prevent any
779 * activities from being started/resumed.
780 */
781 boolean mSleeping = false;
782
783 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700784 * Set if we are shutting down the system, similar to sleeping.
785 */
786 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787
788 /**
789 * Task identifier that activities are currently being started
790 * in. Incremented each time a new task is created.
791 * todo: Replace this with a TokenSpace class that generates non-repeating
792 * integers that won't wrap.
793 */
794 int mCurTask = 1;
795
796 /**
797 * Current sequence id for oom_adj computation traversal.
798 */
799 int mAdjSeq = 0;
800
801 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700802 * Current sequence id for process LRU updating.
803 */
804 int mLruSeq = 0;
805
806 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
808 * is set, indicating the user wants processes started in such a way
809 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
810 * running in each process (thus no pre-initialized process, etc).
811 */
812 boolean mSimpleProcessManagement = false;
813
814 /**
815 * System monitoring: number of processes that died since the last
816 * N procs were started.
817 */
818 int[] mProcDeaths = new int[20];
819
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700820 /**
821 * This is set if we had to do a delayed dexopt of an app before launching
822 * it, to increasing the ANR timeouts in that case.
823 */
824 boolean mDidDexOpt;
825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 String mDebugApp = null;
827 boolean mWaitForDebugger = false;
828 boolean mDebugTransient = false;
829 String mOrigDebugApp = null;
830 boolean mOrigWaitForDebugger = false;
831 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700832 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700834 final RemoteCallbackList<IActivityWatcher> mWatchers
835 = new RemoteCallbackList<IActivityWatcher>();
836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 /**
838 * Callback of last caller to {@link #requestPss}.
839 */
840 Runnable mRequestPssCallback;
841
842 /**
843 * Remaining processes for which we are waiting results from the last
844 * call to {@link #requestPss}.
845 */
846 final ArrayList<ProcessRecord> mRequestPssList
847 = new ArrayList<ProcessRecord>();
848
849 /**
850 * Runtime statistics collection thread. This object's lock is used to
851 * protect all related state.
852 */
853 final Thread mProcessStatsThread;
854
855 /**
856 * Used to collect process stats when showing not responding dialog.
857 * Protected by mProcessStatsThread.
858 */
859 final ProcessStats mProcessStats = new ProcessStats(
860 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700861 final AtomicLong mLastCpuTime = new AtomicLong(0);
862 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 long mLastWriteTime = 0;
865
866 /**
867 * Set to true after the system has finished booting.
868 */
869 boolean mBooted = false;
870
871 int mProcessLimit = 0;
872
873 WindowManagerService mWindowManager;
874
875 static ActivityManagerService mSelf;
876 static ActivityThread mSystemThread;
877
878 private final class AppDeathRecipient implements IBinder.DeathRecipient {
879 final ProcessRecord mApp;
880 final int mPid;
881 final IApplicationThread mAppThread;
882
883 AppDeathRecipient(ProcessRecord app, int pid,
884 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800885 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 TAG, "New death recipient " + this
887 + " for thread " + thread.asBinder());
888 mApp = app;
889 mPid = pid;
890 mAppThread = thread;
891 }
892
893 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800894 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 TAG, "Death received in " + this
896 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 synchronized(ActivityManagerService.this) {
898 appDiedLocked(mApp, mPid, mAppThread);
899 }
900 }
901 }
902
903 static final int SHOW_ERROR_MSG = 1;
904 static final int SHOW_NOT_RESPONDING_MSG = 2;
905 static final int SHOW_FACTORY_ERROR_MSG = 3;
906 static final int UPDATE_CONFIGURATION_MSG = 4;
907 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
908 static final int WAIT_FOR_DEBUGGER_MSG = 6;
909 static final int BROADCAST_INTENT_MSG = 7;
910 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 static final int SERVICE_TIMEOUT_MSG = 12;
912 static final int UPDATE_TIME_ZONE = 13;
913 static final int SHOW_UID_ERROR_MSG = 14;
914 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700916 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700917 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800918 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700919 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
920 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700921 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700922 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923
924 AlertDialog mUidAlert;
925
926 final Handler mHandler = new Handler() {
927 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800928 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 //}
930
931 public void handleMessage(Message msg) {
932 switch (msg.what) {
933 case SHOW_ERROR_MSG: {
934 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 synchronized (ActivityManagerService.this) {
936 ProcessRecord proc = (ProcessRecord)data.get("app");
937 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800938 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 return;
940 }
941 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700942 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800943 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 d.show();
945 proc.crashDialog = d;
946 } else {
947 // The device is asleep, so just pretend that the user
948 // saw a crash dialog and hit "force quit".
949 res.set(0);
950 }
951 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700952
953 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 } break;
955 case SHOW_NOT_RESPONDING_MSG: {
956 synchronized (ActivityManagerService.this) {
957 HashMap data = (HashMap) msg.obj;
958 ProcessRecord proc = (ProcessRecord)data.get("app");
959 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800960 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 return;
962 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800963
964 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
965 null, null, 0, null, null, null,
966 false, false, MY_PID, Process.SYSTEM_UID);
967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700969 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 d.show();
971 proc.anrDialog = d;
972 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700973
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700974 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700976 case SHOW_STRICT_MODE_VIOLATION_MSG: {
977 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
978 synchronized (ActivityManagerService.this) {
979 ProcessRecord proc = (ProcessRecord) data.get("app");
980 if (proc == null) {
981 Slog.e(TAG, "App not found when showing strict mode dialog.");
982 break;
983 }
984 if (proc.crashDialog != null) {
985 Slog.e(TAG, "App already has strict mode dialog: " + proc);
986 return;
987 }
988 AppErrorResult res = (AppErrorResult) data.get("result");
989 if (!mSleeping && !mShuttingDown) {
990 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
991 d.show();
992 proc.crashDialog = d;
993 } else {
994 // The device is asleep, so just pretend that the user
995 // saw a crash dialog and hit "force quit".
996 res.set(0);
997 }
998 }
999 ensureBootCompleted();
1000 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 case SHOW_FACTORY_ERROR_MSG: {
1002 Dialog d = new FactoryErrorDialog(
1003 mContext, msg.getData().getCharSequence("msg"));
1004 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001005 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 } break;
1007 case UPDATE_CONFIGURATION_MSG: {
1008 final ContentResolver resolver = mContext.getContentResolver();
1009 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1010 } break;
1011 case GC_BACKGROUND_PROCESSES_MSG: {
1012 synchronized (ActivityManagerService.this) {
1013 performAppGcsIfAppropriateLocked();
1014 }
1015 } break;
1016 case WAIT_FOR_DEBUGGER_MSG: {
1017 synchronized (ActivityManagerService.this) {
1018 ProcessRecord app = (ProcessRecord)msg.obj;
1019 if (msg.arg1 != 0) {
1020 if (!app.waitedForDebugger) {
1021 Dialog d = new AppWaitingForDebuggerDialog(
1022 ActivityManagerService.this,
1023 mContext, app);
1024 app.waitDialog = d;
1025 app.waitedForDebugger = true;
1026 d.show();
1027 }
1028 } else {
1029 if (app.waitDialog != null) {
1030 app.waitDialog.dismiss();
1031 app.waitDialog = null;
1032 }
1033 }
1034 }
1035 } break;
1036 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001037 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 TAG, "Received BROADCAST_INTENT_MSG");
1039 processNextBroadcast(true);
1040 } break;
1041 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001042 if (mDidDexOpt) {
1043 mDidDexOpt = false;
1044 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1045 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1046 return;
1047 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001048 // Only process broadcast timeouts if the system is ready. That way
1049 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1050 // to do heavy lifting for system up
1051 if (mSystemReady) {
1052 broadcastTimeout();
1053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001056 if (mDidDexOpt) {
1057 mDidDexOpt = false;
1058 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1059 nmsg.obj = msg.obj;
1060 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1061 return;
1062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 serviceTimeout((ProcessRecord)msg.obj);
1064 } break;
1065 case UPDATE_TIME_ZONE: {
1066 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001067 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1068 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 if (r.thread != null) {
1070 try {
1071 r.thread.updateTimeZone();
1072 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001073 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 }
1075 }
1076 }
1077 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001078 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 case SHOW_UID_ERROR_MSG: {
1080 // XXX This is a temporary dialog, no need to localize.
1081 AlertDialog d = new BaseErrorDialog(mContext);
1082 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1083 d.setCancelable(false);
1084 d.setTitle("System UIDs Inconsistent");
1085 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1086 d.setButton("I'm Feeling Lucky",
1087 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1088 mUidAlert = d;
1089 d.show();
1090 } break;
1091 case IM_FEELING_LUCKY_MSG: {
1092 if (mUidAlert != null) {
1093 mUidAlert.dismiss();
1094 mUidAlert = null;
1095 }
1096 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001098 if (mDidDexOpt) {
1099 mDidDexOpt = false;
1100 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1101 nmsg.obj = msg.obj;
1102 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1103 return;
1104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 ProcessRecord app = (ProcessRecord)msg.obj;
1106 synchronized (ActivityManagerService.this) {
1107 processStartTimedOutLocked(app);
1108 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001109 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001110 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1111 synchronized (ActivityManagerService.this) {
1112 doPendingActivityLaunchesLocked(true);
1113 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001114 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001115 case KILL_APPLICATION_MSG: {
1116 synchronized (ActivityManagerService.this) {
1117 int uid = msg.arg1;
1118 boolean restart = (msg.arg2 == 1);
1119 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001120 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001121 }
1122 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001123 case FINALIZE_PENDING_INTENT_MSG: {
1124 ((PendingIntentRecord)msg.obj).completeFinalize();
1125 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001126 case POST_HEAVY_NOTIFICATION_MSG: {
1127 INotificationManager inm = NotificationManager.getService();
1128 if (inm == null) {
1129 return;
1130 }
1131
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001132 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001133 ProcessRecord process = root.app;
1134 if (process == null) {
1135 return;
1136 }
1137
1138 try {
1139 Context context = mContext.createPackageContext(process.info.packageName, 0);
1140 String text = mContext.getString(R.string.heavy_weight_notification,
1141 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1142 Notification notification = new Notification();
1143 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1144 notification.when = 0;
1145 notification.flags = Notification.FLAG_ONGOING_EVENT;
1146 notification.tickerText = text;
1147 notification.defaults = 0; // please be quiet
1148 notification.sound = null;
1149 notification.vibrate = null;
1150 notification.setLatestEventInfo(context, text,
1151 mContext.getText(R.string.heavy_weight_notification_detail),
1152 PendingIntent.getActivity(mContext, 0, root.intent,
1153 PendingIntent.FLAG_CANCEL_CURRENT));
1154
1155 try {
1156 int[] outId = new int[1];
1157 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1158 notification, outId);
1159 } catch (RuntimeException e) {
1160 Slog.w(ActivityManagerService.TAG,
1161 "Error showing notification for heavy-weight app", e);
1162 } catch (RemoteException e) {
1163 }
1164 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001165 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001166 }
1167 } break;
1168 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1169 INotificationManager inm = NotificationManager.getService();
1170 if (inm == null) {
1171 return;
1172 }
1173 try {
1174 inm.cancelNotification("android",
1175 R.string.heavy_weight_notification);
1176 } catch (RuntimeException e) {
1177 Slog.w(ActivityManagerService.TAG,
1178 "Error canceling notification for service", e);
1179 } catch (RemoteException e) {
1180 }
1181 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001182 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1183 synchronized (ActivityManagerService.this) {
1184 checkExcessiveWakeLocksLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001185 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001186 if (mSleeping) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001187 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1188 sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001189 }
1190 }
1191 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 }
1193 }
1194 };
1195
1196 public static void setSystemProcess() {
1197 try {
1198 ActivityManagerService m = mSelf;
1199
1200 ServiceManager.addService("activity", m);
1201 ServiceManager.addService("meminfo", new MemBinder(m));
1202 if (MONITOR_CPU_USAGE) {
1203 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 ServiceManager.addService("permission", new PermissionController(m));
1206
1207 ApplicationInfo info =
1208 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001209 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001210 mSystemThread.installSystemApplicationInfo(info);
1211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 synchronized (mSelf) {
1213 ProcessRecord app = mSelf.newProcessRecordLocked(
1214 mSystemThread.getApplicationThread(), info,
1215 info.processName);
1216 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001217 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 app.maxAdj = SYSTEM_ADJ;
1219 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1220 synchronized (mSelf.mPidsSelfLocked) {
1221 mSelf.mPidsSelfLocked.put(app.pid, app);
1222 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001223 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 }
1225 } catch (PackageManager.NameNotFoundException e) {
1226 throw new RuntimeException(
1227 "Unable to find android system package", e);
1228 }
1229 }
1230
1231 public void setWindowManager(WindowManagerService wm) {
1232 mWindowManager = wm;
1233 }
1234
1235 public static final Context main(int factoryTest) {
1236 AThread thr = new AThread();
1237 thr.start();
1238
1239 synchronized (thr) {
1240 while (thr.mService == null) {
1241 try {
1242 thr.wait();
1243 } catch (InterruptedException e) {
1244 }
1245 }
1246 }
1247
1248 ActivityManagerService m = thr.mService;
1249 mSelf = m;
1250 ActivityThread at = ActivityThread.systemMain();
1251 mSystemThread = at;
1252 Context context = at.getSystemContext();
1253 m.mContext = context;
1254 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001255 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256
1257 m.mBatteryStatsService.publish(context);
1258 m.mUsageStatsService.publish(context);
1259
1260 synchronized (thr) {
1261 thr.mReady = true;
1262 thr.notifyAll();
1263 }
1264
1265 m.startRunning(null, null, null, null);
1266
1267 return context;
1268 }
1269
1270 public static ActivityManagerService self() {
1271 return mSelf;
1272 }
1273
1274 static class AThread extends Thread {
1275 ActivityManagerService mService;
1276 boolean mReady = false;
1277
1278 public AThread() {
1279 super("ActivityManager");
1280 }
1281
1282 public void run() {
1283 Looper.prepare();
1284
1285 android.os.Process.setThreadPriority(
1286 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001287 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288
1289 ActivityManagerService m = new ActivityManagerService();
1290
1291 synchronized (this) {
1292 mService = m;
1293 notifyAll();
1294 }
1295
1296 synchronized (this) {
1297 while (!mReady) {
1298 try {
1299 wait();
1300 } catch (InterruptedException e) {
1301 }
1302 }
1303 }
1304
1305 Looper.loop();
1306 }
1307 }
1308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 static class MemBinder extends Binder {
1310 ActivityManagerService mActivityManagerService;
1311 MemBinder(ActivityManagerService activityManagerService) {
1312 mActivityManagerService = activityManagerService;
1313 }
1314
1315 @Override
1316 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1317 ActivityManagerService service = mActivityManagerService;
1318 ArrayList<ProcessRecord> procs;
1319 synchronized (mActivityManagerService) {
1320 if (args != null && args.length > 0
1321 && args[0].charAt(0) != '-') {
1322 procs = new ArrayList<ProcessRecord>();
1323 int pid = -1;
1324 try {
1325 pid = Integer.parseInt(args[0]);
1326 } catch (NumberFormatException e) {
1327
1328 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001329 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1330 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 if (proc.pid == pid) {
1332 procs.add(proc);
1333 } else if (proc.processName.equals(args[0])) {
1334 procs.add(proc);
1335 }
1336 }
1337 if (procs.size() <= 0) {
1338 pw.println("No process found for: " + args[0]);
1339 return;
1340 }
1341 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001342 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 }
1344 }
1345 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1346 }
1347 }
1348
1349 static class CpuBinder extends Binder {
1350 ActivityManagerService mActivityManagerService;
1351 CpuBinder(ActivityManagerService activityManagerService) {
1352 mActivityManagerService = activityManagerService;
1353 }
1354
1355 @Override
1356 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1357 synchronized (mActivityManagerService.mProcessStatsThread) {
1358 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1359 }
1360 }
1361 }
1362
1363 private ActivityManagerService() {
1364 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1365 if (v != null && Integer.getInteger(v) != 0) {
1366 mSimpleProcessManagement = true;
1367 }
1368 v = System.getenv("ANDROID_DEBUG_APP");
1369 if (v != null) {
1370 mSimpleProcessManagement = true;
1371 }
1372
Joe Onorato8a9b2202010-02-26 18:56:32 -08001373 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 File dataDir = Environment.getDataDirectory();
1376 File systemDir = new File(dataDir, "system");
1377 systemDir.mkdirs();
1378 mBatteryStatsService = new BatteryStatsService(new File(
1379 systemDir, "batterystats.bin").toString());
1380 mBatteryStatsService.getActiveStatistics().readLocked();
1381 mBatteryStatsService.getActiveStatistics().writeLocked();
1382
1383 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001384 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385
Jack Palevichb90d28c2009-07-22 15:35:24 -07001386 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1387 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1388
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001389 mConfiguration.setToDefaults();
1390 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 mProcessStats.init();
1392
1393 // Add ourself to the Watchdog monitors.
1394 Watchdog.getInstance().addMonitor(this);
1395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 mProcessStatsThread = new Thread("ProcessStats") {
1397 public void run() {
1398 while (true) {
1399 try {
1400 try {
1401 synchronized(this) {
1402 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001403 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001405 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 // + ", write delay=" + nextWriteDelay);
1407 if (nextWriteDelay < nextCpuDelay) {
1408 nextCpuDelay = nextWriteDelay;
1409 }
1410 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001411 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 this.wait(nextCpuDelay);
1413 }
1414 }
1415 } catch (InterruptedException e) {
1416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 updateCpuStatsNow();
1418 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001419 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 }
1421 }
1422 }
1423 };
1424 mProcessStatsThread.start();
1425 }
1426
1427 @Override
1428 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1429 throws RemoteException {
1430 try {
1431 return super.onTransact(code, data, reply, flags);
1432 } catch (RuntimeException e) {
1433 // The activity manager only throws security exceptions, so let's
1434 // log all others.
1435 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001436 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 }
1438 throw e;
1439 }
1440 }
1441
1442 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001443 final long now = SystemClock.uptimeMillis();
1444 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1445 return;
1446 }
1447 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1448 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 mProcessStatsThread.notify();
1450 }
1451 }
1452 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 void updateCpuStatsNow() {
1455 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001456 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 final long now = SystemClock.uptimeMillis();
1458 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001461 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1462 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 haveNewCpuStats = true;
1464 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001465 //Slog.i(TAG, mProcessStats.printCurrentState());
1466 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 // + mProcessStats.getTotalCpuPercent() + "%");
1468
Joe Onorato8a9b2202010-02-26 18:56:32 -08001469 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 if ("true".equals(SystemProperties.get("events.cpu"))) {
1471 int user = mProcessStats.getLastUserTime();
1472 int system = mProcessStats.getLastSystemTime();
1473 int iowait = mProcessStats.getLastIoWaitTime();
1474 int irq = mProcessStats.getLastIrqTime();
1475 int softIrq = mProcessStats.getLastSoftIrqTime();
1476 int idle = mProcessStats.getLastIdleTime();
1477
1478 int total = user + system + iowait + irq + softIrq + idle;
1479 if (total == 0) total = 1;
1480
Doug Zongker2bec3d42009-12-04 12:52:44 -08001481 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 ((user+system+iowait+irq+softIrq) * 100) / total,
1483 (user * 100) / total,
1484 (system * 100) / total,
1485 (iowait * 100) / total,
1486 (irq * 100) / total,
1487 (softIrq * 100) / total);
1488 }
1489 }
1490
Amith Yamasanie43530a2009-08-21 13:11:37 -07001491 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001492 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001493 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 synchronized(mPidsSelfLocked) {
1495 if (haveNewCpuStats) {
1496 if (mBatteryStatsService.isOnBattery()) {
1497 final int N = mProcessStats.countWorkingStats();
1498 for (int i=0; i<N; i++) {
1499 ProcessStats.Stats st
1500 = mProcessStats.getWorkingStats(i);
1501 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1502 if (pr != null) {
1503 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1504 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001505 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001506 } else {
1507 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001508 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001509 if (ps != null) {
1510 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001511 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 }
1514 }
1515 }
1516 }
1517 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1520 mLastWriteTime = now;
1521 mBatteryStatsService.getActiveStatistics().writeLocked();
1522 }
1523 }
1524 }
1525 }
1526
1527 /**
1528 * Initialize the application bind args. These are passed to each
1529 * process when the bindApplication() IPC is sent to the process. They're
1530 * lazily setup to make sure the services are running when they're asked for.
1531 */
1532 private HashMap<String, IBinder> getCommonServicesLocked() {
1533 if (mAppBindArgs == null) {
1534 mAppBindArgs = new HashMap<String, IBinder>();
1535
1536 // Setup the application init args
1537 mAppBindArgs.put("package", ServiceManager.getService("package"));
1538 mAppBindArgs.put("window", ServiceManager.getService("window"));
1539 mAppBindArgs.put(Context.ALARM_SERVICE,
1540 ServiceManager.getService(Context.ALARM_SERVICE));
1541 }
1542 return mAppBindArgs;
1543 }
1544
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001545 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 if (mFocusedActivity != r) {
1547 mFocusedActivity = r;
1548 mWindowManager.setFocusedApp(r, true);
1549 }
1550 }
1551
Dianne Hackborn906497c2010-05-10 15:57:38 -07001552 private final void updateLruProcessInternalLocked(ProcessRecord app,
1553 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001555 int lrui = mLruProcesses.indexOf(app);
1556 if (lrui >= 0) mLruProcesses.remove(lrui);
1557
1558 int i = mLruProcesses.size()-1;
1559 int skipTop = 0;
1560
Dianne Hackborn906497c2010-05-10 15:57:38 -07001561 app.lruSeq = mLruSeq;
1562
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001563 // compute the new weight for this process.
1564 if (updateActivityTime) {
1565 app.lastActivityTime = SystemClock.uptimeMillis();
1566 }
1567 if (app.activities.size() > 0) {
1568 // If this process has activities, we more strongly want to keep
1569 // it around.
1570 app.lruWeight = app.lastActivityTime;
1571 } else if (app.pubProviders.size() > 0) {
1572 // If this process contains content providers, we want to keep
1573 // it a little more strongly.
1574 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1575 // Also don't let it kick out the first few "real" hidden processes.
1576 skipTop = MIN_HIDDEN_APPS;
1577 } else {
1578 // If this process doesn't have activities, we less strongly
1579 // want to keep it around, and generally want to avoid getting
1580 // in front of any very recently used activities.
1581 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1582 // Also don't let it kick out the first few "real" hidden processes.
1583 skipTop = MIN_HIDDEN_APPS;
1584 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001585
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001586 while (i >= 0) {
1587 ProcessRecord p = mLruProcesses.get(i);
1588 // If this app shouldn't be in front of the first N background
1589 // apps, then skip over that many that are currently hidden.
1590 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1591 skipTop--;
1592 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001593 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001594 mLruProcesses.add(i+1, app);
1595 break;
1596 }
1597 i--;
1598 }
1599 if (i < 0) {
1600 mLruProcesses.add(0, app);
1601 }
1602
Dianne Hackborn906497c2010-05-10 15:57:38 -07001603 // If the app is currently using a content provider or service,
1604 // bump those processes as well.
1605 if (app.connections.size() > 0) {
1606 for (ConnectionRecord cr : app.connections) {
1607 if (cr.binding != null && cr.binding.service != null
1608 && cr.binding.service.app != null
1609 && cr.binding.service.app.lruSeq != mLruSeq) {
1610 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1611 updateActivityTime, i+1);
1612 }
1613 }
1614 }
1615 if (app.conProviders.size() > 0) {
1616 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1617 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1618 updateLruProcessInternalLocked(cpr.app, oomAdj,
1619 updateActivityTime, i+1);
1620 }
1621 }
1622 }
1623
Joe Onorato8a9b2202010-02-26 18:56:32 -08001624 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 if (oomAdj) {
1626 updateOomAdjLocked();
1627 }
1628 }
1629
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001630 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001631 boolean oomAdj, boolean updateActivityTime) {
1632 mLruSeq++;
1633 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1634 }
1635
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001636 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 String processName, int uid) {
1638 if (uid == Process.SYSTEM_UID) {
1639 // The system gets to run in any process. If there are multiple
1640 // processes with the same uid, just pick the first (this
1641 // should never happen).
1642 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1643 processName);
1644 return procs != null ? procs.valueAt(0) : null;
1645 }
1646 ProcessRecord proc = mProcessNames.get(processName, uid);
1647 return proc;
1648 }
1649
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001650 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001651 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001652 try {
1653 if (pm.performDexOpt(packageName)) {
1654 mDidDexOpt = true;
1655 }
1656 } catch (RemoteException e) {
1657 }
1658 }
1659
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001660 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 int transit = mWindowManager.getPendingAppTransition();
1662 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1663 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1664 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1665 }
1666
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001667 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001669 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1671 // We don't have to do anything more if:
1672 // (1) There is an existing application record; and
1673 // (2) The caller doesn't think it is dead, OR there is no thread
1674 // object attached to it so we know it couldn't have crashed; and
1675 // (3) There is a pid assigned to it, so it is either starting or
1676 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001677 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 + " app=" + app + " knownToBeDead=" + knownToBeDead
1679 + " thread=" + (app != null ? app.thread : null)
1680 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001681 if (app != null && app.pid > 0) {
1682 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001683 // We already have the app running, or are waiting for it to
1684 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001685 return app;
1686 } else {
1687 // An application record is attached to a previous process,
1688 // clean it up now.
1689 handleAppDiedLocked(app, true);
1690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 String hostingNameStr = hostingName != null
1694 ? hostingName.flattenToShortString() : null;
1695
1696 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1697 // If we are in the background, then check to see if this process
1698 // is bad. If so, we will just silently fail.
1699 if (mBadProcesses.get(info.processName, info.uid) != null) {
1700 return null;
1701 }
1702 } else {
1703 // When the user is explicitly starting a process, then clear its
1704 // crash count so that we won't make it bad until they see at
1705 // least one crash dialog again, and make the process good again
1706 // if it had been bad.
1707 mProcessCrashTimes.remove(info.processName, info.uid);
1708 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001709 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 info.processName);
1711 mBadProcesses.remove(info.processName, info.uid);
1712 if (app != null) {
1713 app.bad = false;
1714 }
1715 }
1716 }
1717
1718 if (app == null) {
1719 app = newProcessRecordLocked(null, info, processName);
1720 mProcessNames.put(processName, info.uid, app);
1721 } else {
1722 // If this is a new package in the process, add the package to the list
1723 app.addPackage(info.packageName);
1724 }
1725
1726 // If the system is not ready yet, then hold off on starting this
1727 // process until it is.
1728 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001729 && !isAllowedWhileBooting(info)
1730 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 if (!mProcessesOnHold.contains(app)) {
1732 mProcessesOnHold.add(app);
1733 }
1734 return app;
1735 }
1736
1737 startProcessLocked(app, hostingType, hostingNameStr);
1738 return (app.pid != 0) ? app : null;
1739 }
1740
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001741 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1742 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1743 }
1744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 private final void startProcessLocked(ProcessRecord app,
1746 String hostingType, String hostingNameStr) {
1747 if (app.pid > 0 && app.pid != MY_PID) {
1748 synchronized (mPidsSelfLocked) {
1749 mPidsSelfLocked.remove(app.pid);
1750 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1751 }
1752 app.pid = 0;
1753 }
1754
1755 mProcessesOnHold.remove(app);
1756
1757 updateCpuStats();
1758
1759 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1760 mProcDeaths[0] = 0;
1761
1762 try {
1763 int uid = app.info.uid;
1764 int[] gids = null;
1765 try {
1766 gids = mContext.getPackageManager().getPackageGids(
1767 app.info.packageName);
1768 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001769 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 }
1771 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1772 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1773 && mTopComponent != null
1774 && app.processName.equals(mTopComponent.getPackageName())) {
1775 uid = 0;
1776 }
1777 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1778 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1779 uid = 0;
1780 }
1781 }
1782 int debugFlags = 0;
1783 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1784 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1785 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001786 // Run the app in safe mode if its manifest requests so or the
1787 // system is booted in safe mode.
1788 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1789 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001790 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1793 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1794 }
1795 if ("1".equals(SystemProperties.get("debug.assert"))) {
1796 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1797 }
1798 int pid = Process.start("android.app.ActivityThread",
1799 mSimpleProcessManagement ? app.processName : null, uid, uid,
1800 gids, debugFlags, null);
1801 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1802 synchronized (bs) {
1803 if (bs.isOnBattery()) {
1804 app.batteryStats.incStartsLocked();
1805 }
1806 }
1807
Doug Zongker2bec3d42009-12-04 12:52:44 -08001808 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 app.processName, hostingType,
1810 hostingNameStr != null ? hostingNameStr : "");
1811
1812 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001813 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 }
1815
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001816 StringBuilder buf = mStringBuilder;
1817 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 buf.append("Start proc ");
1819 buf.append(app.processName);
1820 buf.append(" for ");
1821 buf.append(hostingType);
1822 if (hostingNameStr != null) {
1823 buf.append(" ");
1824 buf.append(hostingNameStr);
1825 }
1826 buf.append(": pid=");
1827 buf.append(pid);
1828 buf.append(" uid=");
1829 buf.append(uid);
1830 buf.append(" gids={");
1831 if (gids != null) {
1832 for (int gi=0; gi<gids.length; gi++) {
1833 if (gi != 0) buf.append(", ");
1834 buf.append(gids[gi]);
1835
1836 }
1837 }
1838 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001839 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 if (pid == 0 || pid == MY_PID) {
1841 // Processes are being emulated with threads.
1842 app.pid = MY_PID;
1843 app.removed = false;
1844 mStartingProcesses.add(app);
1845 } else if (pid > 0) {
1846 app.pid = pid;
1847 app.removed = false;
1848 synchronized (mPidsSelfLocked) {
1849 this.mPidsSelfLocked.put(pid, app);
1850 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1851 msg.obj = app;
1852 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1853 }
1854 } else {
1855 app.pid = 0;
1856 RuntimeException e = new RuntimeException(
1857 "Failure starting process " + app.processName
1858 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001859 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 }
1861 } catch (RuntimeException e) {
1862 // XXX do better error recovery.
1863 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001864 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865 }
1866 }
1867
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001868 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 if (resumed) {
1870 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1871 } else {
1872 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1873 }
1874 }
1875
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001876 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001877 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1878 && mTopAction == null) {
1879 // We are running in factory test mode, but unable to find
1880 // the factory test app, so just sit around displaying the
1881 // error message and don't try to start anything.
1882 return false;
1883 }
1884 Intent intent = new Intent(
1885 mTopAction,
1886 mTopData != null ? Uri.parse(mTopData) : null);
1887 intent.setComponent(mTopComponent);
1888 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1889 intent.addCategory(Intent.CATEGORY_HOME);
1890 }
1891 ActivityInfo aInfo =
1892 intent.resolveActivityInfo(mContext.getPackageManager(),
1893 STOCK_PM_FLAGS);
1894 if (aInfo != null) {
1895 intent.setComponent(new ComponentName(
1896 aInfo.applicationInfo.packageName, aInfo.name));
1897 // Don't do this if the home app is currently being
1898 // instrumented.
1899 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1900 aInfo.applicationInfo.uid);
1901 if (app == null || app.instrumentationClass == null) {
1902 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001903 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001904 null, null, 0, 0, 0, false, false);
1905 }
1906 }
1907
1908
1909 return true;
1910 }
1911
1912 /**
1913 * Starts the "new version setup screen" if appropriate.
1914 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001915 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001916 // Only do this once per boot.
1917 if (mCheckedForSetup) {
1918 return;
1919 }
1920
1921 // We will show this screen if the current one is a different
1922 // version than the last one shown, and we are not running in
1923 // low-level factory test mode.
1924 final ContentResolver resolver = mContext.getContentResolver();
1925 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1926 Settings.Secure.getInt(resolver,
1927 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1928 mCheckedForSetup = true;
1929
1930 // See if we should be showing the platform update setup UI.
1931 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1932 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1933 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1934
1935 // We don't allow third party apps to replace this.
1936 ResolveInfo ri = null;
1937 for (int i=0; ris != null && i<ris.size(); i++) {
1938 if ((ris.get(i).activityInfo.applicationInfo.flags
1939 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1940 ri = ris.get(i);
1941 break;
1942 }
1943 }
1944
1945 if (ri != null) {
1946 String vers = ri.activityInfo.metaData != null
1947 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1948 : null;
1949 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1950 vers = ri.activityInfo.applicationInfo.metaData.getString(
1951 Intent.METADATA_SETUP_VERSION);
1952 }
1953 String lastVers = Settings.Secure.getString(
1954 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1955 if (vers != null && !vers.equals(lastVers)) {
1956 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1957 intent.setComponent(new ComponentName(
1958 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001959 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001960 null, null, 0, 0, 0, false, false);
1961 }
1962 }
1963 }
1964 }
1965
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001966 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001967 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001968
1969 final int identHash = System.identityHashCode(r);
1970 updateUsageStats(r, true);
1971
1972 int i = mWatchers.beginBroadcast();
1973 while (i > 0) {
1974 i--;
1975 IActivityWatcher w = mWatchers.getBroadcastItem(i);
1976 if (w != null) {
1977 try {
1978 w.activityResuming(identHash);
1979 } catch (RemoteException e) {
1980 }
1981 }
1982 }
1983 mWatchers.finishBroadcast();
1984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001986 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001987 final int N = mPendingActivityLaunches.size();
1988 if (N <= 0) {
1989 return;
1990 }
1991 for (int i=0; i<N; i++) {
1992 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001993 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001994 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
1995 doResume && i == (N-1));
1996 }
1997 mPendingActivityLaunches.clear();
1998 }
1999
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002000 public final int startActivity(IApplicationThread caller,
2001 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2002 int grantedMode, IBinder resultTo,
2003 String resultWho, int requestCode, boolean onlyIfNeeded,
2004 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002005 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002006 grantedUriPermissions, grantedMode, resultTo, resultWho,
2007 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002008 }
2009
2010 public final WaitResult startActivityAndWait(IApplicationThread caller,
2011 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2012 int grantedMode, IBinder resultTo,
2013 String resultWho, int requestCode, boolean onlyIfNeeded,
2014 boolean debug) {
2015 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002016 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002017 grantedUriPermissions, grantedMode, resultTo, resultWho,
2018 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002019 return res;
2020 }
2021
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002022 public final int startActivityWithConfig(IApplicationThread caller,
2023 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2024 int grantedMode, IBinder resultTo,
2025 String resultWho, int requestCode, boolean onlyIfNeeded,
2026 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002027 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002028 grantedUriPermissions, grantedMode, resultTo, resultWho,
2029 requestCode, onlyIfNeeded, debug, null, config);
2030 }
2031
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002032 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002033 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002034 IBinder resultTo, String resultWho, int requestCode,
2035 int flagsMask, int flagsValues) {
2036 // Refuse possible leaked file descriptors
2037 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2038 throw new IllegalArgumentException("File descriptors passed in Intent");
2039 }
2040
2041 IIntentSender sender = intent.getTarget();
2042 if (!(sender instanceof PendingIntentRecord)) {
2043 throw new IllegalArgumentException("Bad PendingIntent object");
2044 }
2045
2046 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002047
2048 synchronized (this) {
2049 // If this is coming from the currently resumed activity, it is
2050 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002051 if (mMainStack.mResumedActivity != null
2052 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002053 Binder.getCallingUid()) {
2054 mAppSwitchesAllowedTime = 0;
2055 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002056 }
2057
2058 return pir.sendInner(0, fillInIntent, resolvedType,
2059 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2060 }
2061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 public boolean startNextMatchingActivity(IBinder callingActivity,
2063 Intent intent) {
2064 // Refuse possible leaked file descriptors
2065 if (intent != null && intent.hasFileDescriptors() == true) {
2066 throw new IllegalArgumentException("File descriptors passed in Intent");
2067 }
2068
2069 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002070 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 if (index < 0) {
2072 return false;
2073 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002074 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 if (r.app == null || r.app.thread == null) {
2076 // The caller is not running... d'oh!
2077 return false;
2078 }
2079 intent = new Intent(intent);
2080 // The caller is not allowed to change the data.
2081 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2082 // And we are resetting to find the next component...
2083 intent.setComponent(null);
2084
2085 ActivityInfo aInfo = null;
2086 try {
2087 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002088 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002090 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091
2092 // Look for the original activity in the list...
2093 final int N = resolves != null ? resolves.size() : 0;
2094 for (int i=0; i<N; i++) {
2095 ResolveInfo rInfo = resolves.get(i);
2096 if (rInfo.activityInfo.packageName.equals(r.packageName)
2097 && rInfo.activityInfo.name.equals(r.info.name)) {
2098 // We found the current one... the next matching is
2099 // after it.
2100 i++;
2101 if (i<N) {
2102 aInfo = resolves.get(i).activityInfo;
2103 }
2104 break;
2105 }
2106 }
2107 } catch (RemoteException e) {
2108 }
2109
2110 if (aInfo == null) {
2111 // Nobody who is next!
2112 return false;
2113 }
2114
2115 intent.setComponent(new ComponentName(
2116 aInfo.applicationInfo.packageName, aInfo.name));
2117 intent.setFlags(intent.getFlags()&~(
2118 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2119 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2120 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2121 Intent.FLAG_ACTIVITY_NEW_TASK));
2122
2123 // Okay now we need to start the new activity, replacing the
2124 // currently running activity. This is a little tricky because
2125 // we want to start the new one as if the current one is finished,
2126 // but not finish the current one first so that there is no flicker.
2127 // And thus...
2128 final boolean wasFinishing = r.finishing;
2129 r.finishing = true;
2130
2131 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002132 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 final String resultWho = r.resultWho;
2134 final int requestCode = r.requestCode;
2135 r.resultTo = null;
2136 if (resultTo != null) {
2137 resultTo.removeResultsLocked(r, resultWho, requestCode);
2138 }
2139
2140 final long origId = Binder.clearCallingIdentity();
2141 // XXX we are not dealing with propagating grantedUriPermissions...
2142 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002143 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002145 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 Binder.restoreCallingIdentity(origId);
2147
2148 r.finishing = wasFinishing;
2149 if (res != START_SUCCESS) {
2150 return false;
2151 }
2152 return true;
2153 }
2154 }
2155
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002156 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 Intent intent, String resolvedType, IBinder resultTo,
2158 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002159
2160 // This is so super not safe, that only the system (or okay root)
2161 // can do it.
2162 final int callingUid = Binder.getCallingUid();
2163 if (callingUid != 0 && callingUid != Process.myUid()) {
2164 throw new SecurityException(
2165 "startActivityInPackage only available to the system");
2166 }
2167
The Android Open Source Project4df24232009-03-05 14:34:35 -08002168 final boolean componentSpecified = intent.getComponent() != null;
2169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 // Don't modify the client's object!
2171 intent = new Intent(intent);
2172
2173 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 ActivityInfo aInfo;
2175 try {
2176 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002177 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002179 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 aInfo = rInfo != null ? rInfo.activityInfo : null;
2181 } catch (RemoteException e) {
2182 aInfo = null;
2183 }
2184
2185 if (aInfo != null) {
2186 // Store the found target back into the intent, because now that
2187 // we have it we never want to do this again. For example, if the
2188 // user navigates back to this point in the history, we should
2189 // always restart the exact same activity.
2190 intent.setComponent(new ComponentName(
2191 aInfo.applicationInfo.packageName, aInfo.name));
2192 }
2193
2194 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002195 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002197 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 }
2199 }
2200
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002201 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202 // Remove any existing entries that are the same kind of task.
2203 int N = mRecentTasks.size();
2204 for (int i=0; i<N; i++) {
2205 TaskRecord tr = mRecentTasks.get(i);
2206 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2207 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2208 mRecentTasks.remove(i);
2209 i--;
2210 N--;
2211 if (task.intent == null) {
2212 // If the new recent task we are adding is not fully
2213 // specified, then replace it with the existing recent task.
2214 task = tr;
2215 }
2216 }
2217 }
2218 if (N >= MAX_RECENT_TASKS) {
2219 mRecentTasks.remove(N-1);
2220 }
2221 mRecentTasks.add(0, task);
2222 }
2223
2224 public void setRequestedOrientation(IBinder token,
2225 int requestedOrientation) {
2226 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002227 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 if (index < 0) {
2229 return;
2230 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002231 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 final long origId = Binder.clearCallingIdentity();
2233 mWindowManager.setAppOrientation(r, requestedOrientation);
2234 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002235 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 r.mayFreezeScreenLocked(r.app) ? r : null);
2237 if (config != null) {
2238 r.frozenBeforeDestroy = true;
2239 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002240 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002241 }
2242 }
2243 Binder.restoreCallingIdentity(origId);
2244 }
2245 }
2246
2247 public int getRequestedOrientation(IBinder token) {
2248 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002249 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 if (index < 0) {
2251 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2252 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002253 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 return mWindowManager.getAppOrientation(r);
2255 }
2256 }
2257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 /**
2259 * This is the internal entry point for handling Activity.finish().
2260 *
2261 * @param token The Binder token referencing the Activity we want to finish.
2262 * @param resultCode Result code, if any, from this Activity.
2263 * @param resultData Result data (Intent), if any, from this Activity.
2264 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002265 * @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 -08002266 */
2267 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2268 // Refuse possible leaked file descriptors
2269 if (resultData != null && resultData.hasFileDescriptors() == true) {
2270 throw new IllegalArgumentException("File descriptors passed in Intent");
2271 }
2272
2273 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002274 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002276 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 if (next != null) {
2278 // ask watcher if this is allowed
2279 boolean resumeOK = true;
2280 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002281 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002283 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 }
2285
2286 if (!resumeOK) {
2287 return false;
2288 }
2289 }
2290 }
2291 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002292 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 resultData, "app-request");
2294 Binder.restoreCallingIdentity(origId);
2295 return res;
2296 }
2297 }
2298
Dianne Hackborn860755f2010-06-03 18:47:52 -07002299 public final void finishHeavyWeightApp() {
2300 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2301 != PackageManager.PERMISSION_GRANTED) {
2302 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2303 + Binder.getCallingPid()
2304 + ", uid=" + Binder.getCallingUid()
2305 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2306 Slog.w(TAG, msg);
2307 throw new SecurityException(msg);
2308 }
2309
2310 synchronized(this) {
2311 if (mHeavyWeightProcess == null) {
2312 return;
2313 }
2314
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002315 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002316 mHeavyWeightProcess.activities);
2317 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002318 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002319 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002320 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002321 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002322 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002323 null, "finish-heavy");
2324 }
2325 }
2326 }
2327
2328 mHeavyWeightProcess = null;
2329 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2330 }
2331 }
2332
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002333 public void crashApplication(int uid, int initialPid, String packageName,
2334 String message) {
2335 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2336 != PackageManager.PERMISSION_GRANTED) {
2337 String msg = "Permission Denial: crashApplication() from pid="
2338 + Binder.getCallingPid()
2339 + ", uid=" + Binder.getCallingUid()
2340 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2341 Slog.w(TAG, msg);
2342 throw new SecurityException(msg);
2343 }
2344
2345 synchronized(this) {
2346 ProcessRecord proc = null;
2347
2348 // Figure out which process to kill. We don't trust that initialPid
2349 // still has any relation to current pids, so must scan through the
2350 // list.
2351 synchronized (mPidsSelfLocked) {
2352 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2353 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2354 if (p.info.uid != uid) {
2355 continue;
2356 }
2357 if (p.pid == initialPid) {
2358 proc = p;
2359 break;
2360 }
2361 for (String str : p.pkgList) {
2362 if (str.equals(packageName)) {
2363 proc = p;
2364 }
2365 }
2366 }
2367 }
2368
2369 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002370 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002371 + " initialPid=" + initialPid
2372 + " packageName=" + packageName);
2373 return;
2374 }
2375
2376 if (proc.thread != null) {
2377 long ident = Binder.clearCallingIdentity();
2378 try {
2379 proc.thread.scheduleCrash(message);
2380 } catch (RemoteException e) {
2381 }
2382 Binder.restoreCallingIdentity(ident);
2383 }
2384 }
2385 }
2386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 public final void finishSubActivity(IBinder token, String resultWho,
2388 int requestCode) {
2389 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002390 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391 if (index < 0) {
2392 return;
2393 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002394 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002395
2396 final long origId = Binder.clearCallingIdentity();
2397
2398 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002399 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2400 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401 if (r.resultTo == self && r.requestCode == requestCode) {
2402 if ((r.resultWho == null && resultWho == null) ||
2403 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002404 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 Activity.RESULT_CANCELED, null, "request-sub");
2406 }
2407 }
2408 }
2409
2410 Binder.restoreCallingIdentity(origId);
2411 }
2412 }
2413
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002414 public boolean willActivityBeVisible(IBinder token) {
2415 synchronized(this) {
2416 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002417 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2418 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002419 if (r == token) {
2420 return true;
2421 }
2422 if (r.fullscreen && !r.finishing) {
2423 return false;
2424 }
2425 }
2426 return true;
2427 }
2428 }
2429
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002430 public void overridePendingTransition(IBinder token, String packageName,
2431 int enterAnim, int exitAnim) {
2432 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002433 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002434 if (index < 0) {
2435 return;
2436 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002437 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002438
2439 final long origId = Binder.clearCallingIdentity();
2440
2441 if (self.state == ActivityState.RESUMED
2442 || self.state == ActivityState.PAUSING) {
2443 mWindowManager.overridePendingAppTransition(packageName,
2444 enterAnim, exitAnim);
2445 }
2446
2447 Binder.restoreCallingIdentity(origId);
2448 }
2449 }
2450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002451 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002452 * Main function for removing an existing process from the activity manager
2453 * as a result of that process going away. Clears out all connections
2454 * to the process.
2455 */
2456 private final void handleAppDiedLocked(ProcessRecord app,
2457 boolean restarting) {
2458 cleanUpApplicationRecordLocked(app, restarting, -1);
2459 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002460 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461 }
2462
2463 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002464 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2465 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2466 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002468 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2469 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 }
2471
2472 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002473 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002474
2475 boolean atTop = true;
2476 boolean hasVisibleActivities = false;
2477
2478 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002479 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002480 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 TAG, "Removing app " + app + " from history with " + i + " entries");
2482 while (i > 0) {
2483 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002484 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002485 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2487 if (r.app == app) {
2488 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002489 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002490 TAG, "Removing this entry! frozen=" + r.haveState
2491 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002492 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493
2494 r.inHistory = false;
2495 mWindowManager.removeAppToken(r);
2496 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002497 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002499 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500
2501 } else {
2502 // We have the current state for this activity, so
2503 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002504 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 TAG, "Keeping entry, setting app to null");
2506 if (r.visible) {
2507 hasVisibleActivities = true;
2508 }
2509 r.app = null;
2510 r.nowVisible = false;
2511 if (!r.haveState) {
2512 r.icicle = null;
2513 }
2514 }
2515
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002516 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 r.state = ActivityState.STOPPED;
2518 }
2519 atTop = false;
2520 }
2521
2522 app.activities.clear();
2523
2524 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002525 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 + " running instrumentation " + app.instrumentationClass);
2527 Bundle info = new Bundle();
2528 info.putString("shortMsg", "Process crashed.");
2529 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2530 }
2531
2532 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002533 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002534 // If there was nothing to resume, and we are not already
2535 // restarting this process, but there is a visible activity that
2536 // is hosted by the process... then make sure all visible
2537 // activities are running, taking care of restarting this
2538 // process.
2539 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002540 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541 }
2542 }
2543 }
2544 }
2545
2546 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2547 IBinder threadBinder = thread.asBinder();
2548
2549 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002550 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2551 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2553 return i;
2554 }
2555 }
2556 return -1;
2557 }
2558
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002559 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 IApplicationThread thread) {
2561 if (thread == null) {
2562 return null;
2563 }
2564
2565 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002566 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 }
2568
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002569 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 IApplicationThread thread) {
2571
2572 mProcDeaths[0]++;
2573
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002574 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2575 synchronized (stats) {
2576 stats.noteProcessDiedLocked(app.info.uid, pid);
2577 }
2578
Magnus Edlund7bb25812010-02-24 15:45:06 +01002579 // Clean up already done if the process has been re-started.
2580 if (app.pid == pid && app.thread != null &&
2581 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002582 if (!app.killedBackground) {
2583 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2584 + ") has died.");
2585 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002586 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002587 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 TAG, "Dying app: " + app + ", pid: " + pid
2589 + ", thread: " + thread.asBinder());
2590 boolean doLowMem = app.instrumentationClass == null;
2591 handleAppDiedLocked(app, false);
2592
2593 if (doLowMem) {
2594 // If there are no longer any background processes running,
2595 // and the app that died was not running instrumentation,
2596 // then tell everyone we are now low on memory.
2597 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002598 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2599 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2601 haveBg = true;
2602 break;
2603 }
2604 }
2605
2606 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002607 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002608 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002609 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002610 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2611 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002612 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002613 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2614 // The low memory report is overriding any current
2615 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002616 // heavy/important/visible/foreground processes first.
2617 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002618 rec.lastRequestedGc = 0;
2619 } else {
2620 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002622 rec.reportLowMemory = true;
2623 rec.lastLowMemory = now;
2624 mProcessesToGc.remove(rec);
2625 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 }
2627 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002628 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 }
2630 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002631 } else if (app.pid != pid) {
2632 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002633 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002634 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002635 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002636 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002637 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 + thread.asBinder());
2639 }
2640 }
2641
Dan Egnor42471dd2010-01-07 17:25:22 -08002642 /**
2643 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002644 * @param clearTraces causes the dump file to be erased prior to the new
2645 * traces being written, if true; when false, the new traces will be
2646 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08002647 * @param pids of dalvik VM processes to dump stack traces for
2648 * @return file containing stack traces, or null if no dump file is configured
2649 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07002650 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002651 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2652 if (tracesPath == null || tracesPath.length() == 0) {
2653 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002655
2656 File tracesFile = new File(tracesPath);
2657 try {
2658 File tracesDir = tracesFile.getParentFile();
2659 if (!tracesDir.exists()) tracesFile.mkdirs();
2660 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2661
Christopher Tate6ee412d2010-05-28 12:01:56 -07002662 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002663 tracesFile.createNewFile();
2664 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2665 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002666 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002667 return null;
2668 }
2669
2670 // Use a FileObserver to detect when traces finish writing.
2671 // The order of traces is considered important to maintain for legibility.
2672 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2673 public synchronized void onEvent(int event, String path) { notify(); }
2674 };
2675
2676 try {
2677 observer.startWatching();
2678 int num = pids.size();
2679 for (int i = 0; i < num; i++) {
2680 synchronized (observer) {
2681 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
2682 observer.wait(200); // Wait for write-close, give up after 200msec
2683 }
2684 }
2685 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08002686 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002687 } finally {
2688 observer.stopWatching();
2689 }
2690
2691 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 }
2693
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002694 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2695 ActivityRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002696 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002697
2698 synchronized (this) {
2699 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2700 if (mShuttingDown) {
2701 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2702 return;
2703 } else if (app.notResponding) {
2704 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2705 return;
2706 } else if (app.crashing) {
2707 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2708 return;
2709 }
2710
2711 // In case we come through here for the same app before completing
2712 // this one, mark as anring now so we will bail out.
2713 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002714
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002715 // Log the ANR to the event log.
2716 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2717 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002718
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002719 // Dump thread traces as quickly as we can, starting with "interesting" processes.
2720 pids.add(app.pid);
2721
2722 int parentPid = app.pid;
2723 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
2724 if (parentPid != app.pid) pids.add(parentPid);
2725
2726 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002727
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002728 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2729 ProcessRecord r = mLruProcesses.get(i);
2730 if (r != null && r.thread != null) {
2731 int pid = r.pid;
2732 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
2733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 }
2735 }
2736
Christopher Tate6ee412d2010-05-28 12:01:56 -07002737 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002738
2739 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002740 StringBuilder info = mStringBuilder;
2741 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002742 info.append("ANR in ").append(app.processName);
2743 if (activity != null && activity.shortComponentName != null) {
2744 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002745 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002746 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002748 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002750 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002751 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753
Dan Egnor42471dd2010-01-07 17:25:22 -08002754 String cpuInfo = null;
2755 if (MONITOR_CPU_USAGE) {
2756 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002757 synchronized (mProcessStatsThread) {
2758 cpuInfo = mProcessStats.printCurrentState();
2759 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002760 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 }
2762
Joe Onorato8a9b2202010-02-26 18:56:32 -08002763 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002764 if (tracesFile == null) {
2765 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2766 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2767 }
2768
2769 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2770
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002771 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002772 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002773 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2774 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002776 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2777 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 }
2779 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002780 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 }
2782 }
2783
Dan Egnor42471dd2010-01-07 17:25:22 -08002784 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2785 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2786 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002787
2788 synchronized (this) {
2789 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2790 Process.killProcess(app.pid);
2791 return;
2792 }
2793
2794 // Set the app's notResponding state, and look up the errorReportReceiver
2795 makeAppNotRespondingLocked(app,
2796 activity != null ? activity.shortComponentName : null,
2797 annotation != null ? "ANR " + annotation : "ANR",
2798 info.toString());
2799
2800 // Bring up the infamous App Not Responding dialog
2801 Message msg = Message.obtain();
2802 HashMap map = new HashMap();
2803 msg.what = SHOW_NOT_RESPONDING_MSG;
2804 msg.obj = map;
2805 map.put("app", app);
2806 if (activity != null) {
2807 map.put("activity", activity);
2808 }
2809
2810 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002812 }
2813
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002814 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 app.persistentActivities--;
2816 if (app.persistentActivities > 0) {
2817 // Still more of 'em...
2818 return;
2819 }
2820 if (app.persistent) {
2821 // Ah, but the application itself is persistent. Whatever!
2822 return;
2823 }
2824
2825 // App is no longer persistent... make sure it and the ones
2826 // following it in the LRU list have the correc oom_adj.
2827 updateOomAdjLocked();
2828 }
2829
2830 public void setPersistent(IBinder token, boolean isPersistent) {
2831 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2832 != PackageManager.PERMISSION_GRANTED) {
2833 String msg = "Permission Denial: setPersistent() from pid="
2834 + Binder.getCallingPid()
2835 + ", uid=" + Binder.getCallingUid()
2836 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002837 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002838 throw new SecurityException(msg);
2839 }
2840
2841 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002842 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002843 if (index < 0) {
2844 return;
2845 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002846 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002847 ProcessRecord app = r.app;
2848
Joe Onorato8a9b2202010-02-26 18:56:32 -08002849 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002850 TAG, "Setting persistence " + isPersistent + ": " + r);
2851
2852 if (isPersistent) {
2853 if (r.persistent) {
2854 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002855 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 return;
2857 }
2858 r.persistent = true;
2859 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002860 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002861 if (app.persistentActivities > 1) {
2862 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002863 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 return;
2865 }
2866 if (app.persistent) {
2867 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002868 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 return;
2870 }
2871
2872 // App is now persistent... make sure it and the ones
2873 // following it now have the correct oom_adj.
2874 final long origId = Binder.clearCallingIdentity();
2875 updateOomAdjLocked();
2876 Binder.restoreCallingIdentity(origId);
2877
2878 } else {
2879 if (!r.persistent) {
2880 // Okay okay, I heard you already!
2881 return;
2882 }
2883 r.persistent = false;
2884 final long origId = Binder.clearCallingIdentity();
2885 decPersistentCountLocked(app);
2886 Binder.restoreCallingIdentity(origId);
2887
2888 }
2889 }
2890 }
2891
2892 public boolean clearApplicationUserData(final String packageName,
2893 final IPackageDataObserver observer) {
2894 int uid = Binder.getCallingUid();
2895 int pid = Binder.getCallingPid();
2896 long callingId = Binder.clearCallingIdentity();
2897 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002898 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 int pkgUid = -1;
2900 synchronized(this) {
2901 try {
2902 pkgUid = pm.getPackageUid(packageName);
2903 } catch (RemoteException e) {
2904 }
2905 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002906 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002907 return false;
2908 }
2909 if (uid == pkgUid || checkComponentPermission(
2910 android.Manifest.permission.CLEAR_APP_USER_DATA,
2911 pid, uid, -1)
2912 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08002913 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914 } else {
2915 throw new SecurityException(pid+" does not have permission:"+
2916 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
2917 "for process:"+packageName);
2918 }
2919 }
2920
2921 try {
2922 //clear application user data
2923 pm.clearApplicationUserData(packageName, observer);
2924 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
2925 Uri.fromParts("package", packageName, null));
2926 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06002927 synchronized (this) {
2928 broadcastIntentLocked(null, null, intent,
2929 null, null, 0, null, null, null,
2930 false, false, MY_PID, Process.SYSTEM_UID);
2931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 } catch (RemoteException e) {
2933 }
2934 } finally {
2935 Binder.restoreCallingIdentity(callingId);
2936 }
2937 return true;
2938 }
2939
Dianne Hackborn03abb812010-01-04 18:43:19 -08002940 public void killBackgroundProcesses(final String packageName) {
2941 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
2942 != PackageManager.PERMISSION_GRANTED &&
2943 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
2944 != PackageManager.PERMISSION_GRANTED) {
2945 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 + Binder.getCallingPid()
2947 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08002948 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002949 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 throw new SecurityException(msg);
2951 }
2952
2953 long callingId = Binder.clearCallingIdentity();
2954 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002955 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002956 int pkgUid = -1;
2957 synchronized(this) {
2958 try {
2959 pkgUid = pm.getPackageUid(packageName);
2960 } catch (RemoteException e) {
2961 }
2962 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002963 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 return;
2965 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08002966 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002967 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002968 }
2969 } finally {
2970 Binder.restoreCallingIdentity(callingId);
2971 }
2972 }
2973
2974 public void forceStopPackage(final String packageName) {
2975 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2976 != PackageManager.PERMISSION_GRANTED) {
2977 String msg = "Permission Denial: forceStopPackage() from pid="
2978 + Binder.getCallingPid()
2979 + ", uid=" + Binder.getCallingUid()
2980 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002981 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002982 throw new SecurityException(msg);
2983 }
2984
2985 long callingId = Binder.clearCallingIdentity();
2986 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002987 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08002988 int pkgUid = -1;
2989 synchronized(this) {
2990 try {
2991 pkgUid = pm.getPackageUid(packageName);
2992 } catch (RemoteException e) {
2993 }
2994 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002995 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002996 return;
2997 }
2998 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002999 }
3000 } finally {
3001 Binder.restoreCallingIdentity(callingId);
3002 }
3003 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003004
3005 /*
3006 * The pkg name and uid have to be specified.
3007 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3008 */
3009 public void killApplicationWithUid(String pkg, int uid) {
3010 if (pkg == null) {
3011 return;
3012 }
3013 // Make sure the uid is valid.
3014 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003015 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003016 return;
3017 }
3018 int callerUid = Binder.getCallingUid();
3019 // Only the system server can kill an application
3020 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003021 // Post an aysnc message to kill the application
3022 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3023 msg.arg1 = uid;
3024 msg.arg2 = 0;
3025 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003026 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003027 } else {
3028 throw new SecurityException(callerUid + " cannot kill pkg: " +
3029 pkg);
3030 }
3031 }
3032
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003033 public void closeSystemDialogs(String reason) {
3034 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3035 if (reason != null) {
3036 intent.putExtra("reason", reason);
3037 }
3038
3039 final int uid = Binder.getCallingUid();
3040 final long origId = Binder.clearCallingIdentity();
3041 synchronized (this) {
3042 int i = mWatchers.beginBroadcast();
3043 while (i > 0) {
3044 i--;
3045 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3046 if (w != null) {
3047 try {
3048 w.closingSystemDialogs(reason);
3049 } catch (RemoteException e) {
3050 }
3051 }
3052 }
3053 mWatchers.finishBroadcast();
3054
Dianne Hackbornffa42482009-09-23 22:20:11 -07003055 mWindowManager.closeSystemDialogs(reason);
3056
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003057 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3058 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003059 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003060 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003061 Activity.RESULT_CANCELED, null, "close-sys");
3062 }
3063 }
3064
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003065 broadcastIntentLocked(null, null, intent, null,
3066 null, 0, null, null, null, false, false, -1, uid);
3067 }
3068 Binder.restoreCallingIdentity(origId);
3069 }
3070
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003071 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003072 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003073 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3074 for (int i=pids.length-1; i>=0; i--) {
3075 infos[i] = new Debug.MemoryInfo();
3076 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003077 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003078 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003079 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003080
3081 public void killApplicationProcess(String processName, int uid) {
3082 if (processName == null) {
3083 return;
3084 }
3085
3086 int callerUid = Binder.getCallingUid();
3087 // Only the system server can kill an application
3088 if (callerUid == Process.SYSTEM_UID) {
3089 synchronized (this) {
3090 ProcessRecord app = getProcessRecordLocked(processName, uid);
3091 if (app != null) {
3092 try {
3093 app.thread.scheduleSuicide();
3094 } catch (RemoteException e) {
3095 // If the other end already died, then our work here is done.
3096 }
3097 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003098 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003099 + processName + " / " + uid);
3100 }
3101 }
3102 } else {
3103 throw new SecurityException(callerUid + " cannot kill app process: " +
3104 processName);
3105 }
3106 }
3107
Dianne Hackborn03abb812010-01-04 18:43:19 -08003108 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003109 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3111 Uri.fromParts("package", packageName, null));
3112 intent.putExtra(Intent.EXTRA_UID, uid);
3113 broadcastIntentLocked(null, null, intent,
3114 null, null, 0, null, null, null,
3115 false, false, MY_PID, Process.SYSTEM_UID);
3116 }
3117
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003118 private final boolean killPackageProcessesLocked(String packageName, int uid,
3119 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003120 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121
Dianne Hackborn03abb812010-01-04 18:43:19 -08003122 // Remove all processes this package may have touched: all with the
3123 // same UID (except for the system or root user), and all whose name
3124 // matches the package name.
3125 final String procNamePrefix = packageName + ":";
3126 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3127 final int NA = apps.size();
3128 for (int ia=0; ia<NA; ia++) {
3129 ProcessRecord app = apps.valueAt(ia);
3130 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003131 if (doit) {
3132 procs.add(app);
3133 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003134 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3135 || app.processName.equals(packageName)
3136 || app.processName.startsWith(procNamePrefix)) {
3137 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003138 if (!doit) {
3139 return true;
3140 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003141 app.removed = true;
3142 procs.add(app);
3143 }
3144 }
3145 }
3146 }
3147
3148 int N = procs.size();
3149 for (int i=0; i<N; i++) {
3150 removeProcessLocked(procs.get(i), callerWillRestart);
3151 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003152 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003153 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003154
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003155 private final boolean forceStopPackageLocked(String name, int uid,
3156 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 int i, N;
3158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 if (uid < 0) {
3160 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003161 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 } catch (RemoteException e) {
3163 }
3164 }
3165
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003166 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003167 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003168
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003169 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3170 while (badApps.hasNext()) {
3171 SparseArray<Long> ba = badApps.next();
3172 if (ba.get(uid) != null) {
3173 badApps.remove();
3174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 }
3176 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003177
3178 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3179 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003181 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3182 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003184 if (!doit) {
3185 return true;
3186 }
3187 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003188 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 if (r.app != null) {
3190 r.app.removed = true;
3191 }
3192 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003193 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 }
3195 }
3196
3197 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3198 for (ServiceRecord service : mServices.values()) {
3199 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003200 if (!doit) {
3201 return true;
3202 }
3203 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003204 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 if (service.app != null) {
3206 service.app.removed = true;
3207 }
3208 service.app = null;
3209 services.add(service);
3210 }
3211 }
3212
3213 N = services.size();
3214 for (i=0; i<N; i++) {
3215 bringDownServiceLocked(services.get(i), true);
3216 }
3217
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003218 if (doit) {
3219 if (purgeCache) {
3220 AttributeCache ac = AttributeCache.instance();
3221 if (ac != null) {
3222 ac.removePackage(name);
3223 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003224 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003225 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003226 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003227
3228 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 }
3230
3231 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3232 final String name = app.processName;
3233 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003234 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003235 TAG, "Force removing process " + app + " (" + name
3236 + "/" + uid + ")");
3237
3238 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003239 if (mHeavyWeightProcess == app) {
3240 mHeavyWeightProcess = null;
3241 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003243 boolean needRestart = false;
3244 if (app.pid > 0 && app.pid != MY_PID) {
3245 int pid = app.pid;
3246 synchronized (mPidsSelfLocked) {
3247 mPidsSelfLocked.remove(pid);
3248 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3249 }
3250 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003251 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003252 Process.killProcess(pid);
3253
3254 if (app.persistent) {
3255 if (!callerWillRestart) {
3256 addAppLocked(app.info);
3257 } else {
3258 needRestart = true;
3259 }
3260 }
3261 } else {
3262 mRemovedProcesses.add(app);
3263 }
3264
3265 return needRestart;
3266 }
3267
3268 private final void processStartTimedOutLocked(ProcessRecord app) {
3269 final int pid = app.pid;
3270 boolean gone = false;
3271 synchronized (mPidsSelfLocked) {
3272 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3273 if (knownApp != null && knownApp.thread == null) {
3274 mPidsSelfLocked.remove(pid);
3275 gone = true;
3276 }
3277 }
3278
3279 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003280 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003281 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003282 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003283 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003284 if (mHeavyWeightProcess == app) {
3285 mHeavyWeightProcess = null;
3286 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3287 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003288 // Take care of any launching providers waiting for this process.
3289 checkAppInLaunchingProvidersLocked(app, true);
3290 // Take care of any services that are waiting for the process.
3291 for (int i=0; i<mPendingServices.size(); i++) {
3292 ServiceRecord sr = mPendingServices.get(i);
3293 if (app.info.uid == sr.appInfo.uid
3294 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003295 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003296 mPendingServices.remove(i);
3297 i--;
3298 bringDownServiceLocked(sr, true);
3299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003300 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003301 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003302 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003303 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003304 try {
3305 IBackupManager bm = IBackupManager.Stub.asInterface(
3306 ServiceManager.getService(Context.BACKUP_SERVICE));
3307 bm.agentDisconnected(app.info.packageName);
3308 } catch (RemoteException e) {
3309 // Can't happen; the backup manager is local
3310 }
3311 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003312 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003313 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003314 mPendingBroadcast = null;
3315 scheduleBroadcastsLocked();
3316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003318 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 }
3320 }
3321
3322 private final boolean attachApplicationLocked(IApplicationThread thread,
3323 int pid) {
3324
3325 // Find the application record that is being attached... either via
3326 // the pid if we are running in multiple processes, or just pull the
3327 // next app record if we are emulating process with anonymous threads.
3328 ProcessRecord app;
3329 if (pid != MY_PID && pid >= 0) {
3330 synchronized (mPidsSelfLocked) {
3331 app = mPidsSelfLocked.get(pid);
3332 }
3333 } else if (mStartingProcesses.size() > 0) {
3334 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003335 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 } else {
3337 app = null;
3338 }
3339
3340 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003341 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003343 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 if (pid > 0 && pid != MY_PID) {
3345 Process.killProcess(pid);
3346 } else {
3347 try {
3348 thread.scheduleExit();
3349 } catch (Exception e) {
3350 // Ignore exceptions.
3351 }
3352 }
3353 return false;
3354 }
3355
3356 // If this application record is still attached to a previous
3357 // process, clean it up now.
3358 if (app.thread != null) {
3359 handleAppDiedLocked(app, true);
3360 }
3361
3362 // Tell the process all about itself.
3363
Joe Onorato8a9b2202010-02-26 18:56:32 -08003364 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 TAG, "Binding process pid " + pid + " to record " + app);
3366
3367 String processName = app.processName;
3368 try {
3369 thread.asBinder().linkToDeath(new AppDeathRecipient(
3370 app, pid, thread), 0);
3371 } catch (RemoteException e) {
3372 app.resetPackageList();
3373 startProcessLocked(app, "link fail", processName);
3374 return false;
3375 }
3376
Doug Zongker2bec3d42009-12-04 12:52:44 -08003377 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003378
3379 app.thread = thread;
3380 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003381 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3382 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 app.forcingToForeground = null;
3384 app.foregroundServices = false;
3385 app.debugging = false;
3386
3387 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3388
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003389 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3390 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003392 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003393 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003394 }
3395
Joe Onorato8a9b2202010-02-26 18:56:32 -08003396 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397 TAG, "New app record " + app
3398 + " thread=" + thread.asBinder() + " pid=" + pid);
3399 try {
3400 int testMode = IApplicationThread.DEBUG_OFF;
3401 if (mDebugApp != null && mDebugApp.equals(processName)) {
3402 testMode = mWaitForDebugger
3403 ? IApplicationThread.DEBUG_WAIT
3404 : IApplicationThread.DEBUG_ON;
3405 app.debugging = true;
3406 if (mDebugTransient) {
3407 mDebugApp = mOrigDebugApp;
3408 mWaitForDebugger = mOrigWaitForDebugger;
3409 }
3410 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003411
Christopher Tate181fafa2009-05-14 11:12:14 -07003412 // If the app is being launched for restore or full backup, set it up specially
3413 boolean isRestrictedBackupMode = false;
3414 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3415 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3416 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3417 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003418
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003419 ensurePackageDexOpt(app.instrumentationInfo != null
3420 ? app.instrumentationInfo.packageName
3421 : app.info.packageName);
3422 if (app.instrumentationClass != null) {
3423 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003424 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003425 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003426 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003427 thread.bindApplication(processName, app.instrumentationInfo != null
3428 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 app.instrumentationClass, app.instrumentationProfileFile,
3430 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003431 isRestrictedBackupMode || !normalMode,
3432 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003433 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003434 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 } catch (Exception e) {
3436 // todo: Yikes! What should we do? For now we will try to
3437 // start another process, but that could easily get us in
3438 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003439 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440
3441 app.resetPackageList();
3442 startProcessLocked(app, "bind fail", processName);
3443 return false;
3444 }
3445
3446 // Remove this record from the list of starting applications.
3447 mPersistentStartingProcesses.remove(app);
3448 mProcessesOnHold.remove(app);
3449
3450 boolean badApp = false;
3451 boolean didSomething = false;
3452
3453 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003454 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003455 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3457 && processName.equals(hr.processName)) {
3458 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003459 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 didSomething = true;
3461 }
3462 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003463 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 + hr.intent.getComponent().flattenToShortString(), e);
3465 badApp = true;
3466 }
3467 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003468 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 }
3470 }
3471
3472 // Find any services that should be running in this process...
3473 if (!badApp && mPendingServices.size() > 0) {
3474 ServiceRecord sr = null;
3475 try {
3476 for (int i=0; i<mPendingServices.size(); i++) {
3477 sr = mPendingServices.get(i);
3478 if (app.info.uid != sr.appInfo.uid
3479 || !processName.equals(sr.processName)) {
3480 continue;
3481 }
3482
3483 mPendingServices.remove(i);
3484 i--;
3485 realStartServiceLocked(sr, app);
3486 didSomething = true;
3487 }
3488 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003489 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490 + sr.shortName, e);
3491 badApp = true;
3492 }
3493 }
3494
3495 // Check if the next broadcast receiver is in this process...
3496 BroadcastRecord br = mPendingBroadcast;
3497 if (!badApp && br != null && br.curApp == app) {
3498 try {
3499 mPendingBroadcast = null;
3500 processCurBroadcastLocked(br, app);
3501 didSomething = true;
3502 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003503 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 + br.curComponent.flattenToShortString(), e);
3505 badApp = true;
3506 logBroadcastReceiverDiscard(br);
3507 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3508 br.resultExtras, br.resultAbort, true);
3509 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003510 // We need to reset the state if we fails to start the receiver.
3511 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 }
3513 }
3514
Christopher Tate181fafa2009-05-14 11:12:14 -07003515 // Check whether the next backup agent is in this process...
3516 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003517 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003518 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003519 try {
3520 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3521 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003522 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003523 e.printStackTrace();
3524 }
3525 }
3526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003527 if (badApp) {
3528 // todo: Also need to kill application to deal with all
3529 // kinds of exceptions.
3530 handleAppDiedLocked(app, false);
3531 return false;
3532 }
3533
3534 if (!didSomething) {
3535 updateOomAdjLocked();
3536 }
3537
3538 return true;
3539 }
3540
3541 public final void attachApplication(IApplicationThread thread) {
3542 synchronized (this) {
3543 int callingPid = Binder.getCallingPid();
3544 final long origId = Binder.clearCallingIdentity();
3545 attachApplicationLocked(thread, callingPid);
3546 Binder.restoreCallingIdentity(origId);
3547 }
3548 }
3549
Dianne Hackborne88846e2009-09-30 21:34:25 -07003550 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003552 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003553 Binder.restoreCallingIdentity(origId);
3554 }
3555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003557 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003558 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 mWindowManager.enableScreenAfterBoot();
3560 }
3561
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003562 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003563 IntentFilter pkgFilter = new IntentFilter();
3564 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3565 pkgFilter.addDataScheme("package");
3566 mContext.registerReceiver(new BroadcastReceiver() {
3567 @Override
3568 public void onReceive(Context context, Intent intent) {
3569 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3570 if (pkgs != null) {
3571 for (String pkg : pkgs) {
3572 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3573 setResultCode(Activity.RESULT_OK);
3574 return;
3575 }
3576 }
3577 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003578 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003579 }, pkgFilter);
3580
3581 synchronized (this) {
3582 // Ensure that any processes we had put on hold are now started
3583 // up.
3584 final int NP = mProcessesOnHold.size();
3585 if (NP > 0) {
3586 ArrayList<ProcessRecord> procs =
3587 new ArrayList<ProcessRecord>(mProcessesOnHold);
3588 for (int ip=0; ip<NP; ip++) {
3589 this.startProcessLocked(procs.get(ip), "on-hold", null);
3590 }
3591 }
3592
3593 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003594 // Start looking for apps that are abusing wake locks.
3595 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
3596 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003597 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003598 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003599 broadcastIntentLocked(null, null,
3600 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3601 null, null, 0, null, null,
3602 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3603 false, false, MY_PID, Process.SYSTEM_UID);
3604 }
3605 }
3606 }
3607
3608 final void ensureBootCompleted() {
3609 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003610 boolean enableScreen;
3611 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003612 booting = mBooting;
3613 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003614 enableScreen = !mBooted;
3615 mBooted = true;
3616 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003617
3618 if (booting) {
3619 finishBooting();
3620 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003621
3622 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003623 enableScreenAfterBoot();
3624 }
3625 }
3626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 public final void activityPaused(IBinder token, Bundle icicle) {
3628 // Refuse possible leaked file descriptors
3629 if (icicle != null && icicle.hasFileDescriptors()) {
3630 throw new IllegalArgumentException("File descriptors passed in Bundle");
3631 }
3632
3633 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003634 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635 Binder.restoreCallingIdentity(origId);
3636 }
3637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 public final void activityStopped(IBinder token, Bitmap thumbnail,
3639 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003640 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 TAG, "Activity stopped: token=" + token);
3642
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003643 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644
3645 final long origId = Binder.clearCallingIdentity();
3646
3647 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003648 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003649 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003650 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 r.thumbnail = thumbnail;
3652 r.description = description;
3653 r.stopped = true;
3654 r.state = ActivityState.STOPPED;
3655 if (!r.finishing) {
3656 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003657 r.stack.destroyActivityLocked(r, true);
3658 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 }
3660 }
3661 }
3662 }
3663
3664 if (r != null) {
3665 sendPendingThumbnail(r, null, null, null, false);
3666 }
3667
3668 trimApplications();
3669
3670 Binder.restoreCallingIdentity(origId);
3671 }
3672
3673 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003674 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003675 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 }
3677
3678 public String getCallingPackage(IBinder token) {
3679 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003680 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003681 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 }
3683 }
3684
3685 public ComponentName getCallingActivity(IBinder token) {
3686 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003687 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 return r != null ? r.intent.getComponent() : null;
3689 }
3690 }
3691
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003692 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003693 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003695 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003696 if (r != null) {
3697 return r.resultTo;
3698 }
3699 }
3700 return null;
3701 }
3702
3703 public ComponentName getActivityClassForToken(IBinder token) {
3704 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003705 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003707 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 return r.intent.getComponent();
3709 }
3710 return null;
3711 }
3712 }
3713
3714 public String getPackageForToken(IBinder token) {
3715 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003716 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003718 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003719 return r.packageName;
3720 }
3721 return null;
3722 }
3723 }
3724
3725 public IIntentSender getIntentSender(int type,
3726 String packageName, IBinder token, String resultWho,
3727 int requestCode, Intent intent, String resolvedType, int flags) {
3728 // Refuse possible leaked file descriptors
3729 if (intent != null && intent.hasFileDescriptors() == true) {
3730 throw new IllegalArgumentException("File descriptors passed in Intent");
3731 }
3732
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003733 if (type == INTENT_SENDER_BROADCAST) {
3734 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3735 throw new IllegalArgumentException(
3736 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3737 }
3738 }
3739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 synchronized(this) {
3741 int callingUid = Binder.getCallingUid();
3742 try {
3743 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3744 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003745 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003746 .getPackageUid(packageName);
3747 if (uid != Binder.getCallingUid()) {
3748 String msg = "Permission Denial: getIntentSender() from pid="
3749 + Binder.getCallingPid()
3750 + ", uid=" + Binder.getCallingUid()
3751 + ", (need uid=" + uid + ")"
3752 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003753 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 throw new SecurityException(msg);
3755 }
3756 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003757
3758 return getIntentSenderLocked(type, packageName, callingUid,
3759 token, resultWho, requestCode, intent, resolvedType, flags);
3760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003761 } catch (RemoteException e) {
3762 throw new SecurityException(e);
3763 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003764 }
3765 }
3766
3767 IIntentSender getIntentSenderLocked(int type,
3768 String packageName, int callingUid, IBinder token, String resultWho,
3769 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003770 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003771 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003772 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003773 if (index < 0) {
3774 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003776 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003777 if (activity.finishing) {
3778 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003780 }
3781
3782 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3783 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3784 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3785 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3786 |PendingIntent.FLAG_UPDATE_CURRENT);
3787
3788 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3789 type, packageName, activity, resultWho,
3790 requestCode, intent, resolvedType, flags);
3791 WeakReference<PendingIntentRecord> ref;
3792 ref = mIntentSenderRecords.get(key);
3793 PendingIntentRecord rec = ref != null ? ref.get() : null;
3794 if (rec != null) {
3795 if (!cancelCurrent) {
3796 if (updateCurrent) {
3797 rec.key.requestIntent.replaceExtras(intent);
3798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 return rec;
3800 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003801 rec.canceled = true;
3802 mIntentSenderRecords.remove(key);
3803 }
3804 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 return rec;
3806 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003807 rec = new PendingIntentRecord(this, key, callingUid);
3808 mIntentSenderRecords.put(key, rec.ref);
3809 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3810 if (activity.pendingResults == null) {
3811 activity.pendingResults
3812 = new HashSet<WeakReference<PendingIntentRecord>>();
3813 }
3814 activity.pendingResults.add(rec.ref);
3815 }
3816 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 }
3818
3819 public void cancelIntentSender(IIntentSender sender) {
3820 if (!(sender instanceof PendingIntentRecord)) {
3821 return;
3822 }
3823 synchronized(this) {
3824 PendingIntentRecord rec = (PendingIntentRecord)sender;
3825 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003826 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 .getPackageUid(rec.key.packageName);
3828 if (uid != Binder.getCallingUid()) {
3829 String msg = "Permission Denial: cancelIntentSender() from pid="
3830 + Binder.getCallingPid()
3831 + ", uid=" + Binder.getCallingUid()
3832 + " is not allowed to cancel packges "
3833 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003834 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 throw new SecurityException(msg);
3836 }
3837 } catch (RemoteException e) {
3838 throw new SecurityException(e);
3839 }
3840 cancelIntentSenderLocked(rec, true);
3841 }
3842 }
3843
3844 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3845 rec.canceled = true;
3846 mIntentSenderRecords.remove(rec.key);
3847 if (cleanActivity && rec.key.activity != null) {
3848 rec.key.activity.pendingResults.remove(rec.ref);
3849 }
3850 }
3851
3852 public String getPackageForIntentSender(IIntentSender pendingResult) {
3853 if (!(pendingResult instanceof PendingIntentRecord)) {
3854 return null;
3855 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003856 try {
3857 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3858 return res.key.packageName;
3859 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 }
3861 return null;
3862 }
3863
3864 public void setProcessLimit(int max) {
3865 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3866 "setProcessLimit()");
3867 mProcessLimit = max;
3868 }
3869
3870 public int getProcessLimit() {
3871 return mProcessLimit;
3872 }
3873
3874 void foregroundTokenDied(ForegroundToken token) {
3875 synchronized (ActivityManagerService.this) {
3876 synchronized (mPidsSelfLocked) {
3877 ForegroundToken cur
3878 = mForegroundProcesses.get(token.pid);
3879 if (cur != token) {
3880 return;
3881 }
3882 mForegroundProcesses.remove(token.pid);
3883 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3884 if (pr == null) {
3885 return;
3886 }
3887 pr.forcingToForeground = null;
3888 pr.foregroundServices = false;
3889 }
3890 updateOomAdjLocked();
3891 }
3892 }
3893
3894 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3895 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3896 "setProcessForeground()");
3897 synchronized(this) {
3898 boolean changed = false;
3899
3900 synchronized (mPidsSelfLocked) {
3901 ProcessRecord pr = mPidsSelfLocked.get(pid);
3902 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003903 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003904 return;
3905 }
3906 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3907 if (oldToken != null) {
3908 oldToken.token.unlinkToDeath(oldToken, 0);
3909 mForegroundProcesses.remove(pid);
3910 pr.forcingToForeground = null;
3911 changed = true;
3912 }
3913 if (isForeground && token != null) {
3914 ForegroundToken newToken = new ForegroundToken() {
3915 public void binderDied() {
3916 foregroundTokenDied(this);
3917 }
3918 };
3919 newToken.pid = pid;
3920 newToken.token = token;
3921 try {
3922 token.linkToDeath(newToken, 0);
3923 mForegroundProcesses.put(pid, newToken);
3924 pr.forcingToForeground = token;
3925 changed = true;
3926 } catch (RemoteException e) {
3927 // If the process died while doing this, we will later
3928 // do the cleanup with the process death link.
3929 }
3930 }
3931 }
3932
3933 if (changed) {
3934 updateOomAdjLocked();
3935 }
3936 }
3937 }
3938
3939 // =========================================================
3940 // PERMISSIONS
3941 // =========================================================
3942
3943 static class PermissionController extends IPermissionController.Stub {
3944 ActivityManagerService mActivityManagerService;
3945 PermissionController(ActivityManagerService activityManagerService) {
3946 mActivityManagerService = activityManagerService;
3947 }
3948
3949 public boolean checkPermission(String permission, int pid, int uid) {
3950 return mActivityManagerService.checkPermission(permission, pid,
3951 uid) == PackageManager.PERMISSION_GRANTED;
3952 }
3953 }
3954
3955 /**
3956 * This can be called with or without the global lock held.
3957 */
3958 int checkComponentPermission(String permission, int pid, int uid,
3959 int reqUid) {
3960 // We might be performing an operation on behalf of an indirect binder
3961 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
3962 // client identity accordingly before proceeding.
3963 Identity tlsIdentity = sCallerIdentity.get();
3964 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003965 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
3967 uid = tlsIdentity.uid;
3968 pid = tlsIdentity.pid;
3969 }
3970
3971 // Root, system server and our own process get to do everything.
3972 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
3973 !Process.supportsProcesses()) {
3974 return PackageManager.PERMISSION_GRANTED;
3975 }
3976 // If the target requires a specific UID, always fail for others.
3977 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003978 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 return PackageManager.PERMISSION_DENIED;
3980 }
3981 if (permission == null) {
3982 return PackageManager.PERMISSION_GRANTED;
3983 }
3984 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003985 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003986 .checkUidPermission(permission, uid);
3987 } catch (RemoteException e) {
3988 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003989 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003990 }
3991 return PackageManager.PERMISSION_DENIED;
3992 }
3993
3994 /**
3995 * As the only public entry point for permissions checking, this method
3996 * can enforce the semantic that requesting a check on a null global
3997 * permission is automatically denied. (Internally a null permission
3998 * string is used when calling {@link #checkComponentPermission} in cases
3999 * when only uid-based security is needed.)
4000 *
4001 * This can be called with or without the global lock held.
4002 */
4003 public int checkPermission(String permission, int pid, int uid) {
4004 if (permission == null) {
4005 return PackageManager.PERMISSION_DENIED;
4006 }
4007 return checkComponentPermission(permission, pid, uid, -1);
4008 }
4009
4010 /**
4011 * Binder IPC calls go through the public entry point.
4012 * This can be called with or without the global lock held.
4013 */
4014 int checkCallingPermission(String permission) {
4015 return checkPermission(permission,
4016 Binder.getCallingPid(),
4017 Binder.getCallingUid());
4018 }
4019
4020 /**
4021 * This can be called with or without the global lock held.
4022 */
4023 void enforceCallingPermission(String permission, String func) {
4024 if (checkCallingPermission(permission)
4025 == PackageManager.PERMISSION_GRANTED) {
4026 return;
4027 }
4028
4029 String msg = "Permission Denial: " + func + " from pid="
4030 + Binder.getCallingPid()
4031 + ", uid=" + Binder.getCallingUid()
4032 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004033 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 throw new SecurityException(msg);
4035 }
4036
4037 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4038 ProviderInfo pi, int uid, int modeFlags) {
4039 try {
4040 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4041 if ((pi.readPermission != null) &&
4042 (pm.checkUidPermission(pi.readPermission, uid)
4043 != PackageManager.PERMISSION_GRANTED)) {
4044 return false;
4045 }
4046 }
4047 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4048 if ((pi.writePermission != null) &&
4049 (pm.checkUidPermission(pi.writePermission, uid)
4050 != PackageManager.PERMISSION_GRANTED)) {
4051 return false;
4052 }
4053 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004054 if (!pi.exported && pi.applicationInfo.uid != uid) {
4055 return false;
4056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 return true;
4058 } catch (RemoteException e) {
4059 return false;
4060 }
4061 }
4062
4063 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4064 int modeFlags) {
4065 // Root gets to do everything.
4066 if (uid == 0 || !Process.supportsProcesses()) {
4067 return true;
4068 }
4069 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4070 if (perms == null) return false;
4071 UriPermission perm = perms.get(uri);
4072 if (perm == null) return false;
4073 return (modeFlags&perm.modeFlags) == modeFlags;
4074 }
4075
4076 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4077 // Another redirected-binder-call permissions check as in
4078 // {@link checkComponentPermission}.
4079 Identity tlsIdentity = sCallerIdentity.get();
4080 if (tlsIdentity != null) {
4081 uid = tlsIdentity.uid;
4082 pid = tlsIdentity.pid;
4083 }
4084
4085 // Our own process gets to do everything.
4086 if (pid == MY_PID) {
4087 return PackageManager.PERMISSION_GRANTED;
4088 }
4089 synchronized(this) {
4090 return checkUriPermissionLocked(uri, uid, modeFlags)
4091 ? PackageManager.PERMISSION_GRANTED
4092 : PackageManager.PERMISSION_DENIED;
4093 }
4094 }
4095
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004096 void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004097 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4099 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4100 if (modeFlags == 0) {
4101 return;
4102 }
4103
Joe Onorato8a9b2202010-02-26 18:56:32 -08004104 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004105 "Requested grant " + targetPkg + " permission to " + uri);
4106
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004107 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108
4109 // If this is not a content: uri, we can't do anything with it.
4110 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004111 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004112 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004113 return;
4114 }
4115
4116 String name = uri.getAuthority();
4117 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004118 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004119 if (cpr != null) {
4120 pi = cpr.info;
4121 } else {
4122 try {
4123 pi = pm.resolveContentProvider(name,
4124 PackageManager.GET_URI_PERMISSION_PATTERNS);
4125 } catch (RemoteException ex) {
4126 }
4127 }
4128 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004129 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 return;
4131 }
4132
4133 int targetUid;
4134 try {
4135 targetUid = pm.getPackageUid(targetPkg);
4136 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004137 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004138 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004139 return;
4140 }
4141 } catch (RemoteException ex) {
4142 return;
4143 }
4144
4145 // First... does the target actually need this permission?
4146 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4147 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004148 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004149 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 return;
4151 }
4152
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004153 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004154 if (!pi.grantUriPermissions) {
4155 throw new SecurityException("Provider " + pi.packageName
4156 + "/" + pi.name
4157 + " does not allow granting of Uri permissions (uri "
4158 + uri + ")");
4159 }
4160 if (pi.uriPermissionPatterns != null) {
4161 final int N = pi.uriPermissionPatterns.length;
4162 boolean allowed = false;
4163 for (int i=0; i<N; i++) {
4164 if (pi.uriPermissionPatterns[i] != null
4165 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4166 allowed = true;
4167 break;
4168 }
4169 }
4170 if (!allowed) {
4171 throw new SecurityException("Provider " + pi.packageName
4172 + "/" + pi.name
4173 + " does not allow granting of permission to path of Uri "
4174 + uri);
4175 }
4176 }
4177
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004178 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 // this uri?
4180 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4181 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4182 throw new SecurityException("Uid " + callingUid
4183 + " does not have permission to uri " + uri);
4184 }
4185 }
4186
4187 // Okay! So here we are: the caller has the assumed permission
4188 // to the uri, and the target doesn't. Let's now give this to
4189 // the target.
4190
Joe Onorato8a9b2202010-02-26 18:56:32 -08004191 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004192 "Granting " + targetPkg + " permission to " + uri);
4193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 HashMap<Uri, UriPermission> targetUris
4195 = mGrantedUriPermissions.get(targetUid);
4196 if (targetUris == null) {
4197 targetUris = new HashMap<Uri, UriPermission>();
4198 mGrantedUriPermissions.put(targetUid, targetUris);
4199 }
4200
4201 UriPermission perm = targetUris.get(uri);
4202 if (perm == null) {
4203 perm = new UriPermission(targetUid, uri);
4204 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004207 perm.modeFlags |= modeFlags;
4208 if (activity == null) {
4209 perm.globalModeFlags |= modeFlags;
4210 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4211 perm.readActivities.add(activity);
4212 if (activity.readUriPermissions == null) {
4213 activity.readUriPermissions = new HashSet<UriPermission>();
4214 }
4215 activity.readUriPermissions.add(perm);
4216 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4217 perm.writeActivities.add(activity);
4218 if (activity.writeUriPermissions == null) {
4219 activity.writeUriPermissions = new HashSet<UriPermission>();
4220 }
4221 activity.writeUriPermissions.add(perm);
4222 }
4223 }
4224
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004225 void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004226 String targetPkg, Intent intent, ActivityRecord activity) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004227 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4228 "Grant URI perm to " + (intent != null ? intent.getData() : null)
4229 + " from " + intent + "; flags=0x"
4230 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 if (intent == null) {
4233 return;
4234 }
4235 Uri data = intent.getData();
4236 if (data == null) {
4237 return;
4238 }
4239 grantUriPermissionLocked(callingUid, targetPkg, data,
4240 intent.getFlags(), activity);
4241 }
4242
4243 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4244 Uri uri, int modeFlags) {
4245 synchronized(this) {
4246 final ProcessRecord r = getRecordForAppLocked(caller);
4247 if (r == null) {
4248 throw new SecurityException("Unable to find app for caller "
4249 + caller
4250 + " when granting permission to uri " + uri);
4251 }
4252 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004253 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 return;
4255 }
4256 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004257 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 return;
4259 }
4260
4261 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4262 null);
4263 }
4264 }
4265
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004266 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4268 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4269 HashMap<Uri, UriPermission> perms
4270 = mGrantedUriPermissions.get(perm.uid);
4271 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004272 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004273 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 perms.remove(perm.uri);
4275 if (perms.size() == 0) {
4276 mGrantedUriPermissions.remove(perm.uid);
4277 }
4278 }
4279 }
4280 }
4281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4283 int modeFlags) {
4284 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4285 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4286 if (modeFlags == 0) {
4287 return;
4288 }
4289
Joe Onorato8a9b2202010-02-26 18:56:32 -08004290 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004291 "Revoking all granted permissions to " + uri);
4292
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004293 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294
4295 final String authority = uri.getAuthority();
4296 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004297 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 if (cpr != null) {
4299 pi = cpr.info;
4300 } else {
4301 try {
4302 pi = pm.resolveContentProvider(authority,
4303 PackageManager.GET_URI_PERMISSION_PATTERNS);
4304 } catch (RemoteException ex) {
4305 }
4306 }
4307 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004308 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004309 return;
4310 }
4311
4312 // Does the caller have this permission on the URI?
4313 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4314 // Right now, if you are not the original owner of the permission,
4315 // you are not allowed to revoke it.
4316 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4317 throw new SecurityException("Uid " + callingUid
4318 + " does not have permission to uri " + uri);
4319 //}
4320 }
4321
4322 // Go through all of the permissions and remove any that match.
4323 final List<String> SEGMENTS = uri.getPathSegments();
4324 if (SEGMENTS != null) {
4325 final int NS = SEGMENTS.size();
4326 int N = mGrantedUriPermissions.size();
4327 for (int i=0; i<N; i++) {
4328 HashMap<Uri, UriPermission> perms
4329 = mGrantedUriPermissions.valueAt(i);
4330 Iterator<UriPermission> it = perms.values().iterator();
4331 toploop:
4332 while (it.hasNext()) {
4333 UriPermission perm = it.next();
4334 Uri targetUri = perm.uri;
4335 if (!authority.equals(targetUri.getAuthority())) {
4336 continue;
4337 }
4338 List<String> targetSegments = targetUri.getPathSegments();
4339 if (targetSegments == null) {
4340 continue;
4341 }
4342 if (targetSegments.size() < NS) {
4343 continue;
4344 }
4345 for (int j=0; j<NS; j++) {
4346 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4347 continue toploop;
4348 }
4349 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004350 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004351 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004352 perm.clearModes(modeFlags);
4353 if (perm.modeFlags == 0) {
4354 it.remove();
4355 }
4356 }
4357 if (perms.size() == 0) {
4358 mGrantedUriPermissions.remove(
4359 mGrantedUriPermissions.keyAt(i));
4360 N--;
4361 i--;
4362 }
4363 }
4364 }
4365 }
4366
4367 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4368 int modeFlags) {
4369 synchronized(this) {
4370 final ProcessRecord r = getRecordForAppLocked(caller);
4371 if (r == null) {
4372 throw new SecurityException("Unable to find app for caller "
4373 + caller
4374 + " when revoking permission to uri " + uri);
4375 }
4376 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004377 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004378 return;
4379 }
4380
4381 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4382 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4383 if (modeFlags == 0) {
4384 return;
4385 }
4386
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004387 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004388
4389 final String authority = uri.getAuthority();
4390 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004391 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004392 if (cpr != null) {
4393 pi = cpr.info;
4394 } else {
4395 try {
4396 pi = pm.resolveContentProvider(authority,
4397 PackageManager.GET_URI_PERMISSION_PATTERNS);
4398 } catch (RemoteException ex) {
4399 }
4400 }
4401 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004402 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 return;
4404 }
4405
4406 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4407 }
4408 }
4409
4410 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4411 synchronized (this) {
4412 ProcessRecord app =
4413 who != null ? getRecordForAppLocked(who) : null;
4414 if (app == null) return;
4415
4416 Message msg = Message.obtain();
4417 msg.what = WAIT_FOR_DEBUGGER_MSG;
4418 msg.obj = app;
4419 msg.arg1 = waiting ? 1 : 0;
4420 mHandler.sendMessage(msg);
4421 }
4422 }
4423
4424 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4425 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004426 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004427 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004428 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 }
4430
4431 // =========================================================
4432 // TASK MANAGEMENT
4433 // =========================================================
4434
4435 public List getTasks(int maxNum, int flags,
4436 IThumbnailReceiver receiver) {
4437 ArrayList list = new ArrayList();
4438
4439 PendingThumbnailsRecord pending = null;
4440 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004441 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442
4443 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004444 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4446 + ", receiver=" + receiver);
4447
4448 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4449 != PackageManager.PERMISSION_GRANTED) {
4450 if (receiver != null) {
4451 // If the caller wants to wait for pending thumbnails,
4452 // it ain't gonna get them.
4453 try {
4454 receiver.finished();
4455 } catch (RemoteException ex) {
4456 }
4457 }
4458 String msg = "Permission Denial: getTasks() from pid="
4459 + Binder.getCallingPid()
4460 + ", uid=" + Binder.getCallingUid()
4461 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004462 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 throw new SecurityException(msg);
4464 }
4465
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004466 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004467 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004468 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004469 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004470 CharSequence topDescription = null;
4471 TaskRecord curTask = null;
4472 int numActivities = 0;
4473 int numRunning = 0;
4474 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004475 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004477 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478
4479 // Initialize state for next task if needed.
4480 if (top == null ||
4481 (top.state == ActivityState.INITIALIZING
4482 && top.task == r.task)) {
4483 top = r;
4484 topDescription = r.description;
4485 curTask = r.task;
4486 numActivities = numRunning = 0;
4487 }
4488
4489 // Add 'r' into the current task.
4490 numActivities++;
4491 if (r.app != null && r.app.thread != null) {
4492 numRunning++;
4493 }
4494 if (topDescription == null) {
4495 topDescription = r.description;
4496 }
4497
Joe Onorato8a9b2202010-02-26 18:56:32 -08004498 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004499 TAG, r.intent.getComponent().flattenToShortString()
4500 + ": task=" + r.task);
4501
4502 // If the next one is a different task, generate a new
4503 // TaskInfo entry for what we have.
4504 if (next == null || next.task != curTask) {
4505 ActivityManager.RunningTaskInfo ci
4506 = new ActivityManager.RunningTaskInfo();
4507 ci.id = curTask.taskId;
4508 ci.baseActivity = r.intent.getComponent();
4509 ci.topActivity = top.intent.getComponent();
4510 ci.thumbnail = top.thumbnail;
4511 ci.description = topDescription;
4512 ci.numActivities = numActivities;
4513 ci.numRunning = numRunning;
4514 //System.out.println(
4515 // "#" + maxNum + ": " + " descr=" + ci.description);
4516 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004517 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518 TAG, "State=" + top.state + "Idle=" + top.idle
4519 + " app=" + top.app
4520 + " thr=" + (top.app != null ? top.app.thread : null));
4521 if (top.state == ActivityState.RESUMED
4522 || top.state == ActivityState.PAUSING) {
4523 if (top.idle && top.app != null
4524 && top.app.thread != null) {
4525 topRecord = top;
4526 topThumbnail = top.app.thread;
4527 } else {
4528 top.thumbnailNeeded = true;
4529 }
4530 }
4531 if (pending == null) {
4532 pending = new PendingThumbnailsRecord(receiver);
4533 }
4534 pending.pendingRecords.add(top);
4535 }
4536 list.add(ci);
4537 maxNum--;
4538 top = null;
4539 }
4540 }
4541
4542 if (pending != null) {
4543 mPendingThumbnails.add(pending);
4544 }
4545 }
4546
Joe Onorato8a9b2202010-02-26 18:56:32 -08004547 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004548
4549 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004550 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 try {
4552 topThumbnail.requestThumbnail(topRecord);
4553 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004554 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004555 sendPendingThumbnail(null, topRecord, null, null, true);
4556 }
4557 }
4558
4559 if (pending == null && receiver != null) {
4560 // In this case all thumbnails were available and the client
4561 // is being asked to be told when the remaining ones come in...
4562 // which is unusually, since the top-most currently running
4563 // activity should never have a canned thumbnail! Oh well.
4564 try {
4565 receiver.finished();
4566 } catch (RemoteException ex) {
4567 }
4568 }
4569
4570 return list;
4571 }
4572
4573 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4574 int flags) {
4575 synchronized (this) {
4576 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4577 "getRecentTasks()");
4578
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004579 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 final int N = mRecentTasks.size();
4582 ArrayList<ActivityManager.RecentTaskInfo> res
4583 = new ArrayList<ActivityManager.RecentTaskInfo>(
4584 maxNum < N ? maxNum : N);
4585 for (int i=0; i<N && maxNum > 0; i++) {
4586 TaskRecord tr = mRecentTasks.get(i);
4587 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4588 || (tr.intent == null)
4589 || ((tr.intent.getFlags()
4590 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4591 ActivityManager.RecentTaskInfo rti
4592 = new ActivityManager.RecentTaskInfo();
4593 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4594 rti.baseIntent = new Intent(
4595 tr.intent != null ? tr.intent : tr.affinityIntent);
4596 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004597
4598 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4599 // Check whether this activity is currently available.
4600 try {
4601 if (rti.origActivity != null) {
4602 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4603 continue;
4604 }
4605 } else if (rti.baseIntent != null) {
4606 if (pm.queryIntentActivities(rti.baseIntent,
4607 null, 0) == null) {
4608 continue;
4609 }
4610 }
4611 } catch (RemoteException e) {
4612 // Will never happen.
4613 }
4614 }
4615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004616 res.add(rti);
4617 maxNum--;
4618 }
4619 }
4620 return res;
4621 }
4622 }
4623
4624 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4625 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004626 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 TaskRecord jt = startTask;
4628
4629 // First look backwards
4630 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004631 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004632 if (r.task != jt) {
4633 jt = r.task;
4634 if (affinity.equals(jt.affinity)) {
4635 return j;
4636 }
4637 }
4638 }
4639
4640 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004641 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004642 jt = startTask;
4643 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004644 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 if (r.task != jt) {
4646 if (affinity.equals(jt.affinity)) {
4647 return j;
4648 }
4649 jt = r.task;
4650 }
4651 }
4652
4653 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004654 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 return N-1;
4656 }
4657
4658 return -1;
4659 }
4660
4661 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004662 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004663 */
4664 public void moveTaskToFront(int task) {
4665 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4666 "moveTaskToFront()");
4667
4668 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004669 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4670 Binder.getCallingUid(), "Task to front")) {
4671 return;
4672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 final long origId = Binder.clearCallingIdentity();
4674 try {
4675 int N = mRecentTasks.size();
4676 for (int i=0; i<N; i++) {
4677 TaskRecord tr = mRecentTasks.get(i);
4678 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004679 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004680 return;
4681 }
4682 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004683 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4684 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004685 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004686 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 return;
4688 }
4689 }
4690 } finally {
4691 Binder.restoreCallingIdentity(origId);
4692 }
4693 }
4694 }
4695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004696 public void moveTaskToBack(int task) {
4697 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4698 "moveTaskToBack()");
4699
4700 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004701 if (mMainStack.mResumedActivity != null
4702 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004703 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4704 Binder.getCallingUid(), "Task to back")) {
4705 return;
4706 }
4707 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004709 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 Binder.restoreCallingIdentity(origId);
4711 }
4712 }
4713
4714 /**
4715 * Moves an activity, and all of the other activities within the same task, to the bottom
4716 * of the history stack. The activity's order within the task is unchanged.
4717 *
4718 * @param token A reference to the activity we wish to move
4719 * @param nonRoot If false then this only works if the activity is the root
4720 * of a task; if true it will work for any activity in a task.
4721 * @return Returns true if the move completed, false if not.
4722 */
4723 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4724 synchronized(this) {
4725 final long origId = Binder.clearCallingIdentity();
4726 int taskId = getTaskForActivityLocked(token, !nonRoot);
4727 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004728 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729 }
4730 Binder.restoreCallingIdentity(origId);
4731 }
4732 return false;
4733 }
4734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735 public void moveTaskBackwards(int task) {
4736 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4737 "moveTaskBackwards()");
4738
4739 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004740 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4741 Binder.getCallingUid(), "Task backwards")) {
4742 return;
4743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 final long origId = Binder.clearCallingIdentity();
4745 moveTaskBackwardsLocked(task);
4746 Binder.restoreCallingIdentity(origId);
4747 }
4748 }
4749
4750 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004751 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 }
4753
4754 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4755 synchronized(this) {
4756 return getTaskForActivityLocked(token, onlyRoot);
4757 }
4758 }
4759
4760 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004761 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 TaskRecord lastTask = null;
4763 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004764 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 if (r == token) {
4766 if (!onlyRoot || lastTask != r.task) {
4767 return r.task.taskId;
4768 }
4769 return -1;
4770 }
4771 lastTask = r.task;
4772 }
4773
4774 return -1;
4775 }
4776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 public void finishOtherInstances(IBinder token, ComponentName className) {
4778 synchronized(this) {
4779 final long origId = Binder.clearCallingIdentity();
4780
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004781 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004782 TaskRecord lastTask = null;
4783 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004784 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004785 if (r.realActivity.equals(className)
4786 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004787 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 null, "others")) {
4789 i--;
4790 N--;
4791 }
4792 }
4793 lastTask = r.task;
4794 }
4795
4796 Binder.restoreCallingIdentity(origId);
4797 }
4798 }
4799
4800 // =========================================================
4801 // THUMBNAILS
4802 // =========================================================
4803
4804 public void reportThumbnail(IBinder token,
4805 Bitmap thumbnail, CharSequence description) {
4806 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4807 final long origId = Binder.clearCallingIdentity();
4808 sendPendingThumbnail(null, token, thumbnail, description, true);
4809 Binder.restoreCallingIdentity(origId);
4810 }
4811
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004812 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813 Bitmap thumbnail, CharSequence description, boolean always) {
4814 TaskRecord task = null;
4815 ArrayList receivers = null;
4816
4817 //System.out.println("Send pending thumbnail: " + r);
4818
4819 synchronized(this) {
4820 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004821 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 if (index < 0) {
4823 return;
4824 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004825 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 }
4827 if (thumbnail == null) {
4828 thumbnail = r.thumbnail;
4829 description = r.description;
4830 }
4831 if (thumbnail == null && !always) {
4832 // If there is no thumbnail, and this entry is not actually
4833 // going away, then abort for now and pick up the next
4834 // thumbnail we get.
4835 return;
4836 }
4837 task = r.task;
4838
4839 int N = mPendingThumbnails.size();
4840 int i=0;
4841 while (i<N) {
4842 PendingThumbnailsRecord pr =
4843 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4844 //System.out.println("Looking in " + pr.pendingRecords);
4845 if (pr.pendingRecords.remove(r)) {
4846 if (receivers == null) {
4847 receivers = new ArrayList();
4848 }
4849 receivers.add(pr);
4850 if (pr.pendingRecords.size() == 0) {
4851 pr.finished = true;
4852 mPendingThumbnails.remove(i);
4853 N--;
4854 continue;
4855 }
4856 }
4857 i++;
4858 }
4859 }
4860
4861 if (receivers != null) {
4862 final int N = receivers.size();
4863 for (int i=0; i<N; i++) {
4864 try {
4865 PendingThumbnailsRecord pr =
4866 (PendingThumbnailsRecord)receivers.get(i);
4867 pr.receiver.newThumbnail(
4868 task != null ? task.taskId : -1, thumbnail, description);
4869 if (pr.finished) {
4870 pr.receiver.finished();
4871 }
4872 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004873 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 }
4875 }
4876 }
4877 }
4878
4879 // =========================================================
4880 // CONTENT PROVIDERS
4881 // =========================================================
4882
4883 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4884 List providers = null;
4885 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004886 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004888 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004889 } catch (RemoteException ex) {
4890 }
4891 if (providers != null) {
4892 final int N = providers.size();
4893 for (int i=0; i<N; i++) {
4894 ProviderInfo cpi =
4895 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004896 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 if (cpr == null) {
4898 cpr = new ContentProviderRecord(cpi, app.info);
4899 mProvidersByClass.put(cpi.name, cpr);
4900 }
4901 app.pubProviders.put(cpi.name, cpr);
4902 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004903 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 }
4905 }
4906 return providers;
4907 }
4908
4909 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07004910 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004911 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
4912 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
4913 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
4914 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004915 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004916 return null;
4917 }
4918 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
4919 cpi.exported ? -1 : cpi.applicationInfo.uid)
4920 == PackageManager.PERMISSION_GRANTED) {
4921 return null;
4922 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004923
4924 PathPermission[] pps = cpi.pathPermissions;
4925 if (pps != null) {
4926 int i = pps.length;
4927 while (i > 0) {
4928 i--;
4929 PathPermission pp = pps[i];
4930 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
4931 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004932 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004933 return null;
4934 }
4935 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
4936 cpi.exported ? -1 : cpi.applicationInfo.uid)
4937 == PackageManager.PERMISSION_GRANTED) {
4938 return null;
4939 }
4940 }
4941 }
4942
Dianne Hackbornb424b632010-08-18 15:59:05 -07004943 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
4944 if (perms != null) {
4945 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
4946 if (uri.getKey().getAuthority().equals(cpi.authority)) {
4947 return null;
4948 }
4949 }
4950 }
4951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 String msg = "Permission Denial: opening provider " + cpi.name
4953 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
4954 + ", uid=" + callingUid + ") requires "
4955 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004956 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 return msg;
4958 }
4959
4960 private final ContentProviderHolder getContentProviderImpl(
4961 IApplicationThread caller, String name) {
4962 ContentProviderRecord cpr;
4963 ProviderInfo cpi = null;
4964
4965 synchronized(this) {
4966 ProcessRecord r = null;
4967 if (caller != null) {
4968 r = getRecordForAppLocked(caller);
4969 if (r == null) {
4970 throw new SecurityException(
4971 "Unable to find app for caller " + caller
4972 + " (pid=" + Binder.getCallingPid()
4973 + ") when getting content provider " + name);
4974 }
4975 }
4976
4977 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07004978 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 if (cpr != null) {
4980 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07004981 String msg;
4982 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
4983 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 }
4985
4986 if (r != null && cpr.canRunHere(r)) {
4987 // This provider has been published or is in the process
4988 // of being published... but it is also allowed to run
4989 // in the caller's process, so don't make a connection
4990 // and just let the caller instantiate its own instance.
4991 if (cpr.provider != null) {
4992 // don't give caller the provider object, it needs
4993 // to make its own.
4994 cpr = new ContentProviderRecord(cpr);
4995 }
4996 return cpr;
4997 }
4998
4999 final long origId = Binder.clearCallingIdentity();
5000
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005001 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 // return it right away.
5003 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005004 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005005 "Adding provider requested by "
5006 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005007 + cpr.info.processName);
5008 Integer cnt = r.conProviders.get(cpr);
5009 if (cnt == null) {
5010 r.conProviders.put(cpr, new Integer(1));
5011 } else {
5012 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005015 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5016 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005017 // make sure to count it as being accessed and thus
5018 // back up on the LRU list. This is good because
5019 // content providers are often expensive to start.
5020 updateLruProcessLocked(cpr.app, false, true);
5021 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005022 } else {
5023 cpr.externals++;
5024 }
5025
5026 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005027 updateOomAdjLocked(cpr.app);
5028 }
5029
5030 Binder.restoreCallingIdentity(origId);
5031
5032 } else {
5033 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005034 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005035 resolveContentProvider(name,
5036 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 } catch (RemoteException ex) {
5038 }
5039 if (cpi == null) {
5040 return null;
5041 }
5042
Dianne Hackbornb424b632010-08-18 15:59:05 -07005043 String msg;
5044 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5045 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 }
5047
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005048 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5049 && !cpi.processName.equals("system")) {
5050 // If this content provider does not run in the system
5051 // process, and the system is not yet ready to run other
5052 // processes, then fail fast instead of hanging.
5053 throw new IllegalArgumentException(
5054 "Attempt to launch content provider before system ready");
5055 }
5056
Dianne Hackborn860755f2010-06-03 18:47:52 -07005057 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 final boolean firstClass = cpr == null;
5059 if (firstClass) {
5060 try {
5061 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005062 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 getApplicationInfo(
5064 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005065 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005067 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005068 + cpi.name);
5069 return null;
5070 }
5071 cpr = new ContentProviderRecord(cpi, ai);
5072 } catch (RemoteException ex) {
5073 // pm is in same process, this will never happen.
5074 }
5075 }
5076
5077 if (r != null && cpr.canRunHere(r)) {
5078 // If this is a multiprocess provider, then just return its
5079 // info and allow the caller to instantiate it. Only do
5080 // this if the provider is the same user as the caller's
5081 // process, or can run as root (so can be in any process).
5082 return cpr;
5083 }
5084
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005085 if (DEBUG_PROVIDER) {
5086 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005087 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005088 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005089 }
5090
5091 // This is single process, and our app is now connecting to it.
5092 // See if we are already in the process of launching this
5093 // provider.
5094 final int N = mLaunchingProviders.size();
5095 int i;
5096 for (i=0; i<N; i++) {
5097 if (mLaunchingProviders.get(i) == cpr) {
5098 break;
5099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 }
5101
5102 // If the provider is not already being launched, then get it
5103 // started.
5104 if (i >= N) {
5105 final long origId = Binder.clearCallingIdentity();
5106 ProcessRecord proc = startProcessLocked(cpi.processName,
5107 cpr.appInfo, false, 0, "content provider",
5108 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005109 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005111 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 + cpi.applicationInfo.packageName + "/"
5113 + cpi.applicationInfo.uid + " for provider "
5114 + name + ": process is bad");
5115 return null;
5116 }
5117 cpr.launchingApp = proc;
5118 mLaunchingProviders.add(cpr);
5119 Binder.restoreCallingIdentity(origId);
5120 }
5121
5122 // Make sure the provider is published (the same provider class
5123 // may be published under multiple names).
5124 if (firstClass) {
5125 mProvidersByClass.put(cpi.name, cpr);
5126 }
5127 mProvidersByName.put(name, cpr);
5128
5129 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005130 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005131 "Adding provider requested by "
5132 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005133 + cpr.info.processName);
5134 Integer cnt = r.conProviders.get(cpr);
5135 if (cnt == null) {
5136 r.conProviders.put(cpr, new Integer(1));
5137 } else {
5138 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 cpr.clients.add(r);
5141 } else {
5142 cpr.externals++;
5143 }
5144 }
5145 }
5146
5147 // Wait for the provider to be published...
5148 synchronized (cpr) {
5149 while (cpr.provider == null) {
5150 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005151 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 + cpi.applicationInfo.packageName + "/"
5153 + cpi.applicationInfo.uid + " for provider "
5154 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005155 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005156 cpi.applicationInfo.packageName,
5157 cpi.applicationInfo.uid, name);
5158 return null;
5159 }
5160 try {
5161 cpr.wait();
5162 } catch (InterruptedException ex) {
5163 }
5164 }
5165 }
5166 return cpr;
5167 }
5168
5169 public final ContentProviderHolder getContentProvider(
5170 IApplicationThread caller, String name) {
5171 if (caller == null) {
5172 String msg = "null IApplicationThread when getting content provider "
5173 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005174 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 throw new SecurityException(msg);
5176 }
5177
5178 return getContentProviderImpl(caller, name);
5179 }
5180
5181 private ContentProviderHolder getContentProviderExternal(String name) {
5182 return getContentProviderImpl(null, name);
5183 }
5184
5185 /**
5186 * Drop a content provider from a ProcessRecord's bookkeeping
5187 * @param cpr
5188 */
5189 public void removeContentProvider(IApplicationThread caller, String name) {
5190 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005191 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005193 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005194 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005195 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005196 return;
5197 }
5198 final ProcessRecord r = getRecordForAppLocked(caller);
5199 if (r == null) {
5200 throw new SecurityException(
5201 "Unable to find app for caller " + caller +
5202 " when removing content provider " + name);
5203 }
5204 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005205 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005206 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005207 + r.info.processName + " from process "
5208 + localCpr.appInfo.processName);
5209 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005211 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005212 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005213 return;
5214 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005215 Integer cnt = r.conProviders.get(localCpr);
5216 if (cnt == null || cnt.intValue() <= 1) {
5217 localCpr.clients.remove(r);
5218 r.conProviders.remove(localCpr);
5219 } else {
5220 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005222 }
5223 updateOomAdjLocked();
5224 }
5225 }
5226
5227 private void removeContentProviderExternal(String name) {
5228 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005229 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005230 if(cpr == null) {
5231 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005232 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 return;
5234 }
5235
5236 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005237 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005238 localCpr.externals--;
5239 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005240 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005241 }
5242 updateOomAdjLocked();
5243 }
5244 }
5245
5246 public final void publishContentProviders(IApplicationThread caller,
5247 List<ContentProviderHolder> providers) {
5248 if (providers == null) {
5249 return;
5250 }
5251
5252 synchronized(this) {
5253 final ProcessRecord r = getRecordForAppLocked(caller);
5254 if (r == null) {
5255 throw new SecurityException(
5256 "Unable to find app for caller " + caller
5257 + " (pid=" + Binder.getCallingPid()
5258 + ") when publishing content providers");
5259 }
5260
5261 final long origId = Binder.clearCallingIdentity();
5262
5263 final int N = providers.size();
5264 for (int i=0; i<N; i++) {
5265 ContentProviderHolder src = providers.get(i);
5266 if (src == null || src.info == null || src.provider == null) {
5267 continue;
5268 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005269 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 if (dst != null) {
5271 mProvidersByClass.put(dst.info.name, dst);
5272 String names[] = dst.info.authority.split(";");
5273 for (int j = 0; j < names.length; j++) {
5274 mProvidersByName.put(names[j], dst);
5275 }
5276
5277 int NL = mLaunchingProviders.size();
5278 int j;
5279 for (j=0; j<NL; j++) {
5280 if (mLaunchingProviders.get(j) == dst) {
5281 mLaunchingProviders.remove(j);
5282 j--;
5283 NL--;
5284 }
5285 }
5286 synchronized (dst) {
5287 dst.provider = src.provider;
5288 dst.app = r;
5289 dst.notifyAll();
5290 }
5291 updateOomAdjLocked(r);
5292 }
5293 }
5294
5295 Binder.restoreCallingIdentity(origId);
5296 }
5297 }
5298
5299 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005300 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005301 synchronized (mSelf) {
5302 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5303 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005304 if (providers != null) {
5305 for (int i=providers.size()-1; i>=0; i--) {
5306 ProviderInfo pi = (ProviderInfo)providers.get(i);
5307 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5308 Slog.w(TAG, "Not installing system proc provider " + pi.name
5309 + ": not system .apk");
5310 providers.remove(i);
5311 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005312 }
5313 }
5314 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005315 if (providers != null) {
5316 mSystemThread.installSystemProviders(providers);
5317 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 }
5319
5320 // =========================================================
5321 // GLOBAL MANAGEMENT
5322 // =========================================================
5323
5324 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5325 ApplicationInfo info, String customProcess) {
5326 String proc = customProcess != null ? customProcess : info.processName;
5327 BatteryStatsImpl.Uid.Proc ps = null;
5328 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5329 synchronized (stats) {
5330 ps = stats.getProcessStatsLocked(info.uid, proc);
5331 }
5332 return new ProcessRecord(ps, thread, info, proc);
5333 }
5334
5335 final ProcessRecord addAppLocked(ApplicationInfo info) {
5336 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5337
5338 if (app == null) {
5339 app = newProcessRecordLocked(null, info, null);
5340 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005341 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 }
5343
5344 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5345 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5346 app.persistent = true;
5347 app.maxAdj = CORE_SERVER_ADJ;
5348 }
5349 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5350 mPersistentStartingProcesses.add(app);
5351 startProcessLocked(app, "added application", app.processName);
5352 }
5353
5354 return app;
5355 }
5356
5357 public void unhandledBack() {
5358 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5359 "unhandledBack()");
5360
5361 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005362 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005363 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 TAG, "Performing unhandledBack(): stack size = " + count);
5365 if (count > 1) {
5366 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005367 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5369 Binder.restoreCallingIdentity(origId);
5370 }
5371 }
5372 }
5373
5374 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5375 String name = uri.getAuthority();
5376 ContentProviderHolder cph = getContentProviderExternal(name);
5377 ParcelFileDescriptor pfd = null;
5378 if (cph != null) {
5379 // We record the binder invoker's uid in thread-local storage before
5380 // going to the content provider to open the file. Later, in the code
5381 // that handles all permissions checks, we look for this uid and use
5382 // that rather than the Activity Manager's own uid. The effect is that
5383 // we do the check against the caller's permissions even though it looks
5384 // to the content provider like the Activity Manager itself is making
5385 // the request.
5386 sCallerIdentity.set(new Identity(
5387 Binder.getCallingPid(), Binder.getCallingUid()));
5388 try {
5389 pfd = cph.provider.openFile(uri, "r");
5390 } catch (FileNotFoundException e) {
5391 // do nothing; pfd will be returned null
5392 } finally {
5393 // Ensure that whatever happens, we clean up the identity state
5394 sCallerIdentity.remove();
5395 }
5396
5397 // We've got the fd now, so we're done with the provider.
5398 removeContentProviderExternal(name);
5399 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005400 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 }
5402 return pfd;
5403 }
5404
5405 public void goingToSleep() {
5406 synchronized(this) {
5407 mSleeping = true;
5408 mWindowManager.setEventDispatching(false);
5409
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005410 if (mMainStack.mResumedActivity != null) {
5411 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005412 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005413 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005414 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005415
5416 // Initialize the wake times of all processes.
5417 checkExcessiveWakeLocksLocked(false);
5418 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5419 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5420 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 }
5422 }
5423
Dianne Hackborn55280a92009-05-07 15:53:46 -07005424 public boolean shutdown(int timeout) {
5425 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5426 != PackageManager.PERMISSION_GRANTED) {
5427 throw new SecurityException("Requires permission "
5428 + android.Manifest.permission.SHUTDOWN);
5429 }
5430
5431 boolean timedout = false;
5432
5433 synchronized(this) {
5434 mShuttingDown = true;
5435 mWindowManager.setEventDispatching(false);
5436
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005437 if (mMainStack.mResumedActivity != null) {
5438 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005439 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005440 while (mMainStack.mResumedActivity != null
5441 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005442 long delay = endTime - System.currentTimeMillis();
5443 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005444 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005445 timedout = true;
5446 break;
5447 }
5448 try {
5449 this.wait();
5450 } catch (InterruptedException e) {
5451 }
5452 }
5453 }
5454 }
5455
5456 mUsageStatsService.shutdown();
5457 mBatteryStatsService.shutdown();
5458
5459 return timedout;
5460 }
5461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 public void wakingUp() {
5463 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005464 if (mMainStack.mGoingToSleep.isHeld()) {
5465 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005466 }
5467 mWindowManager.setEventDispatching(true);
5468 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005469 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005470 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005471 }
5472 }
5473
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005474 public void stopAppSwitches() {
5475 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5476 != PackageManager.PERMISSION_GRANTED) {
5477 throw new SecurityException("Requires permission "
5478 + android.Manifest.permission.STOP_APP_SWITCHES);
5479 }
5480
5481 synchronized(this) {
5482 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5483 + APP_SWITCH_DELAY_TIME;
5484 mDidAppSwitch = false;
5485 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5486 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5487 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5488 }
5489 }
5490
5491 public void resumeAppSwitches() {
5492 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5493 != PackageManager.PERMISSION_GRANTED) {
5494 throw new SecurityException("Requires permission "
5495 + android.Manifest.permission.STOP_APP_SWITCHES);
5496 }
5497
5498 synchronized(this) {
5499 // Note that we don't execute any pending app switches... we will
5500 // let those wait until either the timeout, or the next start
5501 // activity request.
5502 mAppSwitchesAllowedTime = 0;
5503 }
5504 }
5505
5506 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5507 String name) {
5508 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5509 return true;
5510 }
5511
5512 final int perm = checkComponentPermission(
5513 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5514 callingUid, -1);
5515 if (perm == PackageManager.PERMISSION_GRANTED) {
5516 return true;
5517 }
5518
Joe Onorato8a9b2202010-02-26 18:56:32 -08005519 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005520 return false;
5521 }
5522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005523 public void setDebugApp(String packageName, boolean waitForDebugger,
5524 boolean persistent) {
5525 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5526 "setDebugApp()");
5527
5528 // Note that this is not really thread safe if there are multiple
5529 // callers into it at the same time, but that's not a situation we
5530 // care about.
5531 if (persistent) {
5532 final ContentResolver resolver = mContext.getContentResolver();
5533 Settings.System.putString(
5534 resolver, Settings.System.DEBUG_APP,
5535 packageName);
5536 Settings.System.putInt(
5537 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5538 waitForDebugger ? 1 : 0);
5539 }
5540
5541 synchronized (this) {
5542 if (!persistent) {
5543 mOrigDebugApp = mDebugApp;
5544 mOrigWaitForDebugger = mWaitForDebugger;
5545 }
5546 mDebugApp = packageName;
5547 mWaitForDebugger = waitForDebugger;
5548 mDebugTransient = !persistent;
5549 if (packageName != null) {
5550 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005551 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005552 Binder.restoreCallingIdentity(origId);
5553 }
5554 }
5555 }
5556
5557 public void setAlwaysFinish(boolean enabled) {
5558 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5559 "setAlwaysFinish()");
5560
5561 Settings.System.putInt(
5562 mContext.getContentResolver(),
5563 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5564
5565 synchronized (this) {
5566 mAlwaysFinishActivities = enabled;
5567 }
5568 }
5569
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005570 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005571 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005572 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005574 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005575 }
5576 }
5577
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005578 public boolean isUserAMonkey() {
5579 // For now the fact that there is a controller implies
5580 // we have a monkey.
5581 synchronized (this) {
5582 return mController != null;
5583 }
5584 }
5585
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005586 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005587 synchronized (this) {
5588 mWatchers.register(watcher);
5589 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005590 }
5591
5592 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005593 synchronized (this) {
5594 mWatchers.unregister(watcher);
5595 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005596 }
5597
Daniel Sandler69a48172010-06-23 16:29:36 -04005598 public void setImmersive(IBinder token, boolean immersive) {
5599 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005600 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005601 if (index < 0) {
5602 throw new IllegalArgumentException();
5603 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005604 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005605 r.immersive = immersive;
5606 }
5607 }
5608
5609 public boolean isImmersive(IBinder token) {
5610 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005611 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005612 if (index < 0) {
5613 throw new IllegalArgumentException();
5614 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005615 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005616 return r.immersive;
5617 }
5618 }
5619
5620 public boolean isTopActivityImmersive() {
5621 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005622 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005623 return (r != null) ? r.immersive : false;
5624 }
5625 }
5626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005627 public final void enterSafeMode() {
5628 synchronized(this) {
5629 // It only makes sense to do this before the system is ready
5630 // and started launching other packages.
5631 if (!mSystemReady) {
5632 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005633 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005634 } catch (RemoteException e) {
5635 }
5636
5637 View v = LayoutInflater.from(mContext).inflate(
5638 com.android.internal.R.layout.safe_mode, null);
5639 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5640 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5641 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5642 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5643 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5644 lp.format = v.getBackground().getOpacity();
5645 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5646 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5647 ((WindowManager)mContext.getSystemService(
5648 Context.WINDOW_SERVICE)).addView(v, lp);
5649 }
5650 }
5651 }
5652
5653 public void noteWakeupAlarm(IIntentSender sender) {
5654 if (!(sender instanceof PendingIntentRecord)) {
5655 return;
5656 }
5657 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5658 synchronized (stats) {
5659 if (mBatteryStatsService.isOnBattery()) {
5660 mBatteryStatsService.enforceCallingPermission();
5661 PendingIntentRecord rec = (PendingIntentRecord)sender;
5662 int MY_UID = Binder.getCallingUid();
5663 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5664 BatteryStatsImpl.Uid.Pkg pkg =
5665 stats.getPackageStatsLocked(uid, rec.key.packageName);
5666 pkg.incWakeupsLocked();
5667 }
5668 }
5669 }
5670
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005671 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005673 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005675 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 // XXX Note: don't acquire main activity lock here, because the window
5677 // manager calls in with its locks held.
5678
5679 boolean killed = false;
5680 synchronized (mPidsSelfLocked) {
5681 int[] types = new int[pids.length];
5682 int worstType = 0;
5683 for (int i=0; i<pids.length; i++) {
5684 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5685 if (proc != null) {
5686 int type = proc.setAdj;
5687 types[i] = type;
5688 if (type > worstType) {
5689 worstType = type;
5690 }
5691 }
5692 }
5693
5694 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5695 // then constrain it so we will kill all hidden procs.
5696 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5697 worstType = HIDDEN_APP_MIN_ADJ;
5698 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005699 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 for (int i=0; i<pids.length; i++) {
5701 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5702 if (proc == null) {
5703 continue;
5704 }
5705 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005706 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005707 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005708 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5709 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005710 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005711 proc.killedBackground = true;
5712 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005713 }
5714 }
5715 }
5716 return killed;
5717 }
5718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 public final void startRunning(String pkg, String cls, String action,
5720 String data) {
5721 synchronized(this) {
5722 if (mStartRunning) {
5723 return;
5724 }
5725 mStartRunning = true;
5726 mTopComponent = pkg != null && cls != null
5727 ? new ComponentName(pkg, cls) : null;
5728 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5729 mTopData = data;
5730 if (!mSystemReady) {
5731 return;
5732 }
5733 }
5734
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005735 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005736 }
5737
5738 private void retrieveSettings() {
5739 final ContentResolver resolver = mContext.getContentResolver();
5740 String debugApp = Settings.System.getString(
5741 resolver, Settings.System.DEBUG_APP);
5742 boolean waitForDebugger = Settings.System.getInt(
5743 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5744 boolean alwaysFinishActivities = Settings.System.getInt(
5745 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5746
5747 Configuration configuration = new Configuration();
5748 Settings.System.getConfiguration(resolver, configuration);
5749
5750 synchronized (this) {
5751 mDebugApp = mOrigDebugApp = debugApp;
5752 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5753 mAlwaysFinishActivities = alwaysFinishActivities;
5754 // This happens before any activities are started, so we can
5755 // change mConfiguration in-place.
5756 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005757 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005758 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005759 }
5760 }
5761
5762 public boolean testIsSystemReady() {
5763 // no need to synchronize(this) just to read & return the value
5764 return mSystemReady;
5765 }
5766
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005767 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005768 // In the simulator, startRunning will never have been called, which
5769 // normally sets a few crucial variables. Do it here instead.
5770 if (!Process.supportsProcesses()) {
5771 mStartRunning = true;
5772 mTopAction = Intent.ACTION_MAIN;
5773 }
5774
5775 synchronized(this) {
5776 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005777 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005778 return;
5779 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005780
5781 // Check to see if there are any update receivers to run.
5782 if (!mDidUpdate) {
5783 if (mWaitingUpdate) {
5784 return;
5785 }
5786 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5787 List<ResolveInfo> ris = null;
5788 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005789 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005790 intent, null, 0);
5791 } catch (RemoteException e) {
5792 }
5793 if (ris != null) {
5794 for (int i=ris.size()-1; i>=0; i--) {
5795 if ((ris.get(i).activityInfo.applicationInfo.flags
5796 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5797 ris.remove(i);
5798 }
5799 }
5800 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5801 for (int i=0; i<ris.size(); i++) {
5802 ActivityInfo ai = ris.get(i).activityInfo;
5803 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5804 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005805 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005806 finisher = new IIntentReceiver.Stub() {
5807 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005808 String data, Bundle extras, boolean ordered,
5809 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005810 throws RemoteException {
5811 synchronized (ActivityManagerService.this) {
5812 mDidUpdate = true;
5813 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005814 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005815 }
5816 };
5817 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005818 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005819 broadcastIntentLocked(null, null, intent, null, finisher,
5820 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005821 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005822 mWaitingUpdate = true;
5823 }
5824 }
5825 }
5826 if (mWaitingUpdate) {
5827 return;
5828 }
5829 mDidUpdate = true;
5830 }
5831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 mSystemReady = true;
5833 if (!mStartRunning) {
5834 return;
5835 }
5836 }
5837
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005838 ArrayList<ProcessRecord> procsToKill = null;
5839 synchronized(mPidsSelfLocked) {
5840 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5841 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5842 if (!isAllowedWhileBooting(proc.info)){
5843 if (procsToKill == null) {
5844 procsToKill = new ArrayList<ProcessRecord>();
5845 }
5846 procsToKill.add(proc);
5847 }
5848 }
5849 }
5850
5851 if (procsToKill != null) {
5852 synchronized(this) {
5853 for (int i=procsToKill.size()-1; i>=0; i--) {
5854 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005855 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005856 removeProcessLocked(proc, true);
5857 }
5858 }
5859 }
5860
Joe Onorato8a9b2202010-02-26 18:56:32 -08005861 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005862 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 SystemClock.uptimeMillis());
5864
5865 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005866 // Make sure we have no pre-ready processes sitting around.
5867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5869 ResolveInfo ri = mContext.getPackageManager()
5870 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005871 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005872 CharSequence errorMsg = null;
5873 if (ri != null) {
5874 ActivityInfo ai = ri.activityInfo;
5875 ApplicationInfo app = ai.applicationInfo;
5876 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5877 mTopAction = Intent.ACTION_FACTORY_TEST;
5878 mTopData = null;
5879 mTopComponent = new ComponentName(app.packageName,
5880 ai.name);
5881 } else {
5882 errorMsg = mContext.getResources().getText(
5883 com.android.internal.R.string.factorytest_not_system);
5884 }
5885 } else {
5886 errorMsg = mContext.getResources().getText(
5887 com.android.internal.R.string.factorytest_no_action);
5888 }
5889 if (errorMsg != null) {
5890 mTopAction = null;
5891 mTopData = null;
5892 mTopComponent = null;
5893 Message msg = Message.obtain();
5894 msg.what = SHOW_FACTORY_ERROR_MSG;
5895 msg.getData().putCharSequence("msg", errorMsg);
5896 mHandler.sendMessage(msg);
5897 }
5898 }
5899 }
5900
5901 retrieveSettings();
5902
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005903 if (goingCallback != null) goingCallback.run();
5904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 synchronized (this) {
5906 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5907 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005908 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005909 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005910 if (apps != null) {
5911 int N = apps.size();
5912 int i;
5913 for (i=0; i<N; i++) {
5914 ApplicationInfo info
5915 = (ApplicationInfo)apps.get(i);
5916 if (info != null &&
5917 !info.packageName.equals("android")) {
5918 addAppLocked(info);
5919 }
5920 }
5921 }
5922 } catch (RemoteException ex) {
5923 // pm is in same process, this will never happen.
5924 }
5925 }
5926
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005927 // Start up initial activity.
5928 mBooting = true;
5929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005931 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 Message msg = Message.obtain();
5933 msg.what = SHOW_UID_ERROR_MSG;
5934 mHandler.sendMessage(msg);
5935 }
5936 } catch (RemoteException e) {
5937 }
5938
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005939 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 }
5941 }
5942
Dan Egnorb7f03672009-12-09 16:22:32 -08005943 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005944 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005945 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005946 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005947 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005948 startAppProblemLocked(app);
5949 app.stopFreezingAllLocked();
5950 return handleAppCrashLocked(app);
5951 }
5952
Dan Egnorb7f03672009-12-09 16:22:32 -08005953 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005954 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005956 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005957 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
5958 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005959 startAppProblemLocked(app);
5960 app.stopFreezingAllLocked();
5961 }
5962
5963 /**
5964 * Generate a process error record, suitable for attachment to a ProcessRecord.
5965 *
5966 * @param app The ProcessRecord in which the error occurred.
5967 * @param condition Crashing, Application Not Responding, etc. Values are defined in
5968 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08005969 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 * @param shortMsg Short message describing the crash.
5971 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08005972 * @param stackTrace Full crash stack trace, may be null.
5973 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005974 * @return Returns a fully-formed AppErrorStateInfo record.
5975 */
5976 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005977 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08005979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005980 report.condition = condition;
5981 report.processName = app.processName;
5982 report.pid = app.pid;
5983 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08005984 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005985 report.shortMsg = shortMsg;
5986 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08005987 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005988
5989 return report;
5990 }
5991
Dan Egnor42471dd2010-01-07 17:25:22 -08005992 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005993 synchronized (this) {
5994 app.crashing = false;
5995 app.crashingReport = null;
5996 app.notResponding = false;
5997 app.notRespondingReport = null;
5998 if (app.anrDialog == fromDialog) {
5999 app.anrDialog = null;
6000 }
6001 if (app.waitDialog == fromDialog) {
6002 app.waitDialog = null;
6003 }
6004 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006005 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006006 Slog.i(ActivityManagerService.TAG, "Killing "
6007 + app.processName + " (pid=" + app.pid + "): user's request");
6008 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6009 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006010 Process.killProcess(app.pid);
6011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 }
6013 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006014
Dan Egnorb7f03672009-12-09 16:22:32 -08006015 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006016 long now = SystemClock.uptimeMillis();
6017
6018 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6019 app.info.uid);
6020 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6021 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006022 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006023 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006024 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 app.info.processName, app.info.uid);
6026 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006027 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6028 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006029 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006030 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006031 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006032 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 }
6034 }
6035 if (!app.persistent) {
6036 // We don't want to start this process again until the user
6037 // explicitly does so... but for persistent process, we really
6038 // need to keep it running. If a persistent process is actually
6039 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006040 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 app.info.processName);
6042 mBadProcesses.put(app.info.processName, app.info.uid, now);
6043 app.bad = true;
6044 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6045 app.removed = true;
6046 removeProcessLocked(app, false);
6047 return false;
6048 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006049 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006050 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006051 if (r.app == app) {
6052 // If the top running activity is from this crashing
6053 // process, then terminate it to avoid getting in a loop.
6054 Slog.w(TAG, " Force finishing activity "
6055 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006056 int index = mMainStack.indexOfTokenLocked(r);
6057 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006058 Activity.RESULT_CANCELED, null, "crashed");
6059 // Also terminate an activities below it that aren't yet
6060 // stopped, to avoid a situation where one will get
6061 // re-start our crashing activity once it gets resumed again.
6062 index--;
6063 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006064 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006065 if (r.state == ActivityState.RESUMED
6066 || r.state == ActivityState.PAUSING
6067 || r.state == ActivityState.PAUSED) {
6068 if (!r.isHomeActivity) {
6069 Slog.w(TAG, " Force finishing activity "
6070 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006071 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006072 Activity.RESULT_CANCELED, null, "crashed");
6073 }
6074 }
6075 }
6076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006077 }
6078
6079 // Bump up the crash count of any services currently running in the proc.
6080 if (app.services.size() != 0) {
6081 // Any services running in the application need to be placed
6082 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006083 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006085 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 sr.crashCount++;
6087 }
6088 }
6089
6090 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6091 return true;
6092 }
6093
6094 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006095 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6096 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006097 skipCurrentReceiverLocked(app);
6098 }
6099
6100 void skipCurrentReceiverLocked(ProcessRecord app) {
6101 boolean reschedule = false;
6102 BroadcastRecord r = app.curReceiver;
6103 if (r != null) {
6104 // The current broadcast is waiting for this app's receiver
6105 // to be finished. Looks like that's not going to happen, so
6106 // let the broadcast continue.
6107 logBroadcastReceiverDiscard(r);
6108 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6109 r.resultExtras, r.resultAbort, true);
6110 reschedule = true;
6111 }
6112 r = mPendingBroadcast;
6113 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006114 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 "skip & discard pending app " + r);
6116 logBroadcastReceiverDiscard(r);
6117 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6118 r.resultExtras, r.resultAbort, true);
6119 reschedule = true;
6120 }
6121 if (reschedule) {
6122 scheduleBroadcastsLocked();
6123 }
6124 }
6125
Dan Egnor60d87622009-12-16 16:32:58 -08006126 /**
6127 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6128 * The application process will exit immediately after this call returns.
6129 * @param app object of the crashing app, null for the system server
6130 * @param crashInfo describing the exception
6131 */
6132 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6133 ProcessRecord r = findAppProcess(app);
6134
6135 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6136 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006137 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006138 crashInfo.exceptionClassName,
6139 crashInfo.exceptionMessage,
6140 crashInfo.throwFileName,
6141 crashInfo.throwLineNumber);
6142
Dan Egnor42471dd2010-01-07 17:25:22 -08006143 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006144
6145 crashApplication(r, crashInfo);
6146 }
6147
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006148 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006149 IBinder app,
6150 int violationMask,
6151 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006152 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006153
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006154 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006155 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006156 boolean logIt = true;
6157 synchronized (mAlreadyLoggedViolatedStacks) {
6158 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6159 logIt = false;
6160 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006161 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006162 // the relative pain numbers, without logging all
6163 // the stack traces repeatedly. We'd want to do
6164 // likewise in the client code, which also does
6165 // dup suppression, before the Binder call.
6166 } else {
6167 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6168 mAlreadyLoggedViolatedStacks.clear();
6169 }
6170 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6171 }
6172 }
6173 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006174 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006175 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006176 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006177
6178 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6179 AppErrorResult result = new AppErrorResult();
6180 synchronized (this) {
6181 final long origId = Binder.clearCallingIdentity();
6182
6183 Message msg = Message.obtain();
6184 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6185 HashMap<String, Object> data = new HashMap<String, Object>();
6186 data.put("result", result);
6187 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006188 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006189 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006190 msg.obj = data;
6191 mHandler.sendMessage(msg);
6192
6193 Binder.restoreCallingIdentity(origId);
6194 }
6195 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006196 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006197 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006198 }
6199
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006200 // Depending on the policy in effect, there could be a bunch of
6201 // these in quick succession so we try to batch these together to
6202 // minimize disk writes, number of dropbox entries, and maximize
6203 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006204 private void logStrictModeViolationToDropBox(
6205 ProcessRecord process,
6206 StrictMode.ViolationInfo info) {
6207 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006208 return;
6209 }
6210 final boolean isSystemApp = process == null ||
6211 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6212 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6213 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6214 final DropBoxManager dbox = (DropBoxManager)
6215 mContext.getSystemService(Context.DROPBOX_SERVICE);
6216
6217 // Exit early if the dropbox isn't configured to accept this report type.
6218 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6219
6220 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006221 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006222 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6223 synchronized (sb) {
6224 bufferWasEmpty = sb.length() == 0;
6225 appendDropBoxProcessHeaders(process, sb);
6226 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6227 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006228 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6229 if (info.violationNumThisLoop != 0) {
6230 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6231 }
6232 if (info != null && info.durationMillis != -1) {
6233 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006234 }
6235 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006236 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6237 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006238 }
6239 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006240
6241 // Only buffer up to ~64k. Various logging bits truncate
6242 // things at 128k.
6243 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006244 }
6245
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006246 // Flush immediately if the buffer's grown too large, or this
6247 // is a non-system app. Non-system apps are isolated with a
6248 // different tag & policy and not batched.
6249 //
6250 // Batching is useful during internal testing with
6251 // StrictMode settings turned up high. Without batching,
6252 // thousands of separate files could be created on boot.
6253 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006254 new Thread("Error dump: " + dropboxTag) {
6255 @Override
6256 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006257 String report;
6258 synchronized (sb) {
6259 report = sb.toString();
6260 sb.delete(0, sb.length());
6261 sb.trimToSize();
6262 }
6263 if (report.length() != 0) {
6264 dbox.addText(dropboxTag, report);
6265 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006266 }
6267 }.start();
6268 return;
6269 }
6270
6271 // System app batching:
6272 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006273 // An existing dropbox-writing thread is outstanding, so
6274 // we don't need to start it up. The existing thread will
6275 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006276 return;
6277 }
6278
6279 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6280 // (After this point, we shouldn't access AMS internal data structures.)
6281 new Thread("Error dump: " + dropboxTag) {
6282 @Override
6283 public void run() {
6284 // 5 second sleep to let stacks arrive and be batched together
6285 try {
6286 Thread.sleep(5000); // 5 seconds
6287 } catch (InterruptedException e) {}
6288
6289 String errorReport;
6290 synchronized (mStrictModeBuffer) {
6291 errorReport = mStrictModeBuffer.toString();
6292 if (errorReport.length() == 0) {
6293 return;
6294 }
6295 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6296 mStrictModeBuffer.trimToSize();
6297 }
6298 dbox.addText(dropboxTag, errorReport);
6299 }
6300 }.start();
6301 }
6302
Dan Egnor60d87622009-12-16 16:32:58 -08006303 /**
6304 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6305 * @param app object of the crashing app, null for the system server
6306 * @param tag reported by the caller
6307 * @param crashInfo describing the context of the error
6308 * @return true if the process should exit immediately (WTF is fatal)
6309 */
6310 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006311 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006312 ProcessRecord r = findAppProcess(app);
6313
6314 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6315 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006316 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006317 tag, crashInfo.exceptionMessage);
6318
Dan Egnor42471dd2010-01-07 17:25:22 -08006319 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006320
Doug Zongker43866e02010-01-07 12:09:54 -08006321 if (Settings.Secure.getInt(mContext.getContentResolver(),
6322 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006323 crashApplication(r, crashInfo);
6324 return true;
6325 } else {
6326 return false;
6327 }
6328 }
6329
6330 /**
6331 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6332 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6333 */
6334 private ProcessRecord findAppProcess(IBinder app) {
6335 if (app == null) {
6336 return null;
6337 }
6338
6339 synchronized (this) {
6340 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6341 final int NA = apps.size();
6342 for (int ia=0; ia<NA; ia++) {
6343 ProcessRecord p = apps.valueAt(ia);
6344 if (p.thread != null && p.thread.asBinder() == app) {
6345 return p;
6346 }
6347 }
6348 }
6349
Joe Onorato8a9b2202010-02-26 18:56:32 -08006350 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006351 return null;
6352 }
6353 }
6354
6355 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006356 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6357 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006358 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006359 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006360 if (process == null || process.pid == MY_PID) {
6361 sb.append("Process: system_server\n");
6362 } else {
6363 sb.append("Process: ").append(process.processName).append("\n");
6364 }
6365 if (process != null) {
6366 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006367 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006368 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6369 for (String pkg : process.pkgList) {
6370 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006371 try {
Dan Egnora455d192010-03-12 08:52:28 -08006372 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6373 if (pi != null) {
6374 sb.append(" v").append(pi.versionCode);
6375 if (pi.versionName != null) {
6376 sb.append(" (").append(pi.versionName).append(")");
6377 }
6378 }
6379 } catch (RemoteException e) {
6380 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006381 }
Dan Egnora455d192010-03-12 08:52:28 -08006382 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006383 }
Dan Egnora455d192010-03-12 08:52:28 -08006384 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006385 }
6386
6387 private static String processClass(ProcessRecord process) {
6388 if (process == null || process.pid == MY_PID) {
6389 return "system_server";
6390 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6391 return "system_app";
6392 } else {
6393 return "data_app";
6394 }
6395 }
6396
6397 /**
6398 * Write a description of an error (crash, WTF, ANR) to the drop box.
6399 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6400 * @param process which caused the error, null means the system server
6401 * @param activity which triggered the error, null if unknown
6402 * @param parent activity related to the error, null if unknown
6403 * @param subject line related to the error, null if absent
6404 * @param report in long form describing the error, null if absent
6405 * @param logFile to include in the report, null if none
6406 * @param crashInfo giving an application stack trace, null if absent
6407 */
6408 public void addErrorToDropBox(String eventType,
6409 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6410 final String report, final File logFile,
6411 final ApplicationErrorReport.CrashInfo crashInfo) {
6412 // NOTE -- this must never acquire the ActivityManagerService lock,
6413 // otherwise the watchdog may be prevented from resetting the system.
6414
6415 final String dropboxTag = processClass(process) + "_" + eventType;
6416 final DropBoxManager dbox = (DropBoxManager)
6417 mContext.getSystemService(Context.DROPBOX_SERVICE);
6418
6419 // Exit early if the dropbox isn't configured to accept this report type.
6420 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6421
6422 final StringBuilder sb = new StringBuilder(1024);
6423 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006424 if (activity != null) {
6425 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6426 }
6427 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6428 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6429 }
6430 if (parent != null && parent != activity) {
6431 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6432 }
6433 if (subject != null) {
6434 sb.append("Subject: ").append(subject).append("\n");
6435 }
6436 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6437 sb.append("\n");
6438
6439 // Do the rest in a worker thread to avoid blocking the caller on I/O
6440 // (After this point, we shouldn't access AMS internal data structures.)
6441 Thread worker = new Thread("Error dump: " + dropboxTag) {
6442 @Override
6443 public void run() {
6444 if (report != null) {
6445 sb.append(report);
6446 }
6447 if (logFile != null) {
6448 try {
6449 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6450 } catch (IOException e) {
6451 Slog.e(TAG, "Error reading " + logFile, e);
6452 }
6453 }
6454 if (crashInfo != null && crashInfo.stackTrace != null) {
6455 sb.append(crashInfo.stackTrace);
6456 }
6457
6458 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6459 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6460 if (lines > 0) {
6461 sb.append("\n");
6462
6463 // Merge several logcat streams, and take the last N lines
6464 InputStreamReader input = null;
6465 try {
6466 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6467 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6468 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6469
6470 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6471 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6472 input = new InputStreamReader(logcat.getInputStream());
6473
6474 int num;
6475 char[] buf = new char[8192];
6476 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6477 } catch (IOException e) {
6478 Slog.e(TAG, "Error running logcat", e);
6479 } finally {
6480 if (input != null) try { input.close(); } catch (IOException e) {}
6481 }
6482 }
6483
6484 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006485 }
Dan Egnora455d192010-03-12 08:52:28 -08006486 };
6487
6488 if (process == null || process.pid == MY_PID) {
6489 worker.run(); // We may be about to die -- need to run this synchronously
6490 } else {
6491 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006492 }
6493 }
6494
6495 /**
6496 * Bring up the "unexpected error" dialog box for a crashing app.
6497 * Deal with edge cases (intercepts from instrumented applications,
6498 * ActivityController, error intent receivers, that sort of thing).
6499 * @param r the application crashing
6500 * @param crashInfo describing the failure
6501 */
6502 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006503 long timeMillis = System.currentTimeMillis();
6504 String shortMsg = crashInfo.exceptionClassName;
6505 String longMsg = crashInfo.exceptionMessage;
6506 String stackTrace = crashInfo.stackTrace;
6507 if (shortMsg != null && longMsg != null) {
6508 longMsg = shortMsg + ": " + longMsg;
6509 } else if (shortMsg != null) {
6510 longMsg = shortMsg;
6511 }
6512
Dan Egnor60d87622009-12-16 16:32:58 -08006513 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006514 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006515 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006516 try {
6517 String name = r != null ? r.processName : null;
6518 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006519 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006520 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006521 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 + " at watcher's request");
6523 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006524 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006525 }
6526 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006527 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006528 }
6529 }
6530
6531 final long origId = Binder.clearCallingIdentity();
6532
6533 // If this process is running instrumentation, finish it.
6534 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006535 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006537 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6538 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 Bundle info = new Bundle();
6540 info.putString("shortMsg", shortMsg);
6541 info.putString("longMsg", longMsg);
6542 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6543 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006544 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006545 }
6546
Dan Egnor60d87622009-12-16 16:32:58 -08006547 // If we can't identify the process or it's already exceeded its crash quota,
6548 // quit right away without showing a crash dialog.
6549 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006550 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006551 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006552 }
6553
6554 Message msg = Message.obtain();
6555 msg.what = SHOW_ERROR_MSG;
6556 HashMap data = new HashMap();
6557 data.put("result", result);
6558 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006559 msg.obj = data;
6560 mHandler.sendMessage(msg);
6561
6562 Binder.restoreCallingIdentity(origId);
6563 }
6564
6565 int res = result.get();
6566
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006567 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 synchronized (this) {
6569 if (r != null) {
6570 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6571 SystemClock.uptimeMillis());
6572 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006573 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006574 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006575 }
6576 }
6577
6578 if (appErrorIntent != null) {
6579 try {
6580 mContext.startActivity(appErrorIntent);
6581 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006582 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006583 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006585 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006586
6587 Intent createAppErrorIntentLocked(ProcessRecord r,
6588 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6589 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006590 if (report == null) {
6591 return null;
6592 }
6593 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6594 result.setComponent(r.errorReportReceiver);
6595 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6596 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6597 return result;
6598 }
6599
Dan Egnorb7f03672009-12-09 16:22:32 -08006600 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6601 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006602 if (r.errorReportReceiver == null) {
6603 return null;
6604 }
6605
6606 if (!r.crashing && !r.notResponding) {
6607 return null;
6608 }
6609
Dan Egnorb7f03672009-12-09 16:22:32 -08006610 ApplicationErrorReport report = new ApplicationErrorReport();
6611 report.packageName = r.info.packageName;
6612 report.installerPackageName = r.errorReportReceiver.getPackageName();
6613 report.processName = r.processName;
6614 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006615 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006616
Dan Egnorb7f03672009-12-09 16:22:32 -08006617 if (r.crashing) {
6618 report.type = ApplicationErrorReport.TYPE_CRASH;
6619 report.crashInfo = crashInfo;
6620 } else if (r.notResponding) {
6621 report.type = ApplicationErrorReport.TYPE_ANR;
6622 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006623
Dan Egnorb7f03672009-12-09 16:22:32 -08006624 report.anrInfo.activity = r.notRespondingReport.tag;
6625 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6626 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006627 }
6628
Dan Egnorb7f03672009-12-09 16:22:32 -08006629 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006630 }
6631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006632 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6633 // assume our apps are happy - lazy create the list
6634 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6635
6636 synchronized (this) {
6637
6638 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006639 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6640 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6642 // This one's in trouble, so we'll generate a report for it
6643 // crashes are higher priority (in case there's a crash *and* an anr)
6644 ActivityManager.ProcessErrorStateInfo report = null;
6645 if (app.crashing) {
6646 report = app.crashingReport;
6647 } else if (app.notResponding) {
6648 report = app.notRespondingReport;
6649 }
6650
6651 if (report != null) {
6652 if (errList == null) {
6653 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6654 }
6655 errList.add(report);
6656 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006657 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 " crashing = " + app.crashing +
6659 " notResponding = " + app.notResponding);
6660 }
6661 }
6662 }
6663 }
6664
6665 return errList;
6666 }
6667
6668 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6669 // Lazy instantiation of list
6670 List<ActivityManager.RunningAppProcessInfo> runList = null;
6671 synchronized (this) {
6672 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006673 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6674 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6676 // Generate process state info for running application
6677 ActivityManager.RunningAppProcessInfo currApp =
6678 new ActivityManager.RunningAppProcessInfo(app.processName,
6679 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006680 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006681 if (mHeavyWeightProcess == app) {
6682 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006684 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006685 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006686 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6687 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6688 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006689 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6690 } else if (adj >= HOME_APP_ADJ) {
6691 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6692 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 } else if (adj >= SECONDARY_SERVER_ADJ) {
6694 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006695 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6696 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6697 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6698 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 } else if (adj >= VISIBLE_APP_ADJ) {
6700 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6701 } else {
6702 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6703 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006704 currApp.importanceReasonCode = app.adjTypeCode;
6705 if (app.adjSource instanceof ProcessRecord) {
6706 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006707 } else if (app.adjSource instanceof ActivityRecord) {
6708 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006709 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6710 }
6711 if (app.adjTarget instanceof ComponentName) {
6712 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6713 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006714 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 // + " lru=" + currApp.lru);
6716 if (runList == null) {
6717 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6718 }
6719 runList.add(currApp);
6720 }
6721 }
6722 }
6723 return runList;
6724 }
6725
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006726 public List<ApplicationInfo> getRunningExternalApplications() {
6727 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6728 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6729 if (runningApps != null && runningApps.size() > 0) {
6730 Set<String> extList = new HashSet<String>();
6731 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6732 if (app.pkgList != null) {
6733 for (String pkg : app.pkgList) {
6734 extList.add(pkg);
6735 }
6736 }
6737 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006738 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006739 for (String pkg : extList) {
6740 try {
6741 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6742 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6743 retList.add(info);
6744 }
6745 } catch (RemoteException e) {
6746 }
6747 }
6748 }
6749 return retList;
6750 }
6751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006752 @Override
6753 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006754 if (checkCallingPermission(android.Manifest.permission.DUMP)
6755 != PackageManager.PERMISSION_GRANTED) {
6756 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6757 + Binder.getCallingPid()
6758 + ", uid=" + Binder.getCallingUid()
6759 + " without permission "
6760 + android.Manifest.permission.DUMP);
6761 return;
6762 }
6763
6764 boolean dumpAll = false;
6765
6766 int opti = 0;
6767 while (opti < args.length) {
6768 String opt = args[opti];
6769 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6770 break;
6771 }
6772 opti++;
6773 if ("-a".equals(opt)) {
6774 dumpAll = true;
6775 } else if ("-h".equals(opt)) {
6776 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006777 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006778 pw.println(" cmd may be one of:");
6779 pw.println(" activities: activity stack state");
6780 pw.println(" broadcasts: broadcast state");
6781 pw.println(" intents: pending intent state");
6782 pw.println(" processes: process state");
6783 pw.println(" providers: content provider state");
6784 pw.println(" services: service state");
6785 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006787 } else {
6788 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006789 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006790 }
6791
6792 // Is the caller requesting to dump a particular piece of data?
6793 if (opti < args.length) {
6794 String cmd = args[opti];
6795 opti++;
6796 if ("activities".equals(cmd) || "a".equals(cmd)) {
6797 synchronized (this) {
6798 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006799 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006800 return;
6801 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6802 synchronized (this) {
6803 dumpBroadcastsLocked(fd, pw, args, opti, true);
6804 }
6805 return;
6806 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6807 synchronized (this) {
6808 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6809 }
6810 return;
6811 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6812 synchronized (this) {
6813 dumpProcessesLocked(fd, pw, args, opti, true);
6814 }
6815 return;
6816 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6817 synchronized (this) {
6818 dumpProvidersLocked(fd, pw, args, opti, true);
6819 }
6820 return;
6821 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006822 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006823 return;
6824 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6825 synchronized (this) {
6826 dumpServicesLocked(fd, pw, args, opti, true);
6827 }
6828 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006830 }
6831
6832 // No piece of data specified, dump everything.
6833 synchronized (this) {
6834 boolean needSep;
6835 if (dumpAll) {
6836 pw.println("Providers in Current Activity Manager State:");
6837 }
6838 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6839 if (needSep) {
6840 pw.println(" ");
6841 }
6842 if (dumpAll) {
6843 pw.println("-------------------------------------------------------------------------------");
6844 pw.println("Broadcasts in Current Activity Manager State:");
6845 }
6846 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6847 if (needSep) {
6848 pw.println(" ");
6849 }
6850 if (dumpAll) {
6851 pw.println("-------------------------------------------------------------------------------");
6852 pw.println("Services in Current Activity Manager State:");
6853 }
6854 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6855 if (needSep) {
6856 pw.println(" ");
6857 }
6858 if (dumpAll) {
6859 pw.println("-------------------------------------------------------------------------------");
6860 pw.println("PendingIntents in Current Activity Manager State:");
6861 }
6862 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6863 if (needSep) {
6864 pw.println(" ");
6865 }
6866 if (dumpAll) {
6867 pw.println("-------------------------------------------------------------------------------");
6868 pw.println("Activities in Current Activity Manager State:");
6869 }
6870 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6871 if (needSep) {
6872 pw.println(" ");
6873 }
6874 if (dumpAll) {
6875 pw.println("-------------------------------------------------------------------------------");
6876 pw.println("Processes in Current Activity Manager State:");
6877 }
6878 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6879 }
6880 }
6881
6882 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6883 int opti, boolean dumpAll, boolean needHeader) {
6884 if (needHeader) {
6885 pw.println(" Activity stack:");
6886 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006887 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006888 pw.println(" ");
6889 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006890 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6891 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006892 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006893 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006894 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006895 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006896 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006897 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006898 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006899 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006900 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006901 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006902 pw.println(" ");
6903 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006904 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006907 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006908 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
6909 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006910 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006911 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006912
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006913 if (dumpAll && mRecentTasks.size() > 0) {
6914 pw.println(" ");
6915 pw.println("Recent tasks in Current Activity Manager State:");
6916
6917 final int N = mRecentTasks.size();
6918 for (int i=0; i<N; i++) {
6919 TaskRecord tr = mRecentTasks.get(i);
6920 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
6921 pw.println(tr);
6922 mRecentTasks.get(i).dump(pw, " ");
6923 }
6924 }
6925
6926 pw.println(" ");
6927 pw.println(" mCurTask: " + mCurTask);
6928
6929 return true;
6930 }
6931
6932 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6933 int opti, boolean dumpAll) {
6934 boolean needSep = false;
6935 int numPers = 0;
6936
6937 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006938 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
6939 final int NA = procs.size();
6940 for (int ia=0; ia<NA; ia++) {
6941 if (!needSep) {
6942 pw.println(" All known processes:");
6943 needSep = true;
6944 }
6945 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006946 pw.print(r.persistent ? " *PERS*" : " *APP*");
6947 pw.print(" UID "); pw.print(procs.keyAt(ia));
6948 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006949 r.dump(pw, " ");
6950 if (r.persistent) {
6951 numPers++;
6952 }
6953 }
6954 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006955 }
6956
6957 if (mLruProcesses.size() > 0) {
6958 if (needSep) pw.println(" ");
6959 needSep = true;
6960 pw.println(" Running processes (most recent first):");
6961 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006962 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006963 needSep = true;
6964 }
6965
6966 synchronized (mPidsSelfLocked) {
6967 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006968 if (needSep) pw.println(" ");
6969 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006970 pw.println(" PID mappings:");
6971 for (int i=0; i<mPidsSelfLocked.size(); i++) {
6972 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
6973 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974 }
6975 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006976 }
6977
6978 if (mForegroundProcesses.size() > 0) {
6979 if (needSep) pw.println(" ");
6980 needSep = true;
6981 pw.println(" Foreground Processes:");
6982 for (int i=0; i<mForegroundProcesses.size(); i++) {
6983 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
6984 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006986 }
6987
6988 if (mPersistentStartingProcesses.size() > 0) {
6989 if (needSep) pw.println(" ");
6990 needSep = true;
6991 pw.println(" Persisent processes that are starting:");
6992 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
6993 "Starting Norm", "Restarting PERS", false);
6994 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006995
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006996 if (mStartingProcesses.size() > 0) {
6997 if (needSep) pw.println(" ");
6998 needSep = true;
6999 pw.println(" Processes that are starting:");
7000 dumpProcessList(pw, this, mStartingProcesses, " ",
7001 "Starting Norm", "Starting PERS", false);
7002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007003
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007004 if (mRemovedProcesses.size() > 0) {
7005 if (needSep) pw.println(" ");
7006 needSep = true;
7007 pw.println(" Processes that are being removed:");
7008 dumpProcessList(pw, this, mRemovedProcesses, " ",
7009 "Removed Norm", "Removed PERS", false);
7010 }
7011
7012 if (mProcessesOnHold.size() > 0) {
7013 if (needSep) pw.println(" ");
7014 needSep = true;
7015 pw.println(" Processes that are on old until the system is ready:");
7016 dumpProcessList(pw, this, mProcessesOnHold, " ",
7017 "OnHold Norm", "OnHold PERS", false);
7018 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007019
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007020 if (mProcessesToGc.size() > 0) {
7021 if (needSep) pw.println(" ");
7022 needSep = true;
7023 pw.println(" Processes that are waiting to GC:");
7024 long now = SystemClock.uptimeMillis();
7025 for (int i=0; i<mProcessesToGc.size(); i++) {
7026 ProcessRecord proc = mProcessesToGc.get(i);
7027 pw.print(" Process "); pw.println(proc);
7028 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7029 pw.print(", last gced=");
7030 pw.print(now-proc.lastRequestedGc);
7031 pw.print(" ms ago, last lowMem=");
7032 pw.print(now-proc.lastLowMemory);
7033 pw.println(" ms ago");
7034
7035 }
7036 }
7037
7038 if (mProcessCrashTimes.getMap().size() > 0) {
7039 if (needSep) pw.println(" ");
7040 needSep = true;
7041 pw.println(" Time since processes crashed:");
7042 long now = SystemClock.uptimeMillis();
7043 for (Map.Entry<String, SparseArray<Long>> procs
7044 : mProcessCrashTimes.getMap().entrySet()) {
7045 SparseArray<Long> uids = procs.getValue();
7046 final int N = uids.size();
7047 for (int i=0; i<N; i++) {
7048 pw.print(" Process "); pw.print(procs.getKey());
7049 pw.print(" uid "); pw.print(uids.keyAt(i));
7050 pw.print(": last crashed ");
7051 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007052 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007053 }
7054 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007056
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007057 if (mBadProcesses.getMap().size() > 0) {
7058 if (needSep) pw.println(" ");
7059 needSep = true;
7060 pw.println(" Bad processes:");
7061 for (Map.Entry<String, SparseArray<Long>> procs
7062 : mBadProcesses.getMap().entrySet()) {
7063 SparseArray<Long> uids = procs.getValue();
7064 final int N = uids.size();
7065 for (int i=0; i<N; i++) {
7066 pw.print(" Bad process "); pw.print(procs.getKey());
7067 pw.print(" uid "); pw.print(uids.keyAt(i));
7068 pw.print(": crashed at time ");
7069 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007070 }
7071 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007073
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007074 pw.println(" ");
7075 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007076 if (mHeavyWeightProcess != null) {
7077 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7078 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007079 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007080 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007081 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7082 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7083 || mOrigWaitForDebugger) {
7084 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7085 + " mDebugTransient=" + mDebugTransient
7086 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7087 }
7088 if (mAlwaysFinishActivities || mController != null) {
7089 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7090 + " mController=" + mController);
7091 }
7092 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007093 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007094 pw.println(" mStartRunning=" + mStartRunning
7095 + " mSystemReady=" + mSystemReady
7096 + " mBooting=" + mBooting
7097 + " mBooted=" + mBooted
7098 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007099 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7100 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007101 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007102 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007103
7104 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007105 }
7106
7107 /**
7108 * There are three ways to call this:
7109 * - no service specified: dump all the services
7110 * - a flattened component name that matched an existing service was specified as the
7111 * first arg: dump that one service
7112 * - the first arg isn't the flattened component name of an existing service:
7113 * dump all services whose component contains the first arg as a substring
7114 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007115 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7116 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 String[] newArgs;
7118 String componentNameString;
7119 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007120 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007121 componentNameString = null;
7122 newArgs = EMPTY_STRING_ARRAY;
7123 r = null;
7124 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007125 componentNameString = args[opti];
7126 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007127 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007128 synchronized (this) {
7129 r = componentName != null ? mServices.get(componentName) : null;
7130 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007131 newArgs = new String[args.length - opti];
7132 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007133 }
7134
7135 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007136 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007138 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7139 synchronized (this) {
7140 for (ServiceRecord r1 : mServices.values()) {
7141 if (componentNameString == null
7142 || r1.name.flattenToString().contains(componentNameString)) {
7143 services.add(r1);
7144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145 }
7146 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007147 for (int i=0; i<services.size(); i++) {
7148 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007150 }
7151 }
7152
7153 /**
7154 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7155 * there is a thread associated with the service.
7156 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007157 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7158 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007159 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007160 if (dumpAll) {
7161 synchronized (this) {
7162 pw.print(" * "); pw.println(r);
7163 r.dump(pw, " ");
7164 }
7165 pw.println("");
7166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007167 if (r.app != null && r.app.thread != null) {
7168 try {
7169 // flush anything that is already in the PrintWriter since the thread is going
7170 // to write to the file descriptor directly
7171 pw.flush();
7172 r.app.thread.dumpService(fd, r, args);
7173 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007174 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175 } catch (RemoteException e) {
7176 pw.println("got a RemoteException while dumping the service");
7177 }
7178 }
7179 }
7180
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007181 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7182 int opti, boolean dumpAll) {
7183 boolean needSep = false;
7184
7185 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186 if (mRegisteredReceivers.size() > 0) {
7187 pw.println(" ");
7188 pw.println(" Registered Receivers:");
7189 Iterator it = mRegisteredReceivers.values().iterator();
7190 while (it.hasNext()) {
7191 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007192 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007193 r.dump(pw, " ");
7194 }
7195 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007197 pw.println(" ");
7198 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007199 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007200 needSep = true;
7201 }
7202
7203 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7204 || mPendingBroadcast != null) {
7205 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007206 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007207 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007208 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007209 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7210 pw.println(" Broadcast #" + i + ":");
7211 mParallelBroadcasts.get(i).dump(pw, " ");
7212 }
7213 if (mOrderedBroadcasts.size() > 0) {
7214 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007215 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007216 }
7217 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7218 pw.println(" Serialized Broadcast #" + i + ":");
7219 mOrderedBroadcasts.get(i).dump(pw, " ");
7220 }
7221 pw.println(" ");
7222 pw.println(" Pending broadcast:");
7223 if (mPendingBroadcast != null) {
7224 mPendingBroadcast.dump(pw, " ");
7225 } else {
7226 pw.println(" (null)");
7227 }
7228 needSep = true;
7229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007230
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007231 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007233 pw.println(" Historical broadcasts:");
7234 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7235 BroadcastRecord r = mBroadcastHistory[i];
7236 if (r == null) {
7237 break;
7238 }
7239 pw.println(" Historical Broadcast #" + i + ":");
7240 r.dump(pw, " ");
7241 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007242 needSep = true;
7243 }
7244
7245 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007246 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007247 pw.println(" Sticky broadcasts:");
7248 StringBuilder sb = new StringBuilder(128);
7249 for (Map.Entry<String, ArrayList<Intent>> ent
7250 : mStickyBroadcasts.entrySet()) {
7251 pw.print(" * Sticky action "); pw.print(ent.getKey());
7252 pw.println(":");
7253 ArrayList<Intent> intents = ent.getValue();
7254 final int N = intents.size();
7255 for (int i=0; i<N; i++) {
7256 sb.setLength(0);
7257 sb.append(" Intent: ");
7258 intents.get(i).toShortString(sb, true, false);
7259 pw.println(sb.toString());
7260 Bundle bundle = intents.get(i).getExtras();
7261 if (bundle != null) {
7262 pw.print(" ");
7263 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007264 }
7265 }
7266 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007267 needSep = true;
7268 }
7269
7270 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007272 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 pw.println(" mHandler:");
7274 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007275 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007276 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007277
7278 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007279 }
7280
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007281 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7282 int opti, boolean dumpAll) {
7283 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007284
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007285 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007286 if (mServices.size() > 0) {
7287 pw.println(" Active services:");
7288 Iterator<ServiceRecord> it = mServices.values().iterator();
7289 while (it.hasNext()) {
7290 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007291 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007292 r.dump(pw, " ");
7293 }
7294 needSep = true;
7295 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007296 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007298 if (mPendingServices.size() > 0) {
7299 if (needSep) pw.println(" ");
7300 pw.println(" Pending services:");
7301 for (int i=0; i<mPendingServices.size(); i++) {
7302 ServiceRecord r = mPendingServices.get(i);
7303 pw.print(" * Pending "); pw.println(r);
7304 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007305 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007306 needSep = true;
7307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007309 if (mRestartingServices.size() > 0) {
7310 if (needSep) pw.println(" ");
7311 pw.println(" Restarting services:");
7312 for (int i=0; i<mRestartingServices.size(); i++) {
7313 ServiceRecord r = mRestartingServices.get(i);
7314 pw.print(" * Restarting "); pw.println(r);
7315 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007317 needSep = true;
7318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007320 if (mStoppingServices.size() > 0) {
7321 if (needSep) pw.println(" ");
7322 pw.println(" Stopping services:");
7323 for (int i=0; i<mStoppingServices.size(); i++) {
7324 ServiceRecord r = mStoppingServices.get(i);
7325 pw.print(" * Stopping "); pw.println(r);
7326 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007327 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007328 needSep = true;
7329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007330
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007331 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007332 if (mServiceConnections.size() > 0) {
7333 if (needSep) pw.println(" ");
7334 pw.println(" Connection bindings to services:");
7335 Iterator<ConnectionRecord> it
7336 = mServiceConnections.values().iterator();
7337 while (it.hasNext()) {
7338 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007339 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007340 r.dump(pw, " ");
7341 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007342 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007343 }
7344 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007345
7346 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007347 }
7348
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007349 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7350 int opti, boolean dumpAll) {
7351 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007353 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007354 if (mProvidersByClass.size() > 0) {
7355 if (needSep) pw.println(" ");
7356 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007357 Iterator<Map.Entry<String, ContentProviderRecord>> it
7358 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007359 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007360 Map.Entry<String, ContentProviderRecord> e = it.next();
7361 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007362 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007363 r.dump(pw, " ");
7364 }
7365 needSep = true;
7366 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007367
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007368 if (mProvidersByName.size() > 0) {
7369 pw.println(" ");
7370 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007371 Iterator<Map.Entry<String, ContentProviderRecord>> it
7372 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007373 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007374 Map.Entry<String, ContentProviderRecord> e = it.next();
7375 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007376 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7377 pw.println(r);
7378 }
7379 needSep = true;
7380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007381 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007382
7383 if (mLaunchingProviders.size() > 0) {
7384 if (needSep) pw.println(" ");
7385 pw.println(" Launching content providers:");
7386 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7387 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7388 pw.println(mLaunchingProviders.get(i));
7389 }
7390 needSep = true;
7391 }
7392
7393 if (mGrantedUriPermissions.size() > 0) {
7394 pw.println();
7395 pw.println("Granted Uri Permissions:");
7396 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7397 int uid = mGrantedUriPermissions.keyAt(i);
7398 HashMap<Uri, UriPermission> perms
7399 = mGrantedUriPermissions.valueAt(i);
7400 pw.print(" * UID "); pw.print(uid);
7401 pw.println(" holds:");
7402 for (UriPermission perm : perms.values()) {
7403 pw.print(" "); pw.println(perm);
7404 perm.dump(pw, " ");
7405 }
7406 }
7407 needSep = true;
7408 }
7409
7410 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 }
7412
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007413 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7414 int opti, boolean dumpAll) {
7415 boolean needSep = false;
7416
7417 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007418 if (this.mIntentSenderRecords.size() > 0) {
7419 Iterator<WeakReference<PendingIntentRecord>> it
7420 = mIntentSenderRecords.values().iterator();
7421 while (it.hasNext()) {
7422 WeakReference<PendingIntentRecord> ref = it.next();
7423 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007424 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007425 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007426 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 rec.dump(pw, " ");
7428 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007429 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 }
7431 }
7432 }
7433 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007434
7435 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 }
7437
7438 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007439 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 TaskRecord lastTask = null;
7441 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007442 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007443 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007444 if (lastTask != r.task) {
7445 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007446 pw.print(prefix);
7447 pw.print(full ? "* " : " ");
7448 pw.println(lastTask);
7449 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007450 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007452 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007453 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7454 pw.print(" #"); pw.print(i); pw.print(": ");
7455 pw.println(r);
7456 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007457 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007459 }
7460 }
7461
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007462 private static String buildOomTag(String prefix, String space, int val, int base) {
7463 if (val == base) {
7464 if (space == null) return prefix;
7465 return prefix + " ";
7466 }
7467 return prefix + "+" + Integer.toString(val-base);
7468 }
7469
7470 private static final int dumpProcessList(PrintWriter pw,
7471 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472 String prefix, String normalLabel, String persistentLabel,
7473 boolean inclOomAdj) {
7474 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007475 final int N = list.size()-1;
7476 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007477 ProcessRecord r = (ProcessRecord)list.get(i);
7478 if (false) {
7479 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7480 + " #" + i + ":");
7481 r.dump(pw, prefix + " ");
7482 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007483 String oomAdj;
7484 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007485 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007486 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007487 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7488 } else if (r.setAdj >= HOME_APP_ADJ) {
7489 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7490 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7491 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7492 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7493 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007494 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7495 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7496 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7497 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007498 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7499 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7500 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7501 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007502 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007503 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007504 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007505 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007506 } else {
7507 oomAdj = Integer.toString(r.setAdj);
7508 }
7509 String schedGroup;
7510 switch (r.setSchedGroup) {
7511 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7512 schedGroup = "B";
7513 break;
7514 case Process.THREAD_GROUP_DEFAULT:
7515 schedGroup = "F";
7516 break;
7517 default:
7518 schedGroup = Integer.toString(r.setSchedGroup);
7519 break;
7520 }
7521 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007522 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007523 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007524 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007525 pw.print(prefix);
7526 pw.print(" ");
7527 if (r.adjTarget instanceof ComponentName) {
7528 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7529 } else if (r.adjTarget != null) {
7530 pw.print(r.adjTarget.toString());
7531 } else {
7532 pw.print("{null}");
7533 }
7534 pw.print("<=");
7535 if (r.adjSource instanceof ProcessRecord) {
7536 pw.print("Proc{");
7537 pw.print(((ProcessRecord)r.adjSource).toShortString());
7538 pw.println("}");
7539 } else if (r.adjSource != null) {
7540 pw.println(r.adjSource.toString());
7541 } else {
7542 pw.println("{null}");
7543 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 } else {
7546 pw.println(String.format("%s%s #%2d: %s",
7547 prefix, (r.persistent ? persistentLabel : normalLabel),
7548 i, r.toString()));
7549 }
7550 if (r.persistent) {
7551 numPers++;
7552 }
7553 }
7554 return numPers;
7555 }
7556
Dianne Hackborn472ad872010-04-07 17:31:48 -07007557 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007559 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 long uptime = SystemClock.uptimeMillis();
7561 long realtime = SystemClock.elapsedRealtime();
7562
7563 if (isCheckinRequest) {
7564 // short checkin version
7565 pw.println(uptime + "," + realtime);
7566 pw.flush();
7567 } else {
7568 pw.println("Applications Memory Usage (kB):");
7569 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7570 }
7571 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7572 ProcessRecord r = (ProcessRecord)list.get(i);
7573 if (r.thread != null) {
7574 if (!isCheckinRequest) {
7575 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7576 pw.flush();
7577 }
7578 try {
7579 r.thread.asBinder().dump(fd, args);
7580 } catch (RemoteException e) {
7581 if (!isCheckinRequest) {
7582 pw.println("Got RemoteException!");
7583 pw.flush();
7584 }
7585 }
7586 }
7587 }
7588 }
7589
7590 /**
7591 * Searches array of arguments for the specified string
7592 * @param args array of argument strings
7593 * @param value value to search for
7594 * @return true if the value is contained in the array
7595 */
7596 private static boolean scanArgs(String[] args, String value) {
7597 if (args != null) {
7598 for (String arg : args) {
7599 if (value.equals(arg)) {
7600 return true;
7601 }
7602 }
7603 }
7604 return false;
7605 }
7606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007607 private final void killServicesLocked(ProcessRecord app,
7608 boolean allowRestart) {
7609 // Report disconnected services.
7610 if (false) {
7611 // XXX we are letting the client link to the service for
7612 // death notifications.
7613 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007614 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007616 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007617 if (r.connections.size() > 0) {
7618 Iterator<ConnectionRecord> jt
7619 = r.connections.values().iterator();
7620 while (jt.hasNext()) {
7621 ConnectionRecord c = jt.next();
7622 if (c.binding.client != app) {
7623 try {
7624 //c.conn.connected(r.className, null);
7625 } catch (Exception e) {
7626 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007627 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 + r.shortName
7629 + " from app " + app.processName, e);
7630 }
7631 }
7632 }
7633 }
7634 }
7635 }
7636 }
7637
7638 // Clean up any connections this application has to other services.
7639 if (app.connections.size() > 0) {
7640 Iterator<ConnectionRecord> it = app.connections.iterator();
7641 while (it.hasNext()) {
7642 ConnectionRecord r = it.next();
7643 removeConnectionLocked(r, app, null);
7644 }
7645 }
7646 app.connections.clear();
7647
7648 if (app.services.size() != 0) {
7649 // Any services running in the application need to be placed
7650 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007651 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007653 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007654 synchronized (sr.stats.getBatteryStats()) {
7655 sr.stats.stopLaunchedLocked();
7656 }
7657 sr.app = null;
7658 sr.executeNesting = 0;
7659 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007660
7661 boolean hasClients = sr.bindings.size() > 0;
7662 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007663 Iterator<IntentBindRecord> bindings
7664 = sr.bindings.values().iterator();
7665 while (bindings.hasNext()) {
7666 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007667 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007668 + ": shouldUnbind=" + b.hasBound);
7669 b.binder = null;
7670 b.requested = b.received = b.hasBound = false;
7671 }
7672 }
7673
7674 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007675 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007677 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 sr.crashCount, sr.shortName, app.pid);
7679 bringDownServiceLocked(sr, true);
7680 } else if (!allowRestart) {
7681 bringDownServiceLocked(sr, true);
7682 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007683 boolean canceled = scheduleServiceRestartLocked(sr, true);
7684
7685 // Should the service remain running? Note that in the
7686 // extreme case of so many attempts to deliver a command
7687 // that it failed, that we also will stop it here.
7688 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7689 if (sr.pendingStarts.size() == 0) {
7690 sr.startRequested = false;
7691 if (!hasClients) {
7692 // Whoops, no reason to restart!
7693 bringDownServiceLocked(sr, true);
7694 }
7695 }
7696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 }
7698 }
7699
7700 if (!allowRestart) {
7701 app.services.clear();
7702 }
7703 }
7704
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007705 // Make sure we have no more records on the stopping list.
7706 int i = mStoppingServices.size();
7707 while (i > 0) {
7708 i--;
7709 ServiceRecord sr = mStoppingServices.get(i);
7710 if (sr.app == app) {
7711 mStoppingServices.remove(i);
7712 }
7713 }
7714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007715 app.executingServices.clear();
7716 }
7717
7718 private final void removeDyingProviderLocked(ProcessRecord proc,
7719 ContentProviderRecord cpr) {
7720 synchronized (cpr) {
7721 cpr.launchingApp = null;
7722 cpr.notifyAll();
7723 }
7724
7725 mProvidersByClass.remove(cpr.info.name);
7726 String names[] = cpr.info.authority.split(";");
7727 for (int j = 0; j < names.length; j++) {
7728 mProvidersByName.remove(names[j]);
7729 }
7730
7731 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7732 while (cit.hasNext()) {
7733 ProcessRecord capp = cit.next();
7734 if (!capp.persistent && capp.thread != null
7735 && capp.pid != 0
7736 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007737 Slog.i(TAG, "Kill " + capp.processName
7738 + " (pid " + capp.pid + "): provider " + cpr.info.name
7739 + " in dying process " + proc.processName);
7740 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7741 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 Process.killProcess(capp.pid);
7743 }
7744 }
7745
7746 mLaunchingProviders.remove(cpr);
7747 }
7748
7749 /**
7750 * Main code for cleaning up a process when it has gone away. This is
7751 * called both as a result of the process dying, or directly when stopping
7752 * a process when running in single process mode.
7753 */
7754 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7755 boolean restarting, int index) {
7756 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007757 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007758 }
7759
Dianne Hackborn36124872009-10-08 16:22:03 -07007760 mProcessesToGc.remove(app);
7761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762 // Dismiss any open dialogs.
7763 if (app.crashDialog != null) {
7764 app.crashDialog.dismiss();
7765 app.crashDialog = null;
7766 }
7767 if (app.anrDialog != null) {
7768 app.anrDialog.dismiss();
7769 app.anrDialog = null;
7770 }
7771 if (app.waitDialog != null) {
7772 app.waitDialog.dismiss();
7773 app.waitDialog = null;
7774 }
7775
7776 app.crashing = false;
7777 app.notResponding = false;
7778
7779 app.resetPackageList();
7780 app.thread = null;
7781 app.forcingToForeground = null;
7782 app.foregroundServices = false;
7783
7784 killServicesLocked(app, true);
7785
7786 boolean restart = false;
7787
7788 int NL = mLaunchingProviders.size();
7789
7790 // Remove published content providers.
7791 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007792 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007793 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007794 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795 cpr.provider = null;
7796 cpr.app = null;
7797
7798 // See if someone is waiting for this provider... in which
7799 // case we don't remove it, but just let it restart.
7800 int i = 0;
7801 if (!app.bad) {
7802 for (; i<NL; i++) {
7803 if (mLaunchingProviders.get(i) == cpr) {
7804 restart = true;
7805 break;
7806 }
7807 }
7808 } else {
7809 i = NL;
7810 }
7811
7812 if (i >= NL) {
7813 removeDyingProviderLocked(app, cpr);
7814 NL = mLaunchingProviders.size();
7815 }
7816 }
7817 app.pubProviders.clear();
7818 }
7819
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007820 // Take care of any launching providers waiting for this process.
7821 if (checkAppInLaunchingProvidersLocked(app, false)) {
7822 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 // Unregister from connected content providers.
7826 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007827 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007828 while (it.hasNext()) {
7829 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7830 cpr.clients.remove(app);
7831 }
7832 app.conProviders.clear();
7833 }
7834
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007835 // At this point there may be remaining entries in mLaunchingProviders
7836 // where we were the only one waiting, so they are no longer of use.
7837 // Look for these and clean up if found.
7838 // XXX Commented out for now. Trying to figure out a way to reproduce
7839 // the actual situation to identify what is actually going on.
7840 if (false) {
7841 for (int i=0; i<NL; i++) {
7842 ContentProviderRecord cpr = (ContentProviderRecord)
7843 mLaunchingProviders.get(i);
7844 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7845 synchronized (cpr) {
7846 cpr.launchingApp = null;
7847 cpr.notifyAll();
7848 }
7849 }
7850 }
7851 }
7852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 skipCurrentReceiverLocked(app);
7854
7855 // Unregister any receivers.
7856 if (app.receivers.size() > 0) {
7857 Iterator<ReceiverList> it = app.receivers.iterator();
7858 while (it.hasNext()) {
7859 removeReceiverLocked(it.next());
7860 }
7861 app.receivers.clear();
7862 }
7863
Christopher Tate181fafa2009-05-14 11:12:14 -07007864 // If the app is undergoing backup, tell the backup manager about it
7865 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007866 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007867 try {
7868 IBackupManager bm = IBackupManager.Stub.asInterface(
7869 ServiceManager.getService(Context.BACKUP_SERVICE));
7870 bm.agentDisconnected(app.info.packageName);
7871 } catch (RemoteException e) {
7872 // can't happen; backup manager is local
7873 }
7874 }
7875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 // If the caller is restarting this app, then leave it in its
7877 // current lists and let the caller take care of it.
7878 if (restarting) {
7879 return;
7880 }
7881
7882 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007883 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 "Removing non-persistent process during cleanup: " + app);
7885 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007886 if (mHeavyWeightProcess == app) {
7887 mHeavyWeightProcess = null;
7888 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 } else if (!app.removed) {
7891 // This app is persistent, so we need to keep its record around.
7892 // If it is not already on the pending app list, add it there
7893 // and start a new process for it.
7894 app.thread = null;
7895 app.forcingToForeground = null;
7896 app.foregroundServices = false;
7897 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7898 mPersistentStartingProcesses.add(app);
7899 restart = true;
7900 }
7901 }
7902 mProcessesOnHold.remove(app);
7903
The Android Open Source Project4df24232009-03-05 14:34:35 -08007904 if (app == mHomeProcess) {
7905 mHomeProcess = null;
7906 }
7907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 if (restart) {
7909 // We have components that still need to be running in the
7910 // process, so re-launch it.
7911 mProcessNames.put(app.processName, app.info.uid, app);
7912 startProcessLocked(app, "restart", app.processName);
7913 } else if (app.pid > 0 && app.pid != MY_PID) {
7914 // Goodbye!
7915 synchronized (mPidsSelfLocked) {
7916 mPidsSelfLocked.remove(app.pid);
7917 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
7918 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007919 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007920 }
7921 }
7922
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007923 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
7924 // Look through the content providers we are waiting to have launched,
7925 // and if any run in this process then either schedule a restart of
7926 // the process or kill the client waiting for it if this process has
7927 // gone bad.
7928 int NL = mLaunchingProviders.size();
7929 boolean restart = false;
7930 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007931 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007932 if (cpr.launchingApp == app) {
7933 if (!alwaysBad && !app.bad) {
7934 restart = true;
7935 } else {
7936 removeDyingProviderLocked(app, cpr);
7937 NL = mLaunchingProviders.size();
7938 }
7939 }
7940 }
7941 return restart;
7942 }
7943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007944 // =========================================================
7945 // SERVICES
7946 // =========================================================
7947
7948 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
7949 ActivityManager.RunningServiceInfo info =
7950 new ActivityManager.RunningServiceInfo();
7951 info.service = r.name;
7952 if (r.app != null) {
7953 info.pid = r.app.pid;
7954 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007955 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007956 info.process = r.processName;
7957 info.foreground = r.isForeground;
7958 info.activeSince = r.createTime;
7959 info.started = r.startRequested;
7960 info.clientCount = r.connections.size();
7961 info.crashCount = r.crashCount;
7962 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007963 if (r.isForeground) {
7964 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
7965 }
7966 if (r.startRequested) {
7967 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
7968 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007969 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007970 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
7971 }
7972 if (r.app != null && r.app.persistent) {
7973 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
7974 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007975 for (ConnectionRecord conn : r.connections.values()) {
7976 if (conn.clientLabel != 0) {
7977 info.clientPackage = conn.binding.client.info.packageName;
7978 info.clientLabel = conn.clientLabel;
7979 break;
7980 }
7981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007982 return info;
7983 }
7984
7985 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
7986 int flags) {
7987 synchronized (this) {
7988 ArrayList<ActivityManager.RunningServiceInfo> res
7989 = new ArrayList<ActivityManager.RunningServiceInfo>();
7990
7991 if (mServices.size() > 0) {
7992 Iterator<ServiceRecord> it = mServices.values().iterator();
7993 while (it.hasNext() && res.size() < maxNum) {
7994 res.add(makeRunningServiceInfoLocked(it.next()));
7995 }
7996 }
7997
7998 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
7999 ServiceRecord r = mRestartingServices.get(i);
8000 ActivityManager.RunningServiceInfo info =
8001 makeRunningServiceInfoLocked(r);
8002 info.restarting = r.nextRestartTime;
8003 res.add(info);
8004 }
8005
8006 return res;
8007 }
8008 }
8009
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008010 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8011 synchronized (this) {
8012 ServiceRecord r = mServices.get(name);
8013 if (r != null) {
8014 for (ConnectionRecord conn : r.connections.values()) {
8015 if (conn.clientIntent != null) {
8016 return conn.clientIntent;
8017 }
8018 }
8019 }
8020 }
8021 return null;
8022 }
8023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 private final ServiceRecord findServiceLocked(ComponentName name,
8025 IBinder token) {
8026 ServiceRecord r = mServices.get(name);
8027 return r == token ? r : null;
8028 }
8029
8030 private final class ServiceLookupResult {
8031 final ServiceRecord record;
8032 final String permission;
8033
8034 ServiceLookupResult(ServiceRecord _record, String _permission) {
8035 record = _record;
8036 permission = _permission;
8037 }
8038 };
8039
8040 private ServiceLookupResult findServiceLocked(Intent service,
8041 String resolvedType) {
8042 ServiceRecord r = null;
8043 if (service.getComponent() != null) {
8044 r = mServices.get(service.getComponent());
8045 }
8046 if (r == null) {
8047 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8048 r = mServicesByIntent.get(filter);
8049 }
8050
8051 if (r == null) {
8052 try {
8053 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008054 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008055 service, resolvedType, 0);
8056 ServiceInfo sInfo =
8057 rInfo != null ? rInfo.serviceInfo : null;
8058 if (sInfo == null) {
8059 return null;
8060 }
8061
8062 ComponentName name = new ComponentName(
8063 sInfo.applicationInfo.packageName, sInfo.name);
8064 r = mServices.get(name);
8065 } catch (RemoteException ex) {
8066 // pm is in same process, this will never happen.
8067 }
8068 }
8069 if (r != null) {
8070 int callingPid = Binder.getCallingPid();
8071 int callingUid = Binder.getCallingUid();
8072 if (checkComponentPermission(r.permission,
8073 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8074 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008075 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008076 + " from pid=" + callingPid
8077 + ", uid=" + callingUid
8078 + " requires " + r.permission);
8079 return new ServiceLookupResult(null, r.permission);
8080 }
8081 return new ServiceLookupResult(r, null);
8082 }
8083 return null;
8084 }
8085
8086 private class ServiceRestarter implements Runnable {
8087 private ServiceRecord mService;
8088
8089 void setService(ServiceRecord service) {
8090 mService = service;
8091 }
8092
8093 public void run() {
8094 synchronized(ActivityManagerService.this) {
8095 performServiceRestartLocked(mService);
8096 }
8097 }
8098 }
8099
8100 private ServiceLookupResult retrieveServiceLocked(Intent service,
8101 String resolvedType, int callingPid, int callingUid) {
8102 ServiceRecord r = null;
8103 if (service.getComponent() != null) {
8104 r = mServices.get(service.getComponent());
8105 }
8106 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8107 r = mServicesByIntent.get(filter);
8108 if (r == null) {
8109 try {
8110 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008111 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008112 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113 ServiceInfo sInfo =
8114 rInfo != null ? rInfo.serviceInfo : null;
8115 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008116 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 ": not found");
8118 return null;
8119 }
8120
8121 ComponentName name = new ComponentName(
8122 sInfo.applicationInfo.packageName, sInfo.name);
8123 r = mServices.get(name);
8124 if (r == null) {
8125 filter = new Intent.FilterComparison(service.cloneFilter());
8126 ServiceRestarter res = new ServiceRestarter();
8127 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8128 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8129 synchronized (stats) {
8130 ss = stats.getServiceStatsLocked(
8131 sInfo.applicationInfo.uid, sInfo.packageName,
8132 sInfo.name);
8133 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008134 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008135 res.setService(r);
8136 mServices.put(name, r);
8137 mServicesByIntent.put(filter, r);
8138
8139 // Make sure this component isn't in the pending list.
8140 int N = mPendingServices.size();
8141 for (int i=0; i<N; i++) {
8142 ServiceRecord pr = mPendingServices.get(i);
8143 if (pr.name.equals(name)) {
8144 mPendingServices.remove(i);
8145 i--;
8146 N--;
8147 }
8148 }
8149 }
8150 } catch (RemoteException ex) {
8151 // pm is in same process, this will never happen.
8152 }
8153 }
8154 if (r != null) {
8155 if (checkComponentPermission(r.permission,
8156 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8157 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008158 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159 + " from pid=" + Binder.getCallingPid()
8160 + ", uid=" + Binder.getCallingUid()
8161 + " requires " + r.permission);
8162 return new ServiceLookupResult(null, r.permission);
8163 }
8164 return new ServiceLookupResult(r, null);
8165 }
8166 return null;
8167 }
8168
8169 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8170 long now = SystemClock.uptimeMillis();
8171 if (r.executeNesting == 0 && r.app != null) {
8172 if (r.app.executingServices.size() == 0) {
8173 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8174 msg.obj = r.app;
8175 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8176 }
8177 r.app.executingServices.add(r);
8178 }
8179 r.executeNesting++;
8180 r.executingStart = now;
8181 }
8182
8183 private final void sendServiceArgsLocked(ServiceRecord r,
8184 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008185 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008186 if (N == 0) {
8187 return;
8188 }
8189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 int i = 0;
8191 while (i < N) {
8192 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008193 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008194 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008195 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -07008196 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008197 // If somehow we got a dummy start at the front, then
8198 // just drop it here.
8199 i++;
8200 continue;
8201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 bumpServiceExecutingLocked(r);
8203 if (!oomAdjusted) {
8204 oomAdjusted = true;
8205 updateOomAdjLocked(r.app);
8206 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008207 int flags = 0;
8208 if (si.deliveryCount > 0) {
8209 flags |= Service.START_FLAG_RETRY;
8210 }
8211 if (si.doneExecutingCount > 0) {
8212 flags |= Service.START_FLAG_REDELIVERY;
8213 }
8214 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
8215 si.deliveredTime = SystemClock.uptimeMillis();
8216 r.deliveredStarts.add(si);
8217 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008219 } catch (RemoteException e) {
8220 // Remote process gone... we'll let the normal cleanup take
8221 // care of this.
8222 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008224 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008225 break;
8226 }
8227 }
8228 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008229 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008230 } else {
8231 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008232 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008233 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008234 }
8235 }
8236 }
8237
8238 private final boolean requestServiceBindingLocked(ServiceRecord r,
8239 IntentBindRecord i, boolean rebind) {
8240 if (r.app == null || r.app.thread == null) {
8241 // If service is not currently running, can't yet bind.
8242 return false;
8243 }
8244 if ((!i.requested || rebind) && i.apps.size() > 0) {
8245 try {
8246 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008247 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008248 + ": shouldUnbind=" + i.hasBound);
8249 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8250 if (!rebind) {
8251 i.requested = true;
8252 }
8253 i.hasBound = true;
8254 i.doRebind = false;
8255 } catch (RemoteException e) {
8256 return false;
8257 }
8258 }
8259 return true;
8260 }
8261
8262 private final void requestServiceBindingsLocked(ServiceRecord r) {
8263 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8264 while (bindings.hasNext()) {
8265 IntentBindRecord i = bindings.next();
8266 if (!requestServiceBindingLocked(r, i, false)) {
8267 break;
8268 }
8269 }
8270 }
8271
8272 private final void realStartServiceLocked(ServiceRecord r,
8273 ProcessRecord app) throws RemoteException {
8274 if (app.thread == null) {
8275 throw new RemoteException();
8276 }
8277
8278 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008279 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280
8281 app.services.add(r);
8282 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008283 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284
8285 boolean created = false;
8286 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008287 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008288 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008289 mStringBuilder.setLength(0);
8290 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008291 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008292 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008293 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008294 synchronized (r.stats.getBatteryStats()) {
8295 r.stats.startLaunchedLocked();
8296 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008297 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008298 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008299 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008300 created = true;
8301 } finally {
8302 if (!created) {
8303 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008304 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008305 }
8306 }
8307
8308 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008309
8310 // If the service is in the started state, and there are no
8311 // pending arguments, then fake up one so its onStartCommand() will
8312 // be called.
8313 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8314 r.lastStartId++;
8315 if (r.lastStartId < 1) {
8316 r.lastStartId = 1;
8317 }
8318 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
8319 }
8320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008321 sendServiceArgsLocked(r, true);
8322 }
8323
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008324 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8325 boolean allowCancel) {
8326 boolean canceled = false;
8327
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008328 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008329 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008330 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008331
8332 // Any delivered but not yet finished starts should be put back
8333 // on the pending list.
8334 final int N = r.deliveredStarts.size();
8335 if (N > 0) {
8336 for (int i=N-1; i>=0; i--) {
8337 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
8338 if (si.intent == null) {
8339 // We'll generate this again if needed.
8340 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8341 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8342 r.pendingStarts.add(0, si);
8343 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8344 dur *= 2;
8345 if (minDuration < dur) minDuration = dur;
8346 if (resetTime < dur) resetTime = dur;
8347 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008348 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008349 + r.name);
8350 canceled = true;
8351 }
8352 }
8353 r.deliveredStarts.clear();
8354 }
8355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008356 r.totalRestartCount++;
8357 if (r.restartDelay == 0) {
8358 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008359 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008360 } else {
8361 // If it has been a "reasonably long time" since the service
8362 // was started, then reset our restart duration back to
8363 // the beginning, so we don't infinitely increase the duration
8364 // on a service that just occasionally gets killed (which is
8365 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008366 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008367 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008368 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008369 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008370 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008371 if (r.restartDelay < minDuration) {
8372 r.restartDelay = minDuration;
8373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008374 }
8375 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008376
8377 r.nextRestartTime = now + r.restartDelay;
8378
8379 // Make sure that we don't end up restarting a bunch of services
8380 // all at the same time.
8381 boolean repeat;
8382 do {
8383 repeat = false;
8384 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8385 ServiceRecord r2 = mRestartingServices.get(i);
8386 if (r2 != r && r.nextRestartTime
8387 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8388 && r.nextRestartTime
8389 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8390 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8391 r.restartDelay = r.nextRestartTime - now;
8392 repeat = true;
8393 break;
8394 }
8395 }
8396 } while (repeat);
8397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 if (!mRestartingServices.contains(r)) {
8399 mRestartingServices.add(r);
8400 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008401
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008402 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008404 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008405 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008406 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008407 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008408 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008409 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410 r.shortName, r.restartDelay);
8411
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008412 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008413 }
8414
8415 final void performServiceRestartLocked(ServiceRecord r) {
8416 if (!mRestartingServices.contains(r)) {
8417 return;
8418 }
8419 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8420 }
8421
8422 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8423 if (r.restartDelay == 0) {
8424 return false;
8425 }
8426 r.resetRestartCounter();
8427 mRestartingServices.remove(r);
8428 mHandler.removeCallbacks(r.restarter);
8429 return true;
8430 }
8431
8432 private final boolean bringUpServiceLocked(ServiceRecord r,
8433 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008434 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008435 //r.dump(" ");
8436
Dianne Hackborn36124872009-10-08 16:22:03 -07008437 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008438 sendServiceArgsLocked(r, false);
8439 return true;
8440 }
8441
8442 if (!whileRestarting && r.restartDelay > 0) {
8443 // If waiting for a restart, then do nothing.
8444 return true;
8445 }
8446
Joe Onorato8a9b2202010-02-26 18:56:32 -08008447 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008448 + " " + r.intent);
8449
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008450 // We are now bringing the service up, so no longer in the
8451 // restarting state.
8452 mRestartingServices.remove(r);
8453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008454 final String appName = r.processName;
8455 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8456 if (app != null && app.thread != null) {
8457 try {
8458 realStartServiceLocked(r, app);
8459 return true;
8460 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008461 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008462 }
8463
8464 // If a dead object exception was thrown -- fall through to
8465 // restart the application.
8466 }
8467
Dianne Hackborn36124872009-10-08 16:22:03 -07008468 // Not running -- get it started, and enqueue this service record
8469 // to be executed when the app comes up.
8470 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8471 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008472 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008473 + r.appInfo.packageName + "/"
8474 + r.appInfo.uid + " for service "
8475 + r.intent.getIntent() + ": process is bad");
8476 bringDownServiceLocked(r, true);
8477 return false;
8478 }
8479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008480 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008481 mPendingServices.add(r);
8482 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008484 return true;
8485 }
8486
8487 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008488 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008489 //r.dump(" ");
8490
8491 // Does it still need to run?
8492 if (!force && r.startRequested) {
8493 return;
8494 }
8495 if (r.connections.size() > 0) {
8496 if (!force) {
8497 // XXX should probably keep a count of the number of auto-create
8498 // connections directly in the service.
8499 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8500 while (it.hasNext()) {
8501 ConnectionRecord cr = it.next();
8502 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
8503 return;
8504 }
8505 }
8506 }
8507
8508 // Report to all of the connections that the service is no longer
8509 // available.
8510 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8511 while (it.hasNext()) {
8512 ConnectionRecord c = it.next();
8513 try {
8514 // todo: shouldn't be a synchronous call!
8515 c.conn.connected(r.name, null);
8516 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008517 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 " to connection " + c.conn.asBinder() +
8519 " (in " + c.binding.client.processName + ")", e);
8520 }
8521 }
8522 }
8523
8524 // Tell the service that it has been unbound.
8525 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8526 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8527 while (it.hasNext()) {
8528 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008529 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008530 + ": hasBound=" + ibr.hasBound);
8531 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8532 try {
8533 bumpServiceExecutingLocked(r);
8534 updateOomAdjLocked(r.app);
8535 ibr.hasBound = false;
8536 r.app.thread.scheduleUnbindService(r,
8537 ibr.intent.getIntent());
8538 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008539 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 + r.shortName, e);
8541 serviceDoneExecutingLocked(r, true);
8542 }
8543 }
8544 }
8545 }
8546
Joe Onorato8a9b2202010-02-26 18:56:32 -08008547 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008549 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550 System.identityHashCode(r), r.shortName,
8551 (r.app != null) ? r.app.pid : -1);
8552
8553 mServices.remove(r.name);
8554 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008555 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008556 r.totalRestartCount = 0;
8557 unscheduleServiceRestartLocked(r);
8558
8559 // Also make sure it is not on the pending list.
8560 int N = mPendingServices.size();
8561 for (int i=0; i<N; i++) {
8562 if (mPendingServices.get(i) == r) {
8563 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008564 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008565 TAG, "Removed pending service: " + r.shortName);
8566 i--;
8567 N--;
8568 }
8569 }
8570
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008571 r.cancelNotification();
8572 r.isForeground = false;
8573 r.foregroundId = 0;
8574 r.foregroundNoti = null;
8575
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008576 // Clear start entries.
8577 r.deliveredStarts.clear();
8578 r.pendingStarts.clear();
8579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008580 if (r.app != null) {
8581 synchronized (r.stats.getBatteryStats()) {
8582 r.stats.stopLaunchedLocked();
8583 }
8584 r.app.services.remove(r);
8585 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008587 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008588 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008589 bumpServiceExecutingLocked(r);
8590 mStoppingServices.add(r);
8591 updateOomAdjLocked(r.app);
8592 r.app.thread.scheduleStopService(r);
8593 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008594 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008595 + r.shortName, e);
8596 serviceDoneExecutingLocked(r, true);
8597 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008598 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008600 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008601 TAG, "Removed service that has no process: " + r.shortName);
8602 }
8603 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008604 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008605 TAG, "Removed service that is not running: " + r.shortName);
8606 }
8607 }
8608
8609 ComponentName startServiceLocked(IApplicationThread caller,
8610 Intent service, String resolvedType,
8611 int callingPid, int callingUid) {
8612 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008613 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 + " type=" + resolvedType + " args=" + service.getExtras());
8615
8616 if (caller != null) {
8617 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8618 if (callerApp == null) {
8619 throw new SecurityException(
8620 "Unable to find app for caller " + caller
8621 + " (pid=" + Binder.getCallingPid()
8622 + ") when starting service " + service);
8623 }
8624 }
8625
8626 ServiceLookupResult res =
8627 retrieveServiceLocked(service, resolvedType,
8628 callingPid, callingUid);
8629 if (res == null) {
8630 return null;
8631 }
8632 if (res.record == null) {
8633 return new ComponentName("!", res.permission != null
8634 ? res.permission : "private to package");
8635 }
8636 ServiceRecord r = res.record;
8637 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008638 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 + r.shortName);
8640 }
8641 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008642 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 r.lastStartId++;
8644 if (r.lastStartId < 1) {
8645 r.lastStartId = 1;
8646 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008647 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008648 r.lastActivity = SystemClock.uptimeMillis();
8649 synchronized (r.stats.getBatteryStats()) {
8650 r.stats.startRunningLocked();
8651 }
8652 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8653 return new ComponentName("!", "Service process is bad");
8654 }
8655 return r.name;
8656 }
8657 }
8658
8659 public ComponentName startService(IApplicationThread caller, Intent service,
8660 String resolvedType) {
8661 // Refuse possible leaked file descriptors
8662 if (service != null && service.hasFileDescriptors() == true) {
8663 throw new IllegalArgumentException("File descriptors passed in Intent");
8664 }
8665
8666 synchronized(this) {
8667 final int callingPid = Binder.getCallingPid();
8668 final int callingUid = Binder.getCallingUid();
8669 final long origId = Binder.clearCallingIdentity();
8670 ComponentName res = startServiceLocked(caller, service,
8671 resolvedType, callingPid, callingUid);
8672 Binder.restoreCallingIdentity(origId);
8673 return res;
8674 }
8675 }
8676
8677 ComponentName startServiceInPackage(int uid,
8678 Intent service, String resolvedType) {
8679 synchronized(this) {
8680 final long origId = Binder.clearCallingIdentity();
8681 ComponentName res = startServiceLocked(null, service,
8682 resolvedType, -1, uid);
8683 Binder.restoreCallingIdentity(origId);
8684 return res;
8685 }
8686 }
8687
8688 public int stopService(IApplicationThread caller, Intent service,
8689 String resolvedType) {
8690 // Refuse possible leaked file descriptors
8691 if (service != null && service.hasFileDescriptors() == true) {
8692 throw new IllegalArgumentException("File descriptors passed in Intent");
8693 }
8694
8695 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008696 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 + " type=" + resolvedType);
8698
8699 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8700 if (caller != null && callerApp == null) {
8701 throw new SecurityException(
8702 "Unable to find app for caller " + caller
8703 + " (pid=" + Binder.getCallingPid()
8704 + ") when stopping service " + service);
8705 }
8706
8707 // If this service is active, make sure it is stopped.
8708 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8709 if (r != null) {
8710 if (r.record != null) {
8711 synchronized (r.record.stats.getBatteryStats()) {
8712 r.record.stats.stopRunningLocked();
8713 }
8714 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008715 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008716 final long origId = Binder.clearCallingIdentity();
8717 bringDownServiceLocked(r.record, false);
8718 Binder.restoreCallingIdentity(origId);
8719 return 1;
8720 }
8721 return -1;
8722 }
8723 }
8724
8725 return 0;
8726 }
8727
8728 public IBinder peekService(Intent service, String resolvedType) {
8729 // Refuse possible leaked file descriptors
8730 if (service != null && service.hasFileDescriptors() == true) {
8731 throw new IllegalArgumentException("File descriptors passed in Intent");
8732 }
8733
8734 IBinder ret = null;
8735
8736 synchronized(this) {
8737 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8738
8739 if (r != null) {
8740 // r.record is null if findServiceLocked() failed the caller permission check
8741 if (r.record == null) {
8742 throw new SecurityException(
8743 "Permission Denial: Accessing service " + r.record.name
8744 + " from pid=" + Binder.getCallingPid()
8745 + ", uid=" + Binder.getCallingUid()
8746 + " requires " + r.permission);
8747 }
8748 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8749 if (ib != null) {
8750 ret = ib.binder;
8751 }
8752 }
8753 }
8754
8755 return ret;
8756 }
8757
8758 public boolean stopServiceToken(ComponentName className, IBinder token,
8759 int startId) {
8760 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008761 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008762 + " " + token + " startId=" + startId);
8763 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008764 if (r != null) {
8765 if (startId >= 0) {
8766 // Asked to only stop if done with all work. Note that
8767 // to avoid leaks, we will take this as dropping all
8768 // start items up to and including this one.
8769 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8770 if (si != null) {
8771 while (r.deliveredStarts.size() > 0) {
8772 if (r.deliveredStarts.remove(0) == si) {
8773 break;
8774 }
8775 }
8776 }
8777
8778 if (r.lastStartId != startId) {
8779 return false;
8780 }
8781
8782 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008783 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008784 + " is last, but have " + r.deliveredStarts.size()
8785 + " remaining args");
8786 }
8787 }
8788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008789 synchronized (r.stats.getBatteryStats()) {
8790 r.stats.stopRunningLocked();
8791 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008792 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008793 }
8794 final long origId = Binder.clearCallingIdentity();
8795 bringDownServiceLocked(r, false);
8796 Binder.restoreCallingIdentity(origId);
8797 return true;
8798 }
8799 }
8800 return false;
8801 }
8802
8803 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008804 int id, Notification notification, boolean removeNotification) {
8805 final long origId = Binder.clearCallingIdentity();
8806 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 synchronized(this) {
8808 ServiceRecord r = findServiceLocked(className, token);
8809 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008810 if (id != 0) {
8811 if (notification == null) {
8812 throw new IllegalArgumentException("null notification");
8813 }
8814 if (r.foregroundId != id) {
8815 r.cancelNotification();
8816 r.foregroundId = id;
8817 }
8818 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8819 r.foregroundNoti = notification;
8820 r.isForeground = true;
8821 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008822 if (r.app != null) {
8823 updateServiceForegroundLocked(r.app, true);
8824 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008825 } else {
8826 if (r.isForeground) {
8827 r.isForeground = false;
8828 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008829 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008830 updateServiceForegroundLocked(r.app, true);
8831 }
8832 }
8833 if (removeNotification) {
8834 r.cancelNotification();
8835 r.foregroundId = 0;
8836 r.foregroundNoti = null;
8837 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 }
8839 }
8840 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008841 } finally {
8842 Binder.restoreCallingIdentity(origId);
8843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 }
8845
8846 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8847 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008848 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 if (sr.isForeground) {
8850 anyForeground = true;
8851 break;
8852 }
8853 }
8854 if (anyForeground != proc.foregroundServices) {
8855 proc.foregroundServices = anyForeground;
8856 if (oomAdj) {
8857 updateOomAdjLocked();
8858 }
8859 }
8860 }
8861
8862 public int bindService(IApplicationThread caller, IBinder token,
8863 Intent service, String resolvedType,
8864 IServiceConnection connection, int flags) {
8865 // Refuse possible leaked file descriptors
8866 if (service != null && service.hasFileDescriptors() == true) {
8867 throw new IllegalArgumentException("File descriptors passed in Intent");
8868 }
8869
8870 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008871 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008872 + " type=" + resolvedType + " conn=" + connection.asBinder()
8873 + " flags=0x" + Integer.toHexString(flags));
8874 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8875 if (callerApp == null) {
8876 throw new SecurityException(
8877 "Unable to find app for caller " + caller
8878 + " (pid=" + Binder.getCallingPid()
8879 + ") when binding service " + service);
8880 }
8881
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008882 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008883 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008884 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008885 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008886 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 return 0;
8888 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008889 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 }
8891
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008892 int clientLabel = 0;
8893 PendingIntent clientIntent = null;
8894
8895 if (callerApp.info.uid == Process.SYSTEM_UID) {
8896 // Hacky kind of thing -- allow system stuff to tell us
8897 // what they are, so we can report this elsewhere for
8898 // others to know why certain services are running.
8899 try {
8900 clientIntent = (PendingIntent)service.getParcelableExtra(
8901 Intent.EXTRA_CLIENT_INTENT);
8902 } catch (RuntimeException e) {
8903 }
8904 if (clientIntent != null) {
8905 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
8906 if (clientLabel != 0) {
8907 // There are no useful extras in the intent, trash them.
8908 // System code calling with this stuff just needs to know
8909 // this will happen.
8910 service = service.cloneFilter();
8911 }
8912 }
8913 }
8914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008915 ServiceLookupResult res =
8916 retrieveServiceLocked(service, resolvedType,
8917 Binder.getCallingPid(), Binder.getCallingUid());
8918 if (res == null) {
8919 return 0;
8920 }
8921 if (res.record == null) {
8922 return -1;
8923 }
8924 ServiceRecord s = res.record;
8925
8926 final long origId = Binder.clearCallingIdentity();
8927
8928 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008929 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008930 + s.shortName);
8931 }
8932
8933 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
8934 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008935 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008936
8937 IBinder binder = connection.asBinder();
8938 s.connections.put(binder, c);
8939 b.connections.add(c);
8940 if (activity != null) {
8941 if (activity.connections == null) {
8942 activity.connections = new HashSet<ConnectionRecord>();
8943 }
8944 activity.connections.add(c);
8945 }
8946 b.client.connections.add(c);
8947 mServiceConnections.put(binder, c);
8948
8949 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
8950 s.lastActivity = SystemClock.uptimeMillis();
8951 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
8952 return 0;
8953 }
8954 }
8955
8956 if (s.app != null) {
8957 // This could have made the service more important.
8958 updateOomAdjLocked(s.app);
8959 }
8960
Joe Onorato8a9b2202010-02-26 18:56:32 -08008961 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 + ": received=" + b.intent.received
8963 + " apps=" + b.intent.apps.size()
8964 + " doRebind=" + b.intent.doRebind);
8965
8966 if (s.app != null && b.intent.received) {
8967 // Service is already running, so we can immediately
8968 // publish the connection.
8969 try {
8970 c.conn.connected(s.name, b.intent.binder);
8971 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008972 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 + " to connection " + c.conn.asBinder()
8974 + " (in " + c.binding.client.processName + ")", e);
8975 }
8976
8977 // If this is the first app connected back to this binding,
8978 // and the service had previously asked to be told when
8979 // rebound, then do so.
8980 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
8981 requestServiceBindingLocked(s, b.intent, true);
8982 }
8983 } else if (!b.intent.requested) {
8984 requestServiceBindingLocked(s, b.intent, false);
8985 }
8986
8987 Binder.restoreCallingIdentity(origId);
8988 }
8989
8990 return 1;
8991 }
8992
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008993 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008994 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008995 IBinder binder = c.conn.asBinder();
8996 AppBindRecord b = c.binding;
8997 ServiceRecord s = b.service;
8998 s.connections.remove(binder);
8999 b.connections.remove(c);
9000 if (c.activity != null && c.activity != skipAct) {
9001 if (c.activity.connections != null) {
9002 c.activity.connections.remove(c);
9003 }
9004 }
9005 if (b.client != skipApp) {
9006 b.client.connections.remove(c);
9007 }
9008 mServiceConnections.remove(binder);
9009
9010 if (b.connections.size() == 0) {
9011 b.intent.apps.remove(b.client);
9012 }
9013
Joe Onorato8a9b2202010-02-26 18:56:32 -08009014 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009015 + ": shouldUnbind=" + b.intent.hasBound);
9016 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9017 && b.intent.hasBound) {
9018 try {
9019 bumpServiceExecutingLocked(s);
9020 updateOomAdjLocked(s.app);
9021 b.intent.hasBound = false;
9022 // Assume the client doesn't want to know about a rebind;
9023 // we will deal with that later if it asks for one.
9024 b.intent.doRebind = false;
9025 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9026 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009027 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009028 serviceDoneExecutingLocked(s, true);
9029 }
9030 }
9031
9032 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9033 bringDownServiceLocked(s, false);
9034 }
9035 }
9036
9037 public boolean unbindService(IServiceConnection connection) {
9038 synchronized (this) {
9039 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009040 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 ConnectionRecord r = mServiceConnections.get(binder);
9042 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009043 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 + connection.asBinder());
9045 return false;
9046 }
9047
9048 final long origId = Binder.clearCallingIdentity();
9049
9050 removeConnectionLocked(r, null, null);
9051
9052 if (r.binding.service.app != null) {
9053 // This could have made the service less important.
9054 updateOomAdjLocked(r.binding.service.app);
9055 }
9056
9057 Binder.restoreCallingIdentity(origId);
9058 }
9059
9060 return true;
9061 }
9062
9063 public void publishService(IBinder token, Intent intent, IBinder service) {
9064 // Refuse possible leaked file descriptors
9065 if (intent != null && intent.hasFileDescriptors() == true) {
9066 throw new IllegalArgumentException("File descriptors passed in Intent");
9067 }
9068
9069 synchronized(this) {
9070 if (!(token instanceof ServiceRecord)) {
9071 throw new IllegalArgumentException("Invalid service token");
9072 }
9073 ServiceRecord r = (ServiceRecord)token;
9074
9075 final long origId = Binder.clearCallingIdentity();
9076
Joe Onorato8a9b2202010-02-26 18:56:32 -08009077 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009078 + " " + intent + ": " + service);
9079 if (r != null) {
9080 Intent.FilterComparison filter
9081 = new Intent.FilterComparison(intent);
9082 IntentBindRecord b = r.bindings.get(filter);
9083 if (b != null && !b.received) {
9084 b.binder = service;
9085 b.requested = true;
9086 b.received = true;
9087 if (r.connections.size() > 0) {
9088 Iterator<ConnectionRecord> it
9089 = r.connections.values().iterator();
9090 while (it.hasNext()) {
9091 ConnectionRecord c = it.next();
9092 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009093 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009094 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009095 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009096 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009097 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098 TAG, "Published intent: " + intent);
9099 continue;
9100 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009101 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102 try {
9103 c.conn.connected(r.name, service);
9104 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009105 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009106 " to connection " + c.conn.asBinder() +
9107 " (in " + c.binding.client.processName + ")", e);
9108 }
9109 }
9110 }
9111 }
9112
9113 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9114
9115 Binder.restoreCallingIdentity(origId);
9116 }
9117 }
9118 }
9119
9120 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9121 // Refuse possible leaked file descriptors
9122 if (intent != null && intent.hasFileDescriptors() == true) {
9123 throw new IllegalArgumentException("File descriptors passed in Intent");
9124 }
9125
9126 synchronized(this) {
9127 if (!(token instanceof ServiceRecord)) {
9128 throw new IllegalArgumentException("Invalid service token");
9129 }
9130 ServiceRecord r = (ServiceRecord)token;
9131
9132 final long origId = Binder.clearCallingIdentity();
9133
9134 if (r != null) {
9135 Intent.FilterComparison filter
9136 = new Intent.FilterComparison(intent);
9137 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009138 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009139 + " at " + b + ": apps="
9140 + (b != null ? b.apps.size() : 0));
9141 if (b != null) {
9142 if (b.apps.size() > 0) {
9143 // Applications have already bound since the last
9144 // unbind, so just rebind right here.
9145 requestServiceBindingLocked(r, b, true);
9146 } else {
9147 // Note to tell the service the next time there is
9148 // a new client.
9149 b.doRebind = true;
9150 }
9151 }
9152
9153 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9154
9155 Binder.restoreCallingIdentity(origId);
9156 }
9157 }
9158 }
9159
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009160 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009161 synchronized(this) {
9162 if (!(token instanceof ServiceRecord)) {
9163 throw new IllegalArgumentException("Invalid service token");
9164 }
9165 ServiceRecord r = (ServiceRecord)token;
9166 boolean inStopping = mStoppingServices.contains(token);
9167 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009168 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009169 + ": nesting=" + r.executeNesting
9170 + ", inStopping=" + inStopping);
9171 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009172 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 + " with incorrect token: given " + token
9174 + ", expected " + r);
9175 return;
9176 }
9177
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009178 if (type == 1) {
9179 // This is a call from a service start... take care of
9180 // book-keeping.
9181 r.callStart = true;
9182 switch (res) {
9183 case Service.START_STICKY_COMPATIBILITY:
9184 case Service.START_STICKY: {
9185 // We are done with the associated start arguments.
9186 r.findDeliveredStart(startId, true);
9187 // Don't stop if killed.
9188 r.stopIfKilled = false;
9189 break;
9190 }
9191 case Service.START_NOT_STICKY: {
9192 // We are done with the associated start arguments.
9193 r.findDeliveredStart(startId, true);
9194 if (r.lastStartId == startId) {
9195 // There is no more work, and this service
9196 // doesn't want to hang around if killed.
9197 r.stopIfKilled = true;
9198 }
9199 break;
9200 }
9201 case Service.START_REDELIVER_INTENT: {
9202 // We'll keep this item until they explicitly
9203 // call stop for it, but keep track of the fact
9204 // that it was delivered.
9205 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9206 if (si != null) {
9207 si.deliveryCount = 0;
9208 si.doneExecutingCount++;
9209 // Don't stop if killed.
9210 r.stopIfKilled = true;
9211 }
9212 break;
9213 }
9214 default:
9215 throw new IllegalArgumentException(
9216 "Unknown service start result: " + res);
9217 }
9218 if (res == Service.START_STICKY_COMPATIBILITY) {
9219 r.callStart = false;
9220 }
9221 }
9222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009223 final long origId = Binder.clearCallingIdentity();
9224 serviceDoneExecutingLocked(r, inStopping);
9225 Binder.restoreCallingIdentity(origId);
9226 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009227 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009228 + " with token " + token);
9229 }
9230 }
9231 }
9232
9233 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9234 r.executeNesting--;
9235 if (r.executeNesting <= 0 && r.app != null) {
9236 r.app.executingServices.remove(r);
9237 if (r.app.executingServices.size() == 0) {
9238 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9239 }
9240 if (inStopping) {
9241 mStoppingServices.remove(r);
9242 }
9243 updateOomAdjLocked(r.app);
9244 }
9245 }
9246
9247 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009248 String anrMessage = null;
9249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 synchronized(this) {
9251 if (proc.executingServices.size() == 0 || proc.thread == null) {
9252 return;
9253 }
9254 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9255 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9256 ServiceRecord timeout = null;
9257 long nextTime = 0;
9258 while (it.hasNext()) {
9259 ServiceRecord sr = it.next();
9260 if (sr.executingStart < maxTime) {
9261 timeout = sr;
9262 break;
9263 }
9264 if (sr.executingStart > nextTime) {
9265 nextTime = sr.executingStart;
9266 }
9267 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009268 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009269 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009270 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 } else {
9272 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9273 msg.obj = proc;
9274 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9275 }
9276 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009277
9278 if (anrMessage != null) {
9279 appNotResponding(proc, null, null, anrMessage);
9280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009281 }
9282
9283 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009284 // BACKUP AND RESTORE
9285 // =========================================================
9286
9287 // Cause the target app to be launched if necessary and its backup agent
9288 // instantiated. The backup agent will invoke backupAgentCreated() on the
9289 // activity manager to announce its creation.
9290 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009291 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009292 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9293
9294 synchronized(this) {
9295 // !!! TODO: currently no check here that we're already bound
9296 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9297 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9298 synchronized (stats) {
9299 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9300 }
9301
9302 BackupRecord r = new BackupRecord(ss, app, backupMode);
9303 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9304 // startProcessLocked() returns existing proc's record if it's already running
9305 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009306 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009307 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009308 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009309 return false;
9310 }
9311
9312 r.app = proc;
9313 mBackupTarget = r;
9314 mBackupAppName = app.packageName;
9315
Christopher Tate6fa95972009-06-05 18:43:55 -07009316 // Try not to kill the process during backup
9317 updateOomAdjLocked(proc);
9318
Christopher Tate181fafa2009-05-14 11:12:14 -07009319 // If the process is already attached, schedule the creation of the backup agent now.
9320 // If it is not yet live, this will be done when it attaches to the framework.
9321 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009322 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009323 try {
9324 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9325 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009326 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009327 }
9328 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009329 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009330 }
9331 // Invariants: at this point, the target app process exists and the application
9332 // is either already running or in the process of coming up. mBackupTarget and
9333 // mBackupAppName describe the app, so that when it binds back to the AM we
9334 // know that it's scheduled for a backup-agent operation.
9335 }
9336
9337 return true;
9338 }
9339
9340 // A backup agent has just come up
9341 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009342 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009343 + " = " + agent);
9344
9345 synchronized(this) {
9346 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009347 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009348 return;
9349 }
9350
Christopher Tate043dadc2009-06-02 16:11:00 -07009351 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009352 try {
9353 IBackupManager bm = IBackupManager.Stub.asInterface(
9354 ServiceManager.getService(Context.BACKUP_SERVICE));
9355 bm.agentConnected(agentPackageName, agent);
9356 } catch (RemoteException e) {
9357 // can't happen; the backup manager service is local
9358 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009359 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009360 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009361 } finally {
9362 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009363 }
9364 }
9365 }
9366
9367 // done with this agent
9368 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009369 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009370 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009371 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009372 return;
9373 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009374
9375 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009376 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009377 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009378 return;
9379 }
9380
Christopher Tate181fafa2009-05-14 11:12:14 -07009381 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009382 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009383 return;
9384 }
9385
Christopher Tate6fa95972009-06-05 18:43:55 -07009386 ProcessRecord proc = mBackupTarget.app;
9387 mBackupTarget = null;
9388 mBackupAppName = null;
9389
9390 // Not backing this app up any more; reset its OOM adjustment
9391 updateOomAdjLocked(proc);
9392
Christopher Tatec7b31e32009-06-10 15:49:30 -07009393 // If the app crashed during backup, 'thread' will be null here
9394 if (proc.thread != null) {
9395 try {
9396 proc.thread.scheduleDestroyBackupAgent(appInfo);
9397 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009398 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009399 e.printStackTrace();
9400 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009401 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009402 }
9403 }
9404 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009405 // BROADCASTS
9406 // =========================================================
9407
Josh Bartel7f208742010-02-25 11:01:44 -06009408 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009409 List cur) {
9410 final ContentResolver resolver = mContext.getContentResolver();
9411 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9412 if (list == null) {
9413 return cur;
9414 }
9415 int N = list.size();
9416 for (int i=0; i<N; i++) {
9417 Intent intent = list.get(i);
9418 if (filter.match(resolver, intent, true, TAG) >= 0) {
9419 if (cur == null) {
9420 cur = new ArrayList<Intent>();
9421 }
9422 cur.add(intent);
9423 }
9424 }
9425 return cur;
9426 }
9427
9428 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009429 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009430 + mBroadcastsScheduled);
9431
9432 if (mBroadcastsScheduled) {
9433 return;
9434 }
9435 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9436 mBroadcastsScheduled = true;
9437 }
9438
9439 public Intent registerReceiver(IApplicationThread caller,
9440 IIntentReceiver receiver, IntentFilter filter, String permission) {
9441 synchronized(this) {
9442 ProcessRecord callerApp = null;
9443 if (caller != null) {
9444 callerApp = getRecordForAppLocked(caller);
9445 if (callerApp == null) {
9446 throw new SecurityException(
9447 "Unable to find app for caller " + caller
9448 + " (pid=" + Binder.getCallingPid()
9449 + ") when registering receiver " + receiver);
9450 }
9451 }
9452
9453 List allSticky = null;
9454
9455 // Look for any matching sticky broadcasts...
9456 Iterator actions = filter.actionsIterator();
9457 if (actions != null) {
9458 while (actions.hasNext()) {
9459 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009460 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461 }
9462 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009463 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009464 }
9465
9466 // The first sticky in the list is returned directly back to
9467 // the client.
9468 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9469
Joe Onorato8a9b2202010-02-26 18:56:32 -08009470 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 + ": " + sticky);
9472
9473 if (receiver == null) {
9474 return sticky;
9475 }
9476
9477 ReceiverList rl
9478 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9479 if (rl == null) {
9480 rl = new ReceiverList(this, callerApp,
9481 Binder.getCallingPid(),
9482 Binder.getCallingUid(), receiver);
9483 if (rl.app != null) {
9484 rl.app.receivers.add(rl);
9485 } else {
9486 try {
9487 receiver.asBinder().linkToDeath(rl, 0);
9488 } catch (RemoteException e) {
9489 return sticky;
9490 }
9491 rl.linkedToDeath = true;
9492 }
9493 mRegisteredReceivers.put(receiver.asBinder(), rl);
9494 }
9495 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9496 rl.add(bf);
9497 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009498 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009499 }
9500 mReceiverResolver.addFilter(bf);
9501
9502 // Enqueue broadcasts for all existing stickies that match
9503 // this filter.
9504 if (allSticky != null) {
9505 ArrayList receivers = new ArrayList();
9506 receivers.add(bf);
9507
9508 int N = allSticky.size();
9509 for (int i=0; i<N; i++) {
9510 Intent intent = (Intent)allSticky.get(i);
9511 BroadcastRecord r = new BroadcastRecord(intent, null,
9512 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009513 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009514 if (mParallelBroadcasts.size() == 0) {
9515 scheduleBroadcastsLocked();
9516 }
9517 mParallelBroadcasts.add(r);
9518 }
9519 }
9520
9521 return sticky;
9522 }
9523 }
9524
9525 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009526 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009527
9528 boolean doNext = false;
9529
9530 synchronized(this) {
9531 ReceiverList rl
9532 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9533 if (rl != null) {
9534 if (rl.curBroadcast != null) {
9535 BroadcastRecord r = rl.curBroadcast;
9536 doNext = finishReceiverLocked(
9537 receiver.asBinder(), r.resultCode, r.resultData,
9538 r.resultExtras, r.resultAbort, true);
9539 }
9540
9541 if (rl.app != null) {
9542 rl.app.receivers.remove(rl);
9543 }
9544 removeReceiverLocked(rl);
9545 if (rl.linkedToDeath) {
9546 rl.linkedToDeath = false;
9547 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9548 }
9549 }
9550 }
9551
9552 if (!doNext) {
9553 return;
9554 }
9555
9556 final long origId = Binder.clearCallingIdentity();
9557 processNextBroadcast(false);
9558 trimApplications();
9559 Binder.restoreCallingIdentity(origId);
9560 }
9561
9562 void removeReceiverLocked(ReceiverList rl) {
9563 mRegisteredReceivers.remove(rl.receiver.asBinder());
9564 int N = rl.size();
9565 for (int i=0; i<N; i++) {
9566 mReceiverResolver.removeFilter(rl.get(i));
9567 }
9568 }
9569
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009570 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9571 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9572 ProcessRecord r = mLruProcesses.get(i);
9573 if (r.thread != null) {
9574 try {
9575 r.thread.dispatchPackageBroadcast(cmd, packages);
9576 } catch (RemoteException ex) {
9577 }
9578 }
9579 }
9580 }
9581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009582 private final int broadcastIntentLocked(ProcessRecord callerApp,
9583 String callerPackage, Intent intent, String resolvedType,
9584 IIntentReceiver resultTo, int resultCode, String resultData,
9585 Bundle map, String requiredPermission,
9586 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9587 intent = new Intent(intent);
9588
Joe Onorato8a9b2202010-02-26 18:56:32 -08009589 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9591 + " ordered=" + ordered);
9592 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009593 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009594 }
9595
9596 // Handle special intents: if this broadcast is from the package
9597 // manager about a package being removed, we need to remove all of
9598 // its activities from the history stack.
9599 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9600 intent.getAction());
9601 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9602 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009603 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009604 || uidRemoved) {
9605 if (checkComponentPermission(
9606 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9607 callingPid, callingUid, -1)
9608 == PackageManager.PERMISSION_GRANTED) {
9609 if (uidRemoved) {
9610 final Bundle intentExtras = intent.getExtras();
9611 final int uid = intentExtras != null
9612 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9613 if (uid >= 0) {
9614 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9615 synchronized (bs) {
9616 bs.removeUidStatsLocked(uid);
9617 }
9618 }
9619 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009620 // If resources are unvailble just force stop all
9621 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009622 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009623 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9624 if (list != null && (list.length > 0)) {
9625 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009626 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009627 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009628 sendPackageBroadcastLocked(
9629 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009630 }
9631 } else {
9632 Uri data = intent.getData();
9633 String ssp;
9634 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9635 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9636 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009637 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009638 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009639 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9640 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9641 new String[] {ssp});
9642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 }
9644 }
9645 }
9646 } else {
9647 String msg = "Permission Denial: " + intent.getAction()
9648 + " broadcast from " + callerPackage + " (pid=" + callingPid
9649 + ", uid=" + callingUid + ")"
9650 + " requires "
9651 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009652 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009653 throw new SecurityException(msg);
9654 }
9655 }
9656
9657 /*
9658 * If this is the time zone changed action, queue up a message that will reset the timezone
9659 * of all currently running processes. This message will get queued up before the broadcast
9660 * happens.
9661 */
9662 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9663 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9664 }
9665
Dianne Hackborn854060af2009-07-09 18:14:31 -07009666 /*
9667 * Prevent non-system code (defined here to be non-persistent
9668 * processes) from sending protected broadcasts.
9669 */
9670 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9671 || callingUid == Process.SHELL_UID || callingUid == 0) {
9672 // Always okay.
9673 } else if (callerApp == null || !callerApp.persistent) {
9674 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009675 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009676 intent.getAction())) {
9677 String msg = "Permission Denial: not allowed to send broadcast "
9678 + intent.getAction() + " from pid="
9679 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009680 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009681 throw new SecurityException(msg);
9682 }
9683 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009684 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009685 return BROADCAST_SUCCESS;
9686 }
9687 }
9688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 // Add to the sticky list if requested.
9690 if (sticky) {
9691 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9692 callingPid, callingUid)
9693 != PackageManager.PERMISSION_GRANTED) {
9694 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9695 + callingPid + ", uid=" + callingUid
9696 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009697 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 throw new SecurityException(msg);
9699 }
9700 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009701 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 + " and enforce permission " + requiredPermission);
9703 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9704 }
9705 if (intent.getComponent() != null) {
9706 throw new SecurityException(
9707 "Sticky broadcasts can't target a specific component");
9708 }
9709 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9710 if (list == null) {
9711 list = new ArrayList<Intent>();
9712 mStickyBroadcasts.put(intent.getAction(), list);
9713 }
9714 int N = list.size();
9715 int i;
9716 for (i=0; i<N; i++) {
9717 if (intent.filterEquals(list.get(i))) {
9718 // This sticky already exists, replace it.
9719 list.set(i, new Intent(intent));
9720 break;
9721 }
9722 }
9723 if (i >= N) {
9724 list.add(new Intent(intent));
9725 }
9726 }
9727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 // Figure out who all will receive this broadcast.
9729 List receivers = null;
9730 List<BroadcastFilter> registeredReceivers = null;
9731 try {
9732 if (intent.getComponent() != null) {
9733 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009734 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009735 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009736 if (ai != null) {
9737 receivers = new ArrayList();
9738 ResolveInfo ri = new ResolveInfo();
9739 ri.activityInfo = ai;
9740 receivers.add(ri);
9741 }
9742 } else {
9743 // Need to resolve the intent to interested receivers...
9744 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9745 == 0) {
9746 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009747 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009748 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009749 }
Mihai Preda074edef2009-05-18 17:13:31 +02009750 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 }
9752 } catch (RemoteException ex) {
9753 // pm is in same process, this will never happen.
9754 }
9755
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009756 final boolean replacePending =
9757 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9758
Joe Onorato8a9b2202010-02-26 18:56:32 -08009759 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009760 + " replacePending=" + replacePending);
9761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9763 if (!ordered && NR > 0) {
9764 // If we are not serializing this broadcast, then send the
9765 // registered receivers separately so they don't wait for the
9766 // components to be launched.
9767 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9768 callerPackage, callingPid, callingUid, requiredPermission,
9769 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009770 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009771 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009772 TAG, "Enqueueing parallel broadcast " + r
9773 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009774 boolean replaced = false;
9775 if (replacePending) {
9776 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9777 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009778 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009779 "***** DROPPING PARALLEL: " + intent);
9780 mParallelBroadcasts.set(i, r);
9781 replaced = true;
9782 break;
9783 }
9784 }
9785 }
9786 if (!replaced) {
9787 mParallelBroadcasts.add(r);
9788 scheduleBroadcastsLocked();
9789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009790 registeredReceivers = null;
9791 NR = 0;
9792 }
9793
9794 // Merge into one list.
9795 int ir = 0;
9796 if (receivers != null) {
9797 // A special case for PACKAGE_ADDED: do not allow the package
9798 // being added to see this broadcast. This prevents them from
9799 // using this as a back door to get run as soon as they are
9800 // installed. Maybe in the future we want to have a special install
9801 // broadcast or such for apps, but we'd like to deliberately make
9802 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009803 String skipPackages[] = null;
9804 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9805 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9806 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9807 Uri data = intent.getData();
9808 if (data != null) {
9809 String pkgName = data.getSchemeSpecificPart();
9810 if (pkgName != null) {
9811 skipPackages = new String[] { pkgName };
9812 }
9813 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009814 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009815 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009816 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009817 if (skipPackages != null && (skipPackages.length > 0)) {
9818 for (String skipPackage : skipPackages) {
9819 if (skipPackage != null) {
9820 int NT = receivers.size();
9821 for (int it=0; it<NT; it++) {
9822 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9823 if (curt.activityInfo.packageName.equals(skipPackage)) {
9824 receivers.remove(it);
9825 it--;
9826 NT--;
9827 }
9828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 }
9830 }
9831 }
9832
9833 int NT = receivers != null ? receivers.size() : 0;
9834 int it = 0;
9835 ResolveInfo curt = null;
9836 BroadcastFilter curr = null;
9837 while (it < NT && ir < NR) {
9838 if (curt == null) {
9839 curt = (ResolveInfo)receivers.get(it);
9840 }
9841 if (curr == null) {
9842 curr = registeredReceivers.get(ir);
9843 }
9844 if (curr.getPriority() >= curt.priority) {
9845 // Insert this broadcast record into the final list.
9846 receivers.add(it, curr);
9847 ir++;
9848 curr = null;
9849 it++;
9850 NT++;
9851 } else {
9852 // Skip to the next ResolveInfo in the final list.
9853 it++;
9854 curt = null;
9855 }
9856 }
9857 }
9858 while (ir < NR) {
9859 if (receivers == null) {
9860 receivers = new ArrayList();
9861 }
9862 receivers.add(registeredReceivers.get(ir));
9863 ir++;
9864 }
9865
9866 if ((receivers != null && receivers.size() > 0)
9867 || resultTo != null) {
9868 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9869 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009870 receivers, resultTo, resultCode, resultData, map, ordered,
9871 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009872 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009873 TAG, "Enqueueing ordered broadcast " + r
9874 + ": prev had " + mOrderedBroadcasts.size());
9875 if (DEBUG_BROADCAST) {
9876 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009877 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009879 boolean replaced = false;
9880 if (replacePending) {
9881 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9882 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009883 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009884 "***** DROPPING ORDERED: " + intent);
9885 mOrderedBroadcasts.set(i, r);
9886 replaced = true;
9887 break;
9888 }
9889 }
9890 }
9891 if (!replaced) {
9892 mOrderedBroadcasts.add(r);
9893 scheduleBroadcastsLocked();
9894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009895 }
9896
9897 return BROADCAST_SUCCESS;
9898 }
9899
9900 public final int broadcastIntent(IApplicationThread caller,
9901 Intent intent, String resolvedType, IIntentReceiver resultTo,
9902 int resultCode, String resultData, Bundle map,
9903 String requiredPermission, boolean serialized, boolean sticky) {
9904 // Refuse possible leaked file descriptors
9905 if (intent != null && intent.hasFileDescriptors() == true) {
9906 throw new IllegalArgumentException("File descriptors passed in Intent");
9907 }
9908
9909 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009910 int flags = intent.getFlags();
9911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009912 if (!mSystemReady) {
9913 // if the caller really truly claims to know what they're doing, go
9914 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009915 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
9916 intent = new Intent(intent);
9917 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
9918 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -08009919 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009920 + " before boot completion");
9921 throw new IllegalStateException("Cannot broadcast before boot completed");
9922 }
9923 }
9924
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009925 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
9926 throw new IllegalArgumentException(
9927 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
9928 }
9929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009930 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9931 final int callingPid = Binder.getCallingPid();
9932 final int callingUid = Binder.getCallingUid();
9933 final long origId = Binder.clearCallingIdentity();
9934 int res = broadcastIntentLocked(callerApp,
9935 callerApp != null ? callerApp.info.packageName : null,
9936 intent, resolvedType, resultTo,
9937 resultCode, resultData, map, requiredPermission, serialized,
9938 sticky, callingPid, callingUid);
9939 Binder.restoreCallingIdentity(origId);
9940 return res;
9941 }
9942 }
9943
9944 int broadcastIntentInPackage(String packageName, int uid,
9945 Intent intent, String resolvedType, IIntentReceiver resultTo,
9946 int resultCode, String resultData, Bundle map,
9947 String requiredPermission, boolean serialized, boolean sticky) {
9948 synchronized(this) {
9949 final long origId = Binder.clearCallingIdentity();
9950 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
9951 resultTo, resultCode, resultData, map, requiredPermission,
9952 serialized, sticky, -1, uid);
9953 Binder.restoreCallingIdentity(origId);
9954 return res;
9955 }
9956 }
9957
9958 public final void unbroadcastIntent(IApplicationThread caller,
9959 Intent intent) {
9960 // Refuse possible leaked file descriptors
9961 if (intent != null && intent.hasFileDescriptors() == true) {
9962 throw new IllegalArgumentException("File descriptors passed in Intent");
9963 }
9964
9965 synchronized(this) {
9966 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
9967 != PackageManager.PERMISSION_GRANTED) {
9968 String msg = "Permission Denial: unbroadcastIntent() from pid="
9969 + Binder.getCallingPid()
9970 + ", uid=" + Binder.getCallingUid()
9971 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009972 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009973 throw new SecurityException(msg);
9974 }
9975 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9976 if (list != null) {
9977 int N = list.size();
9978 int i;
9979 for (i=0; i<N; i++) {
9980 if (intent.filterEquals(list.get(i))) {
9981 list.remove(i);
9982 break;
9983 }
9984 }
9985 }
9986 }
9987 }
9988
9989 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
9990 String resultData, Bundle resultExtras, boolean resultAbort,
9991 boolean explicit) {
9992 if (mOrderedBroadcasts.size() == 0) {
9993 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009994 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009995 }
9996 return false;
9997 }
9998 BroadcastRecord r = mOrderedBroadcasts.get(0);
9999 if (r.receiver == null) {
10000 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010001 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 }
10003 return false;
10004 }
10005 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010006 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010007 return false;
10008 }
10009 int state = r.state;
10010 r.state = r.IDLE;
10011 if (state == r.IDLE) {
10012 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010013 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010014 }
10015 }
10016 r.receiver = null;
10017 r.intent.setComponent(null);
10018 if (r.curApp != null) {
10019 r.curApp.curReceiver = null;
10020 }
10021 if (r.curFilter != null) {
10022 r.curFilter.receiverList.curBroadcast = null;
10023 }
10024 r.curFilter = null;
10025 r.curApp = null;
10026 r.curComponent = null;
10027 r.curReceiver = null;
10028 mPendingBroadcast = null;
10029
10030 r.resultCode = resultCode;
10031 r.resultData = resultData;
10032 r.resultExtras = resultExtras;
10033 r.resultAbort = resultAbort;
10034
10035 // We will process the next receiver right now if this is finishing
10036 // an app receiver (which is always asynchronous) or after we have
10037 // come back from calling a receiver.
10038 return state == BroadcastRecord.APP_RECEIVE
10039 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10040 }
10041
10042 public void finishReceiver(IBinder who, int resultCode, String resultData,
10043 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010044 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010045
10046 // Refuse possible leaked file descriptors
10047 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10048 throw new IllegalArgumentException("File descriptors passed in Bundle");
10049 }
10050
10051 boolean doNext;
10052
10053 final long origId = Binder.clearCallingIdentity();
10054
10055 synchronized(this) {
10056 doNext = finishReceiverLocked(
10057 who, resultCode, resultData, resultExtras, resultAbort, true);
10058 }
10059
10060 if (doNext) {
10061 processNextBroadcast(false);
10062 }
10063 trimApplications();
10064
10065 Binder.restoreCallingIdentity(origId);
10066 }
10067
10068 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10069 if (r.nextReceiver > 0) {
10070 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10071 if (curReceiver instanceof BroadcastFilter) {
10072 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010073 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010074 System.identityHashCode(r),
10075 r.intent.getAction(),
10076 r.nextReceiver - 1,
10077 System.identityHashCode(bf));
10078 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010079 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010080 System.identityHashCode(r),
10081 r.intent.getAction(),
10082 r.nextReceiver - 1,
10083 ((ResolveInfo)curReceiver).toString());
10084 }
10085 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010086 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010087 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010088 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010089 System.identityHashCode(r),
10090 r.intent.getAction(),
10091 r.nextReceiver,
10092 "NONE");
10093 }
10094 }
10095
10096 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010097 ProcessRecord app = null;
10098 String anrMessage = null;
10099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010100 synchronized (this) {
10101 if (mOrderedBroadcasts.size() == 0) {
10102 return;
10103 }
10104 long now = SystemClock.uptimeMillis();
10105 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010106 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010107 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010108 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010109 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010110 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010111 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 return;
10113 }
10114
Joe Onorato8a9b2202010-02-26 18:56:32 -080010115 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010116 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010117 r.anrCount++;
10118
10119 // Current receiver has passed its expiration date.
10120 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010121 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010122 return;
10123 }
10124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010125 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010126 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010127 logBroadcastReceiverDiscard(r);
10128 if (curReceiver instanceof BroadcastFilter) {
10129 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10130 if (bf.receiverList.pid != 0
10131 && bf.receiverList.pid != MY_PID) {
10132 synchronized (this.mPidsSelfLocked) {
10133 app = this.mPidsSelfLocked.get(
10134 bf.receiverList.pid);
10135 }
10136 }
10137 } else {
10138 app = r.curApp;
10139 }
10140
10141 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010142 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010143 }
10144
10145 if (mPendingBroadcast == r) {
10146 mPendingBroadcast = null;
10147 }
10148
10149 // Move on to the next receiver.
10150 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10151 r.resultExtras, r.resultAbort, true);
10152 scheduleBroadcastsLocked();
10153 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010154
10155 if (anrMessage != null) {
10156 appNotResponding(app, null, null, anrMessage);
10157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010158 }
10159
10160 private final void processCurBroadcastLocked(BroadcastRecord r,
10161 ProcessRecord app) throws RemoteException {
10162 if (app.thread == null) {
10163 throw new RemoteException();
10164 }
10165 r.receiver = app.thread.asBinder();
10166 r.curApp = app;
10167 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010168 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010169
10170 // Tell the application to launch this receiver.
10171 r.intent.setComponent(r.curComponent);
10172
10173 boolean started = false;
10174 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010175 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010176 "Delivering to component " + r.curComponent
10177 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010178 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010179 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10180 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10181 started = true;
10182 } finally {
10183 if (!started) {
10184 r.receiver = null;
10185 r.curApp = null;
10186 app.curReceiver = null;
10187 }
10188 }
10189
10190 }
10191
10192 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010193 Intent intent, int resultCode, String data, Bundle extras,
10194 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010195 if (app != null && app.thread != null) {
10196 // If we have an app thread, do the call through that so it is
10197 // correctly ordered with other one-way calls.
10198 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010199 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010200 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010201 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010202 }
10203 }
10204
10205 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10206 BroadcastFilter filter, boolean ordered) {
10207 boolean skip = false;
10208 if (filter.requiredPermission != null) {
10209 int perm = checkComponentPermission(filter.requiredPermission,
10210 r.callingPid, r.callingUid, -1);
10211 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010212 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 + r.intent.toString()
10214 + " from " + r.callerPackage + " (pid="
10215 + r.callingPid + ", uid=" + r.callingUid + ")"
10216 + " requires " + filter.requiredPermission
10217 + " due to registered receiver " + filter);
10218 skip = true;
10219 }
10220 }
10221 if (r.requiredPermission != null) {
10222 int perm = checkComponentPermission(r.requiredPermission,
10223 filter.receiverList.pid, filter.receiverList.uid, -1);
10224 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010225 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010226 + r.intent.toString()
10227 + " to " + filter.receiverList.app
10228 + " (pid=" + filter.receiverList.pid
10229 + ", uid=" + filter.receiverList.uid + ")"
10230 + " requires " + r.requiredPermission
10231 + " due to sender " + r.callerPackage
10232 + " (uid " + r.callingUid + ")");
10233 skip = true;
10234 }
10235 }
10236
10237 if (!skip) {
10238 // If this is not being sent as an ordered broadcast, then we
10239 // don't want to touch the fields that keep track of the current
10240 // state of ordered broadcasts.
10241 if (ordered) {
10242 r.receiver = filter.receiverList.receiver.asBinder();
10243 r.curFilter = filter;
10244 filter.receiverList.curBroadcast = r;
10245 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010246 if (filter.receiverList.app != null) {
10247 // Bump hosting application to no longer be in background
10248 // scheduling class. Note that we can't do that if there
10249 // isn't an app... but we can only be in that case for
10250 // things that directly call the IActivityManager API, which
10251 // are already core system stuff so don't matter for this.
10252 r.curApp = filter.receiverList.app;
10253 filter.receiverList.app.curReceiver = r;
10254 updateOomAdjLocked();
10255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010256 }
10257 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010258 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010259 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010260 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010261 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262 }
10263 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10264 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010265 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 if (ordered) {
10267 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10268 }
10269 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010270 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010271 if (ordered) {
10272 r.receiver = null;
10273 r.curFilter = null;
10274 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010275 if (filter.receiverList.app != null) {
10276 filter.receiverList.app.curReceiver = null;
10277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010278 }
10279 }
10280 }
10281 }
10282
Dianne Hackborn12527f92009-11-11 17:39:50 -080010283 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10284 if (r.callingUid < 0) {
10285 // This was from a registerReceiver() call; ignore it.
10286 return;
10287 }
10288 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10289 MAX_BROADCAST_HISTORY-1);
10290 r.finishTime = SystemClock.uptimeMillis();
10291 mBroadcastHistory[0] = r;
10292 }
10293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010294 private final void processNextBroadcast(boolean fromMsg) {
10295 synchronized(this) {
10296 BroadcastRecord r;
10297
Joe Onorato8a9b2202010-02-26 18:56:32 -080010298 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010300 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301
10302 updateCpuStats();
10303
10304 if (fromMsg) {
10305 mBroadcastsScheduled = false;
10306 }
10307
10308 // First, deliver any non-serialized broadcasts right away.
10309 while (mParallelBroadcasts.size() > 0) {
10310 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010311 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010312 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010313 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010314 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 for (int i=0; i<N; i++) {
10316 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010317 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010318 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 + target + ": " + r);
10320 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10321 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010322 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010323 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010324 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010325 }
10326
10327 // Now take care of the next serialized one...
10328
10329 // If we are waiting for a process to come up to handle the next
10330 // broadcast, then do nothing at this point. Just in case, we
10331 // check that the process we're waiting for still exists.
10332 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010333 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010334 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010335 + mPendingBroadcast.curApp);
10336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010337
10338 boolean isDead;
10339 synchronized (mPidsSelfLocked) {
10340 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10341 }
10342 if (!isDead) {
10343 // It's still alive, so keep waiting
10344 return;
10345 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010346 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010347 + " died before responding to broadcast");
10348 mPendingBroadcast = null;
10349 }
10350 }
10351
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010352 boolean looped = false;
10353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 do {
10355 if (mOrderedBroadcasts.size() == 0) {
10356 // No more broadcasts pending, so all done!
10357 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010358 if (looped) {
10359 // If we had finished the last ordered broadcast, then
10360 // make sure all processes have correct oom and sched
10361 // adjustments.
10362 updateOomAdjLocked();
10363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010364 return;
10365 }
10366 r = mOrderedBroadcasts.get(0);
10367 boolean forceReceive = false;
10368
10369 // Ensure that even if something goes awry with the timeout
10370 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010371 // and continue to make progress.
10372 //
10373 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10374 // receivers don't get executed with with timeouts. They're intended for
10375 // one time heavy lifting after system upgrades and can take
10376 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010377 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010378 if (mSystemReady && r.dispatchTime > 0) {
10379 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010380 if ((numReceivers > 0) &&
10381 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010382 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 + " now=" + now
10384 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010385 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010386 + " intent=" + r.intent
10387 + " numReceivers=" + numReceivers
10388 + " nextReceiver=" + r.nextReceiver
10389 + " state=" + r.state);
10390 broadcastTimeout(); // forcibly finish this broadcast
10391 forceReceive = true;
10392 r.state = BroadcastRecord.IDLE;
10393 }
10394 }
10395
10396 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010397 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010398 "processNextBroadcast() called when not idle (state="
10399 + r.state + ")");
10400 return;
10401 }
10402
10403 if (r.receivers == null || r.nextReceiver >= numReceivers
10404 || r.resultAbort || forceReceive) {
10405 // No more receivers for this broadcast! Send the final
10406 // result if requested...
10407 if (r.resultTo != null) {
10408 try {
10409 if (DEBUG_BROADCAST) {
10410 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010411 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010412 + " seq=" + seq + " app=" + r.callerApp);
10413 }
10414 performReceive(r.callerApp, r.resultTo,
10415 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010416 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010417 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010418 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010419 }
10420 }
10421
Joe Onorato8a9b2202010-02-26 18:56:32 -080010422 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10424
Joe Onorato8a9b2202010-02-26 18:56:32 -080010425 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010426 + r);
10427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010428 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010429 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 mOrderedBroadcasts.remove(0);
10431 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010432 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010433 continue;
10434 }
10435 } while (r == null);
10436
10437 // Get the next receiver...
10438 int recIdx = r.nextReceiver++;
10439
10440 // Keep track of when this receiver started, and make sure there
10441 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010442 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010444 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010445
Joe Onorato8a9b2202010-02-26 18:56:32 -080010446 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010447 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010448 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010449 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010450 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010451 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010452 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010453 }
10454
10455 Object nextReceiver = r.receivers.get(recIdx);
10456 if (nextReceiver instanceof BroadcastFilter) {
10457 // Simple case: this is a registered receiver who gets
10458 // a direct call.
10459 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010460 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010461 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010462 + filter + ": " + r);
10463 deliverToRegisteredReceiver(r, filter, r.ordered);
10464 if (r.receiver == null || !r.ordered) {
10465 // The receiver has already finished, so schedule to
10466 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010467 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10468 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010469 r.state = BroadcastRecord.IDLE;
10470 scheduleBroadcastsLocked();
10471 }
10472 return;
10473 }
10474
10475 // Hard case: need to instantiate the receiver, possibly
10476 // starting its application process to host it.
10477
10478 ResolveInfo info =
10479 (ResolveInfo)nextReceiver;
10480
10481 boolean skip = false;
10482 int perm = checkComponentPermission(info.activityInfo.permission,
10483 r.callingPid, r.callingUid,
10484 info.activityInfo.exported
10485 ? -1 : info.activityInfo.applicationInfo.uid);
10486 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010487 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010488 + r.intent.toString()
10489 + " from " + r.callerPackage + " (pid=" + r.callingPid
10490 + ", uid=" + r.callingUid + ")"
10491 + " requires " + info.activityInfo.permission
10492 + " due to receiver " + info.activityInfo.packageName
10493 + "/" + info.activityInfo.name);
10494 skip = true;
10495 }
10496 if (r.callingUid != Process.SYSTEM_UID &&
10497 r.requiredPermission != null) {
10498 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010499 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 checkPermission(r.requiredPermission,
10501 info.activityInfo.applicationInfo.packageName);
10502 } catch (RemoteException e) {
10503 perm = PackageManager.PERMISSION_DENIED;
10504 }
10505 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010506 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010507 + r.intent + " to "
10508 + info.activityInfo.applicationInfo.packageName
10509 + " requires " + r.requiredPermission
10510 + " due to sender " + r.callerPackage
10511 + " (uid " + r.callingUid + ")");
10512 skip = true;
10513 }
10514 }
10515 if (r.curApp != null && r.curApp.crashing) {
10516 // If the target process is crashing, just skip it.
10517 skip = true;
10518 }
10519
10520 if (skip) {
10521 r.receiver = null;
10522 r.curFilter = null;
10523 r.state = BroadcastRecord.IDLE;
10524 scheduleBroadcastsLocked();
10525 return;
10526 }
10527
10528 r.state = BroadcastRecord.APP_RECEIVE;
10529 String targetProcess = info.activityInfo.processName;
10530 r.curComponent = new ComponentName(
10531 info.activityInfo.applicationInfo.packageName,
10532 info.activityInfo.name);
10533 r.curReceiver = info.activityInfo;
10534
10535 // Is this receiver's application already running?
10536 ProcessRecord app = getProcessRecordLocked(targetProcess,
10537 info.activityInfo.applicationInfo.uid);
10538 if (app != null && app.thread != null) {
10539 try {
10540 processCurBroadcastLocked(r, app);
10541 return;
10542 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010543 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010544 + r.curComponent, e);
10545 }
10546
10547 // If a dead object exception was thrown -- fall through to
10548 // restart the application.
10549 }
10550
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010551 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010552 if ((r.curApp=startProcessLocked(targetProcess,
10553 info.activityInfo.applicationInfo, true,
10554 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010555 "broadcast", r.curComponent,
10556 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10557 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010558 // Ah, this recipient is unavailable. Finish it if necessary,
10559 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010560 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010561 + info.activityInfo.applicationInfo.packageName + "/"
10562 + info.activityInfo.applicationInfo.uid + " for broadcast "
10563 + r.intent + ": process is bad");
10564 logBroadcastReceiverDiscard(r);
10565 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10566 r.resultExtras, r.resultAbort, true);
10567 scheduleBroadcastsLocked();
10568 r.state = BroadcastRecord.IDLE;
10569 return;
10570 }
10571
10572 mPendingBroadcast = r;
10573 }
10574 }
10575
10576 // =========================================================
10577 // INSTRUMENTATION
10578 // =========================================================
10579
10580 public boolean startInstrumentation(ComponentName className,
10581 String profileFile, int flags, Bundle arguments,
10582 IInstrumentationWatcher watcher) {
10583 // Refuse possible leaked file descriptors
10584 if (arguments != null && arguments.hasFileDescriptors()) {
10585 throw new IllegalArgumentException("File descriptors passed in Bundle");
10586 }
10587
10588 synchronized(this) {
10589 InstrumentationInfo ii = null;
10590 ApplicationInfo ai = null;
10591 try {
10592 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010593 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010594 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010595 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010596 } catch (PackageManager.NameNotFoundException e) {
10597 }
10598 if (ii == null) {
10599 reportStartInstrumentationFailure(watcher, className,
10600 "Unable to find instrumentation info for: " + className);
10601 return false;
10602 }
10603 if (ai == null) {
10604 reportStartInstrumentationFailure(watcher, className,
10605 "Unable to find instrumentation target package: " + ii.targetPackage);
10606 return false;
10607 }
10608
10609 int match = mContext.getPackageManager().checkSignatures(
10610 ii.targetPackage, ii.packageName);
10611 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10612 String msg = "Permission Denial: starting instrumentation "
10613 + className + " from pid="
10614 + Binder.getCallingPid()
10615 + ", uid=" + Binder.getCallingPid()
10616 + " not allowed because package " + ii.packageName
10617 + " does not have a signature matching the target "
10618 + ii.targetPackage;
10619 reportStartInstrumentationFailure(watcher, className, msg);
10620 throw new SecurityException(msg);
10621 }
10622
10623 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010624 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010625 ProcessRecord app = addAppLocked(ai);
10626 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010627 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010628 app.instrumentationProfileFile = profileFile;
10629 app.instrumentationArguments = arguments;
10630 app.instrumentationWatcher = watcher;
10631 app.instrumentationResultClass = className;
10632 Binder.restoreCallingIdentity(origId);
10633 }
10634
10635 return true;
10636 }
10637
10638 /**
10639 * Report errors that occur while attempting to start Instrumentation. Always writes the
10640 * error to the logs, but if somebody is watching, send the report there too. This enables
10641 * the "am" command to report errors with more information.
10642 *
10643 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10644 * @param cn The component name of the instrumentation.
10645 * @param report The error report.
10646 */
10647 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10648 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010649 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010650 try {
10651 if (watcher != null) {
10652 Bundle results = new Bundle();
10653 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10654 results.putString("Error", report);
10655 watcher.instrumentationStatus(cn, -1, results);
10656 }
10657 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010658 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010659 }
10660 }
10661
10662 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10663 if (app.instrumentationWatcher != null) {
10664 try {
10665 // NOTE: IInstrumentationWatcher *must* be oneway here
10666 app.instrumentationWatcher.instrumentationFinished(
10667 app.instrumentationClass,
10668 resultCode,
10669 results);
10670 } catch (RemoteException e) {
10671 }
10672 }
10673 app.instrumentationWatcher = null;
10674 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010675 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010676 app.instrumentationProfileFile = null;
10677 app.instrumentationArguments = null;
10678
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010679 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010680 }
10681
10682 public void finishInstrumentation(IApplicationThread target,
10683 int resultCode, Bundle results) {
10684 // Refuse possible leaked file descriptors
10685 if (results != null && results.hasFileDescriptors()) {
10686 throw new IllegalArgumentException("File descriptors passed in Intent");
10687 }
10688
10689 synchronized(this) {
10690 ProcessRecord app = getRecordForAppLocked(target);
10691 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010692 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010693 return;
10694 }
10695 final long origId = Binder.clearCallingIdentity();
10696 finishInstrumentationLocked(app, resultCode, results);
10697 Binder.restoreCallingIdentity(origId);
10698 }
10699 }
10700
10701 // =========================================================
10702 // CONFIGURATION
10703 // =========================================================
10704
10705 public ConfigurationInfo getDeviceConfigurationInfo() {
10706 ConfigurationInfo config = new ConfigurationInfo();
10707 synchronized (this) {
10708 config.reqTouchScreen = mConfiguration.touchscreen;
10709 config.reqKeyboardType = mConfiguration.keyboard;
10710 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010711 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10712 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010713 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10714 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010715 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10716 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010717 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10718 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010719 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 }
10721 return config;
10722 }
10723
10724 public Configuration getConfiguration() {
10725 Configuration ci;
10726 synchronized(this) {
10727 ci = new Configuration(mConfiguration);
10728 }
10729 return ci;
10730 }
10731
10732 public void updateConfiguration(Configuration values) {
10733 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10734 "updateConfiguration()");
10735
10736 synchronized(this) {
10737 if (values == null && mWindowManager != null) {
10738 // sentinel: fetch the current configuration from the window manager
10739 values = mWindowManager.computeNewConfiguration();
10740 }
10741
10742 final long origId = Binder.clearCallingIdentity();
10743 updateConfigurationLocked(values, null);
10744 Binder.restoreCallingIdentity(origId);
10745 }
10746 }
10747
10748 /**
10749 * Do either or both things: (1) change the current configuration, and (2)
10750 * make sure the given activity is running with the (now) current
10751 * configuration. Returns true if the activity has been left running, or
10752 * false if <var>starting</var> is being destroyed to match the new
10753 * configuration.
10754 */
10755 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010756 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757 int changes = 0;
10758
10759 boolean kept = true;
10760
10761 if (values != null) {
10762 Configuration newConfig = new Configuration(mConfiguration);
10763 changes = newConfig.updateFrom(values);
10764 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010765 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010766 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010767 }
10768
Doug Zongker2bec3d42009-12-04 12:52:44 -080010769 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010770
10771 if (values.locale != null) {
10772 saveLocaleLocked(values.locale,
10773 !values.locale.equals(mConfiguration.locale),
10774 values.userSetLocale);
10775 }
10776
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010777 mConfigurationSeq++;
10778 if (mConfigurationSeq <= 0) {
10779 mConfigurationSeq = 1;
10780 }
10781 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010783 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010784
10785 AttributeCache ac = AttributeCache.instance();
10786 if (ac != null) {
10787 ac.updateConfiguration(mConfiguration);
10788 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010790 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10791 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10792 msg.obj = new Configuration(mConfiguration);
10793 mHandler.sendMessage(msg);
10794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010795
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010796 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10797 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010798 try {
10799 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010800 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010801 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010802 app.thread.scheduleConfigurationChanged(mConfiguration);
10803 }
10804 } catch (Exception e) {
10805 }
10806 }
10807 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010808 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10809 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10811 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010812 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10813 broadcastIntentLocked(null, null,
10814 new Intent(Intent.ACTION_LOCALE_CHANGED),
10815 null, null, 0, null, null,
10816 null, false, false, MY_PID, Process.SYSTEM_UID);
10817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010818 }
10819 }
10820
10821 if (changes != 0 && starting == null) {
10822 // If the configuration changed, and the caller is not already
10823 // in the process of starting an activity, then find the top
10824 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010825 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010826 }
10827
10828 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010829 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 if (kept) {
10831 // If this didn't result in the starting activity being
10832 // destroyed, then we need to make sure at this point that all
10833 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010834 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010835 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010836 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010837 }
10838 }
10839
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010840 if (values != null && mWindowManager != null) {
10841 mWindowManager.setNewConfiguration(mConfiguration);
10842 }
10843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 return kept;
10845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010846
10847 /**
10848 * Save the locale. You must be inside a synchronized (this) block.
10849 */
10850 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10851 if(isDiff) {
10852 SystemProperties.set("user.language", l.getLanguage());
10853 SystemProperties.set("user.region", l.getCountry());
10854 }
10855
10856 if(isPersist) {
10857 SystemProperties.set("persist.sys.language", l.getLanguage());
10858 SystemProperties.set("persist.sys.country", l.getCountry());
10859 SystemProperties.set("persist.sys.localevar", l.getVariant());
10860 }
10861 }
10862
10863 // =========================================================
10864 // LIFETIME MANAGEMENT
10865 // =========================================================
10866
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010867 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
10868 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010869 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010870 // This adjustment has already been computed. If we are calling
10871 // from the top, we may have already computed our adjustment with
10872 // an earlier hidden adjustment that isn't really for us... if
10873 // so, use the new hidden adjustment.
10874 if (!recursed && app.hidden) {
10875 app.curAdj = hiddenAdj;
10876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010877 return app.curAdj;
10878 }
10879
10880 if (app.thread == null) {
10881 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010882 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883 return (app.curAdj=EMPTY_APP_ADJ);
10884 }
10885
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010886 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
10887 // The max adjustment doesn't allow this app to be anything
10888 // below foreground, so it is not worth doing work for it.
10889 app.adjType = "fixed";
10890 app.adjSeq = mAdjSeq;
10891 app.curRawAdj = app.maxAdj;
10892 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
10893 return (app.curAdj=app.maxAdj);
10894 }
10895
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010896 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010897 app.adjSource = null;
10898 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010899 app.empty = false;
10900 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010901
The Android Open Source Project4df24232009-03-05 14:34:35 -080010902 // Determine the importance of the process, starting with most
10903 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010905 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010907 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 // The last app on the list is the foreground app.
10909 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010910 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010911 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010912 } else if (app.instrumentationClass != null) {
10913 // Don't want to kill running instrumentation.
10914 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010915 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010916 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010917 } else if (app.persistentActivities > 0) {
10918 // Special persistent activities... shouldn't be used these days.
10919 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010920 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010921 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010922 } else if (app.curReceiver != null ||
10923 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
10924 // An app that is currently receiving a broadcast also
10925 // counts as being in the foreground.
10926 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010927 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010928 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 } else if (app.executingServices.size() > 0) {
10930 // An app that is currently executing a service callback also
10931 // counts as being in the foreground.
10932 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010933 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010934 app.adjType = "exec-service";
10935 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010937 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010938 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010939 app.adjType = "foreground-service";
10940 } else if (app.forcingToForeground != null) {
10941 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010942 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010943 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010944 app.adjType = "force-foreground";
10945 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010946 } else if (app == mHeavyWeightProcess) {
10947 // We don't want to kill the current heavy-weight process.
10948 adj = HEAVY_WEIGHT_APP_ADJ;
10949 schedGroup = Process.THREAD_GROUP_DEFAULT;
10950 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080010951 } else if (app == mHomeProcess) {
10952 // This process is hosting what we currently consider to be the
10953 // home app, so we don't want to let it go into the background.
10954 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010955 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010956 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 } else if ((N=app.activities.size()) != 0) {
10958 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010959 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010961 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010962 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010963 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010964 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010965 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010967 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010968 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010969 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010970 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010971 break;
10972 }
10973 }
10974 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010975 // A very not-needed process. If this is lower in the lru list,
10976 // we will push it in to the empty bucket.
10977 app.hidden = true;
10978 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010979 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010980 adj = hiddenAdj;
10981 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010982 }
10983
Joe Onorato8a9b2202010-02-26 18:56:32 -080010984 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010985
The Android Open Source Project4df24232009-03-05 14:34:35 -080010986 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987 // there are applications dependent on our services or providers, but
10988 // this gives us a baseline and makes sure we don't get into an
10989 // infinite recursion.
10990 app.adjSeq = mAdjSeq;
10991 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992
Christopher Tate6fa95972009-06-05 18:43:55 -070010993 if (mBackupTarget != null && app == mBackupTarget.app) {
10994 // If possible we want to avoid killing apps while they're being backed up
10995 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010996 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070010997 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010998 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010999 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011000 }
11001 }
11002
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011003 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11004 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011005 final long now = SystemClock.uptimeMillis();
11006 // This process is more important if the top activity is
11007 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011008 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011009 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011010 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 if (s.startRequested) {
11012 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11013 // This service has seen some activity within
11014 // recent memory, so we will keep its process ahead
11015 // of the background processes.
11016 if (adj > SECONDARY_SERVER_ADJ) {
11017 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011018 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011019 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 }
11021 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011022 // If we have let the service slide into the background
11023 // state, still have some text describing what it is doing
11024 // even though the service no longer has an impact.
11025 if (adj > SECONDARY_SERVER_ADJ) {
11026 app.adjType = "started-bg-services";
11027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011028 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011029 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11030 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011031 Iterator<ConnectionRecord> kt
11032 = s.connections.values().iterator();
11033 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11034 // XXX should compute this based on the max of
11035 // all connected clients.
11036 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011037 if (cr.binding.client == app) {
11038 // Binding to ourself is not interesting.
11039 continue;
11040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11042 ProcessRecord client = cr.binding.client;
11043 int myHiddenAdj = hiddenAdj;
11044 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011045 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 myHiddenAdj = client.hiddenAdj;
11047 } else {
11048 myHiddenAdj = VISIBLE_APP_ADJ;
11049 }
11050 }
11051 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011052 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011054 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011055 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011056 if (!client.hidden) {
11057 app.hidden = false;
11058 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011059 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011060 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11061 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011062 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011063 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011065 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11066 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11067 schedGroup = Process.THREAD_GROUP_DEFAULT;
11068 }
11069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011071 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011073 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011074 //}
11075 if (a != null && adj > FOREGROUND_APP_ADJ &&
11076 (a.state == ActivityState.RESUMED
11077 || a.state == ActivityState.PAUSING)) {
11078 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011079 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011080 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011081 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011082 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11083 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011084 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011085 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011086 }
11087 }
11088 }
11089 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011090
11091 // Finally, f this process has active services running in it, we
11092 // would like to avoid killing it unless it would prevent the current
11093 // application from running. By default we put the process in
11094 // with the rest of the background processes; as we scan through
11095 // its services we may bump it up from there.
11096 if (adj > hiddenAdj) {
11097 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011098 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011099 app.adjType = "bg-services";
11100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011101 }
11102
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011103 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11104 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011105 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011106 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11107 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011108 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 if (cpr.clients.size() != 0) {
11110 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11111 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11112 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011113 if (client == app) {
11114 // Being our own client is not interesting.
11115 continue;
11116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 int myHiddenAdj = hiddenAdj;
11118 if (myHiddenAdj > client.hiddenAdj) {
11119 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11120 myHiddenAdj = client.hiddenAdj;
11121 } else {
11122 myHiddenAdj = FOREGROUND_APP_ADJ;
11123 }
11124 }
11125 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011126 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011127 if (adj > clientAdj) {
11128 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011129 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011130 if (!client.hidden) {
11131 app.hidden = false;
11132 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011133 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011134 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11135 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011136 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011137 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011138 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011139 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11140 schedGroup = Process.THREAD_GROUP_DEFAULT;
11141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 }
11143 }
11144 // If the provider has external (non-framework) process
11145 // dependencies, ensure that its adjustment is at least
11146 // FOREGROUND_APP_ADJ.
11147 if (cpr.externals != 0) {
11148 if (adj > FOREGROUND_APP_ADJ) {
11149 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011150 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011151 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011152 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011153 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 }
11155 }
11156 }
11157 }
11158
11159 app.curRawAdj = adj;
11160
Joe Onorato8a9b2202010-02-26 18:56:32 -080011161 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011162 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11163 if (adj > app.maxAdj) {
11164 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011165 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011166 schedGroup = Process.THREAD_GROUP_DEFAULT;
11167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011168 }
11169
11170 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011171 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 return adj;
11174 }
11175
11176 /**
11177 * Ask a given process to GC right now.
11178 */
11179 final void performAppGcLocked(ProcessRecord app) {
11180 try {
11181 app.lastRequestedGc = SystemClock.uptimeMillis();
11182 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011183 if (app.reportLowMemory) {
11184 app.reportLowMemory = false;
11185 app.thread.scheduleLowMemory();
11186 } else {
11187 app.thread.processInBackground();
11188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189 }
11190 } catch (Exception e) {
11191 // whatever.
11192 }
11193 }
11194
11195 /**
11196 * Returns true if things are idle enough to perform GCs.
11197 */
Josh Bartel7f208742010-02-25 11:01:44 -060011198 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 return mParallelBroadcasts.size() == 0
11200 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011201 && (mSleeping || (mMainStack.mResumedActivity != null &&
11202 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011203 }
11204
11205 /**
11206 * Perform GCs on all processes that are waiting for it, but only
11207 * if things are idle.
11208 */
11209 final void performAppGcsLocked() {
11210 final int N = mProcessesToGc.size();
11211 if (N <= 0) {
11212 return;
11213 }
Josh Bartel7f208742010-02-25 11:01:44 -060011214 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011215 while (mProcessesToGc.size() > 0) {
11216 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011217 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011218 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11219 <= SystemClock.uptimeMillis()) {
11220 // To avoid spamming the system, we will GC processes one
11221 // at a time, waiting a few seconds between each.
11222 performAppGcLocked(proc);
11223 scheduleAppGcsLocked();
11224 return;
11225 } else {
11226 // It hasn't been long enough since we last GCed this
11227 // process... put it in the list to wait for its time.
11228 addProcessToGcListLocked(proc);
11229 break;
11230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 }
11232 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011233
11234 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 }
11236 }
11237
11238 /**
11239 * If all looks good, perform GCs on all processes waiting for them.
11240 */
11241 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011242 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011243 performAppGcsLocked();
11244 return;
11245 }
11246 // Still not idle, wait some more.
11247 scheduleAppGcsLocked();
11248 }
11249
11250 /**
11251 * Schedule the execution of all pending app GCs.
11252 */
11253 final void scheduleAppGcsLocked() {
11254 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011255
11256 if (mProcessesToGc.size() > 0) {
11257 // Schedule a GC for the time to the next process.
11258 ProcessRecord proc = mProcessesToGc.get(0);
11259 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11260
11261 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11262 long now = SystemClock.uptimeMillis();
11263 if (when < (now+GC_TIMEOUT)) {
11264 when = now + GC_TIMEOUT;
11265 }
11266 mHandler.sendMessageAtTime(msg, when);
11267 }
11268 }
11269
11270 /**
11271 * Add a process to the array of processes waiting to be GCed. Keeps the
11272 * list in sorted order by the last GC time. The process can't already be
11273 * on the list.
11274 */
11275 final void addProcessToGcListLocked(ProcessRecord proc) {
11276 boolean added = false;
11277 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11278 if (mProcessesToGc.get(i).lastRequestedGc <
11279 proc.lastRequestedGc) {
11280 added = true;
11281 mProcessesToGc.add(i+1, proc);
11282 break;
11283 }
11284 }
11285 if (!added) {
11286 mProcessesToGc.add(0, proc);
11287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011288 }
11289
11290 /**
11291 * Set up to ask a process to GC itself. This will either do it
11292 * immediately, or put it on the list of processes to gc the next
11293 * time things are idle.
11294 */
11295 final void scheduleAppGcLocked(ProcessRecord app) {
11296 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011297 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298 return;
11299 }
11300 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011301 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011302 scheduleAppGcsLocked();
11303 }
11304 }
11305
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011306 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11307 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11308 if (mLastWakeLockCheckTime == 0) {
11309 doKills = false;
11310 }
11311 if (stats.isScreenOn()) {
11312 doKills = false;
11313 }
11314 final long curRealtime = SystemClock.elapsedRealtime();
11315 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11316 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011317 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011318 doKills = false;
11319 }
11320 int i = mLruProcesses.size();
11321 while (i > 0) {
11322 i--;
11323 ProcessRecord app = mLruProcesses.get(i);
11324 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11325 long wtime;
11326 synchronized (stats) {
11327 wtime = stats.getProcessWakeTime(app.info.uid,
11328 app.pid, curRealtime);
11329 }
11330 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011331 if (false) {
11332 StringBuilder sb = new StringBuilder(128);
11333 sb.append("Wake for ");
11334 app.toShortString(sb);
11335 sb.append(": over ");
11336 TimeUtils.formatDuration(timeSince, sb);
11337 sb.append(" used ");
11338 TimeUtils.formatDuration(timeUsed, sb);
11339 sb.append(" (");
11340 sb.append((timeUsed*100)/timeSince);
11341 sb.append("%)");
11342 Slog.i(TAG, sb.toString());
11343 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011344 // If a process has held a wake lock for more
11345 // than 50% of the time during this period,
11346 // that sounds pad. Kill!
11347 if (doKills && timeSince > 0
11348 && ((timeUsed*100)/timeSince) >= 50) {
11349 Slog.i(TAG, "Excessive wake lock in " + app.processName
11350 + " (pid " + app.pid + "): held " + timeUsed
11351 + " during " + timeSince);
11352 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11353 app.processName, app.setAdj, "excessive wake lock");
11354 Process.killProcessQuiet(app.pid);
11355 } else {
11356 app.lastWakeTime = wtime;
11357 }
11358 }
11359 }
11360 }
11361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 private final boolean updateOomAdjLocked(
11363 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11364 app.hiddenAdj = hiddenAdj;
11365
11366 if (app.thread == null) {
11367 return true;
11368 }
11369
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011370 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011371
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011372 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011373 if (app.curRawAdj != app.setRawAdj) {
11374 if (app.curRawAdj > FOREGROUND_APP_ADJ
11375 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11376 // If this app is transitioning from foreground to
11377 // non-foreground, have it do a gc.
11378 scheduleAppGcLocked(app);
11379 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11380 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11381 // Likewise do a gc when an app is moving in to the
11382 // background (such as a service stopping).
11383 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011384 // And note its current wake lock time.
11385 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11386 synchronized (stats) {
11387 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11388 app.pid, SystemClock.elapsedRealtime());
11389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390 }
11391 app.setRawAdj = app.curRawAdj;
11392 }
11393 if (adj != app.setAdj) {
11394 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011395 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011396 TAG, "Set app " + app.processName +
11397 " oom adj to " + adj);
11398 app.setAdj = adj;
11399 } else {
11400 return false;
11401 }
11402 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011403 if (app.setSchedGroup != app.curSchedGroup) {
11404 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011405 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011406 "Setting process group of " + app.processName
11407 + " to " + app.curSchedGroup);
11408 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011409 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011410 try {
11411 Process.setProcessGroup(app.pid, app.curSchedGroup);
11412 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011413 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011414 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011415 e.printStackTrace();
11416 } finally {
11417 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011418 }
11419 }
11420 if (false) {
11421 if (app.thread != null) {
11422 try {
11423 app.thread.setSchedulingGroup(app.curSchedGroup);
11424 } catch (RemoteException e) {
11425 }
11426 }
11427 }
11428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011429 }
11430
11431 return true;
11432 }
11433
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011434 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011435 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011437 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011438 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011439 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011440 }
11441 }
11442 return resumedActivity;
11443 }
11444
11445 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011446 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011447 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11448 int curAdj = app.curAdj;
11449 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11450 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11451
11452 mAdjSeq++;
11453
11454 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11455 if (res) {
11456 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11457 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11458 if (nowHidden != wasHidden) {
11459 // Changed to/from hidden state, so apps after it in the LRU
11460 // list may also be changed.
11461 updateOomAdjLocked();
11462 }
11463 }
11464 return res;
11465 }
11466
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011467 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011469 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11471
11472 if (false) {
11473 RuntimeException e = new RuntimeException();
11474 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011475 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011476 }
11477
11478 mAdjSeq++;
11479
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011480 // Let's determine how many processes we have running vs.
11481 // how many slots we have for background processes; we may want
11482 // to put multiple processes in a slot of there are enough of
11483 // them.
11484 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11485 int factor = (mLruProcesses.size()-4)/numSlots;
11486 if (factor < 1) factor = 1;
11487 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011488 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011490 // First try updating the OOM adjustment for each of the
11491 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011492 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011493 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11494 while (i > 0) {
11495 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011496 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011497 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011498 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011499 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011501 step++;
11502 if (step >= factor) {
11503 step = 0;
11504 curHiddenAdj++;
11505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011507 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011508 if (!app.killedBackground) {
11509 numHidden++;
11510 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011511 Slog.i(TAG, "No longer want " + app.processName
11512 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011513 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11514 app.processName, app.setAdj, "too many background");
11515 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011516 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011517 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011518 }
11519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011520 } else {
11521 didOomAdj = false;
11522 }
11523 }
11524
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011525 // If we return false, we will fall back on killing processes to
11526 // have a fixed limit. Do this if a limit has been requested; else
11527 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011528 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11529 }
11530
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011531 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 synchronized (this) {
11533 int i;
11534
11535 // First remove any unused application processes whose package
11536 // has been removed.
11537 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11538 final ProcessRecord app = mRemovedProcesses.get(i);
11539 if (app.activities.size() == 0
11540 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011541 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011542 TAG, "Exiting empty application process "
11543 + app.processName + " ("
11544 + (app.thread != null ? app.thread.asBinder() : null)
11545 + ")\n");
11546 if (app.pid > 0 && app.pid != MY_PID) {
11547 Process.killProcess(app.pid);
11548 } else {
11549 try {
11550 app.thread.scheduleExit();
11551 } catch (Exception e) {
11552 // Ignore exceptions.
11553 }
11554 }
11555 cleanUpApplicationRecordLocked(app, false, -1);
11556 mRemovedProcesses.remove(i);
11557
11558 if (app.persistent) {
11559 if (app.persistent) {
11560 addAppLocked(app.info);
11561 }
11562 }
11563 }
11564 }
11565
11566 // Now try updating the OOM adjustment for each of the
11567 // application processes based on their current state.
11568 // If the setOomAdj() API is not supported, then go with our
11569 // back-up plan...
11570 if (!updateOomAdjLocked()) {
11571
11572 // Count how many processes are running services.
11573 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011574 for (i=mLruProcesses.size()-1; i>=0; i--) {
11575 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576
11577 if (app.persistent || app.services.size() != 0
11578 || app.curReceiver != null
11579 || app.persistentActivities > 0) {
11580 // Don't count processes holding services against our
11581 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011582 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011583 TAG, "Not trimming app " + app + " with services: "
11584 + app.services);
11585 numServiceProcs++;
11586 }
11587 }
11588
11589 int curMaxProcs = mProcessLimit;
11590 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11591 if (mAlwaysFinishActivities) {
11592 curMaxProcs = 1;
11593 }
11594 curMaxProcs += numServiceProcs;
11595
11596 // Quit as many processes as we can to get down to the desired
11597 // process count. First remove any processes that no longer
11598 // have activites running in them.
11599 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011600 i<mLruProcesses.size()
11601 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011603 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 // Quit an application only if it is not currently
11605 // running any activities.
11606 if (!app.persistent && app.activities.size() == 0
11607 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011608 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011609 TAG, "Exiting empty application process "
11610 + app.processName + " ("
11611 + (app.thread != null ? app.thread.asBinder() : null)
11612 + ")\n");
11613 if (app.pid > 0 && app.pid != MY_PID) {
11614 Process.killProcess(app.pid);
11615 } else {
11616 try {
11617 app.thread.scheduleExit();
11618 } catch (Exception e) {
11619 // Ignore exceptions.
11620 }
11621 }
11622 // todo: For now we assume the application is not buggy
11623 // or evil, and will quit as a result of our request.
11624 // Eventually we need to drive this off of the death
11625 // notification, and kill the process if it takes too long.
11626 cleanUpApplicationRecordLocked(app, false, i);
11627 i--;
11628 }
11629 }
11630
11631 // If we still have too many processes, now from the least
11632 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011633 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011634 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011635 " of " + curMaxProcs + " processes");
11636 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011637 i<mLruProcesses.size()
11638 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011640 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011641 // Quit the application only if we have a state saved for
11642 // all of its activities.
11643 boolean canQuit = !app.persistent && app.curReceiver == null
11644 && app.services.size() == 0
11645 && app.persistentActivities == 0;
11646 int NUMA = app.activities.size();
11647 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011648 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011649 TAG, "Looking to quit " + app.processName);
11650 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011651 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011652 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 TAG, " " + r.intent.getComponent().flattenToShortString()
11654 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11655 canQuit = (r.haveState || !r.stateNotNeeded)
11656 && !r.visible && r.stopped;
11657 }
11658 if (canQuit) {
11659 // Finish all of the activities, and then the app itself.
11660 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011661 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011662 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011663 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011664 }
11665 r.resultTo = null;
11666 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011667 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011668 + app.processName + " ("
11669 + (app.thread != null ? app.thread.asBinder() : null)
11670 + ")\n");
11671 if (app.pid > 0 && app.pid != MY_PID) {
11672 Process.killProcess(app.pid);
11673 } else {
11674 try {
11675 app.thread.scheduleExit();
11676 } catch (Exception e) {
11677 // Ignore exceptions.
11678 }
11679 }
11680 // todo: For now we assume the application is not buggy
11681 // or evil, and will quit as a result of our request.
11682 // Eventually we need to drive this off of the death
11683 // notification, and kill the process if it takes too long.
11684 cleanUpApplicationRecordLocked(app, false, i);
11685 i--;
11686 //dump();
11687 }
11688 }
11689
11690 }
11691
11692 int curMaxActivities = MAX_ACTIVITIES;
11693 if (mAlwaysFinishActivities) {
11694 curMaxActivities = 1;
11695 }
11696
11697 // Finally, if there are too many activities now running, try to
11698 // finish as many as we can to get back down to the limit.
11699 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011700 i<mMainStack.mLRUActivities.size()
11701 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011702 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011703 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011704 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011705
11706 // We can finish this one if we have its icicle saved and
11707 // it is not persistent.
11708 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11709 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011710 final int origSize = mMainStack.mLRUActivities.size();
11711 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712
11713 // This will remove it from the LRU list, so keep
11714 // our index at the same value. Note that this check to
11715 // see if the size changes is just paranoia -- if
11716 // something unexpected happens, we don't want to end up
11717 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011718 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011719 i--;
11720 }
11721 }
11722 }
11723 }
11724 }
11725
11726 /** This method sends the specified signal to each of the persistent apps */
11727 public void signalPersistentProcesses(int sig) throws RemoteException {
11728 if (sig != Process.SIGNAL_USR1) {
11729 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11730 }
11731
11732 synchronized (this) {
11733 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11734 != PackageManager.PERMISSION_GRANTED) {
11735 throw new SecurityException("Requires permission "
11736 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11737 }
11738
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011739 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11740 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011741 if (r.thread != null && r.persistent) {
11742 Process.sendSignal(r.pid, sig);
11743 }
11744 }
11745 }
11746 }
11747
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011748 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011749 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011750
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011751 try {
11752 synchronized (this) {
11753 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11754 // its own permission.
11755 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11756 != PackageManager.PERMISSION_GRANTED) {
11757 throw new SecurityException("Requires permission "
11758 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011759 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011760
11761 if (start && fd == null) {
11762 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011763 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011764
11765 ProcessRecord proc = null;
11766 try {
11767 int pid = Integer.parseInt(process);
11768 synchronized (mPidsSelfLocked) {
11769 proc = mPidsSelfLocked.get(pid);
11770 }
11771 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011772 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011773
11774 if (proc == null) {
11775 HashMap<String, SparseArray<ProcessRecord>> all
11776 = mProcessNames.getMap();
11777 SparseArray<ProcessRecord> procs = all.get(process);
11778 if (procs != null && procs.size() > 0) {
11779 proc = procs.valueAt(0);
11780 }
11781 }
11782
11783 if (proc == null || proc.thread == null) {
11784 throw new IllegalArgumentException("Unknown process: " + process);
11785 }
11786
11787 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11788 if (isSecure) {
11789 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11790 throw new SecurityException("Process not debuggable: " + proc);
11791 }
11792 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011793
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011794 proc.thread.profilerControl(start, path, fd);
11795 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011796 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011797 }
11798 } catch (RemoteException e) {
11799 throw new IllegalStateException("Process disappeared");
11800 } finally {
11801 if (fd != null) {
11802 try {
11803 fd.close();
11804 } catch (IOException e) {
11805 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011806 }
11807 }
11808 }
11809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011810 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11811 public void monitor() {
11812 synchronized (this) { }
11813 }
11814}