blob: d5353433e1c908e35ff536a2cdb826dda5577e03 [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 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700612 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
613 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614
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 Hackborn39792d22010-08-19 18:01:52 -07004096 /**
4097 * Check if the targetPkg can be granted permission to access uri by
4098 * the callingUid using the given modeFlags. Throws a security exception
4099 * if callingUid is not allowed to do this. Returns the uid of the target
4100 * if the URI permission grant should be performed; returns -1 if it is not
4101 * needed (for example targetPkg already has permission to access the URI).
4102 */
4103 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4104 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004105 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4106 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4107 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004108 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004109 }
4110
Joe Onorato8a9b2202010-02-26 18:56:32 -08004111 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004112 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004113
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004114 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115
4116 // If this is not a content: uri, we can't do anything with it.
4117 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004118 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004119 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004120 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 }
4122
4123 String name = uri.getAuthority();
4124 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004125 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004126 if (cpr != null) {
4127 pi = cpr.info;
4128 } else {
4129 try {
4130 pi = pm.resolveContentProvider(name,
4131 PackageManager.GET_URI_PERMISSION_PATTERNS);
4132 } catch (RemoteException ex) {
4133 }
4134 }
4135 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004136 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004137 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004138 }
4139
4140 int targetUid;
4141 try {
4142 targetUid = pm.getPackageUid(targetPkg);
4143 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004144 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004145 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004146 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004147 }
4148 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004149 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 }
4151
4152 // First... does the target actually need this permission?
4153 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4154 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004155 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004156 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004157 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 }
4159
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004160 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 if (!pi.grantUriPermissions) {
4162 throw new SecurityException("Provider " + pi.packageName
4163 + "/" + pi.name
4164 + " does not allow granting of Uri permissions (uri "
4165 + uri + ")");
4166 }
4167 if (pi.uriPermissionPatterns != null) {
4168 final int N = pi.uriPermissionPatterns.length;
4169 boolean allowed = false;
4170 for (int i=0; i<N; i++) {
4171 if (pi.uriPermissionPatterns[i] != null
4172 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4173 allowed = true;
4174 break;
4175 }
4176 }
4177 if (!allowed) {
4178 throw new SecurityException("Provider " + pi.packageName
4179 + "/" + pi.name
4180 + " does not allow granting of permission to path of Uri "
4181 + uri);
4182 }
4183 }
4184
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004185 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004186 // this uri?
4187 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4188 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4189 throw new SecurityException("Uid " + callingUid
4190 + " does not have permission to uri " + uri);
4191 }
4192 }
4193
Dianne Hackborn39792d22010-08-19 18:01:52 -07004194 return targetUid;
4195 }
4196
4197 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4198 Uri uri, int modeFlags, UriPermissionOwner owner) {
4199 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4200 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4201 if (modeFlags == 0) {
4202 return;
4203 }
4204
4205 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206 // to the uri, and the target doesn't. Let's now give this to
4207 // the target.
4208
Joe Onorato8a9b2202010-02-26 18:56:32 -08004209 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004210 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 HashMap<Uri, UriPermission> targetUris
4213 = mGrantedUriPermissions.get(targetUid);
4214 if (targetUris == null) {
4215 targetUris = new HashMap<Uri, UriPermission>();
4216 mGrantedUriPermissions.put(targetUid, targetUris);
4217 }
4218
4219 UriPermission perm = targetUris.get(uri);
4220 if (perm == null) {
4221 perm = new UriPermission(targetUid, uri);
4222 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004226 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 perm.globalModeFlags |= modeFlags;
4228 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004229 perm.readOwners.add(owner);
4230 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004231 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004232 perm.writeOwners.add(owner);
4233 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 }
4235 }
4236
Dianne Hackborn39792d22010-08-19 18:01:52 -07004237 void grantUriPermissionLocked(int callingUid,
4238 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4239 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4240 if (targetUid < 0) {
4241 return;
4242 }
4243
4244 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4245 }
4246
4247 /**
4248 * Like checkGrantUriPermissionLocked, but takes an Intent.
4249 */
4250 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4251 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004252 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004253 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004254 + " from " + intent + "; flags=0x"
4255 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004257 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004258 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 }
4260 Uri data = intent.getData();
4261 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004262 return -1;
4263 }
4264 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4265 intent.getFlags());
4266 }
4267
4268 /**
4269 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4270 */
4271 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4272 String targetPkg, Intent intent, UriPermissionOwner owner) {
4273 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4274 intent.getFlags(), owner);
4275 }
4276
4277 void grantUriPermissionFromIntentLocked(int callingUid,
4278 String targetPkg, Intent intent, UriPermissionOwner owner) {
4279 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4280 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 return;
4282 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004283
4284 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 }
4286
4287 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4288 Uri uri, int modeFlags) {
4289 synchronized(this) {
4290 final ProcessRecord r = getRecordForAppLocked(caller);
4291 if (r == null) {
4292 throw new SecurityException("Unable to find app for caller "
4293 + caller
4294 + " when granting permission to uri " + uri);
4295 }
4296 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004297 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 }
4299 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004300 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 }
4302
4303 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4304 null);
4305 }
4306 }
4307
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004308 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004309 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4310 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4311 HashMap<Uri, UriPermission> perms
4312 = mGrantedUriPermissions.get(perm.uid);
4313 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004314 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004315 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 perms.remove(perm.uri);
4317 if (perms.size() == 0) {
4318 mGrantedUriPermissions.remove(perm.uid);
4319 }
4320 }
4321 }
4322 }
4323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004324 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4325 int modeFlags) {
4326 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4327 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4328 if (modeFlags == 0) {
4329 return;
4330 }
4331
Joe Onorato8a9b2202010-02-26 18:56:32 -08004332 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004333 "Revoking all granted permissions to " + uri);
4334
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004335 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336
4337 final String authority = uri.getAuthority();
4338 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004339 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 if (cpr != null) {
4341 pi = cpr.info;
4342 } else {
4343 try {
4344 pi = pm.resolveContentProvider(authority,
4345 PackageManager.GET_URI_PERMISSION_PATTERNS);
4346 } catch (RemoteException ex) {
4347 }
4348 }
4349 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004350 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351 return;
4352 }
4353
4354 // Does the caller have this permission on the URI?
4355 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4356 // Right now, if you are not the original owner of the permission,
4357 // you are not allowed to revoke it.
4358 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4359 throw new SecurityException("Uid " + callingUid
4360 + " does not have permission to uri " + uri);
4361 //}
4362 }
4363
4364 // Go through all of the permissions and remove any that match.
4365 final List<String> SEGMENTS = uri.getPathSegments();
4366 if (SEGMENTS != null) {
4367 final int NS = SEGMENTS.size();
4368 int N = mGrantedUriPermissions.size();
4369 for (int i=0; i<N; i++) {
4370 HashMap<Uri, UriPermission> perms
4371 = mGrantedUriPermissions.valueAt(i);
4372 Iterator<UriPermission> it = perms.values().iterator();
4373 toploop:
4374 while (it.hasNext()) {
4375 UriPermission perm = it.next();
4376 Uri targetUri = perm.uri;
4377 if (!authority.equals(targetUri.getAuthority())) {
4378 continue;
4379 }
4380 List<String> targetSegments = targetUri.getPathSegments();
4381 if (targetSegments == null) {
4382 continue;
4383 }
4384 if (targetSegments.size() < NS) {
4385 continue;
4386 }
4387 for (int j=0; j<NS; j++) {
4388 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4389 continue toploop;
4390 }
4391 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004392 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004393 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 perm.clearModes(modeFlags);
4395 if (perm.modeFlags == 0) {
4396 it.remove();
4397 }
4398 }
4399 if (perms.size() == 0) {
4400 mGrantedUriPermissions.remove(
4401 mGrantedUriPermissions.keyAt(i));
4402 N--;
4403 i--;
4404 }
4405 }
4406 }
4407 }
4408
4409 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4410 int modeFlags) {
4411 synchronized(this) {
4412 final ProcessRecord r = getRecordForAppLocked(caller);
4413 if (r == null) {
4414 throw new SecurityException("Unable to find app for caller "
4415 + caller
4416 + " when revoking permission to uri " + uri);
4417 }
4418 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004419 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004420 return;
4421 }
4422
4423 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4424 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4425 if (modeFlags == 0) {
4426 return;
4427 }
4428
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004429 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004430
4431 final String authority = uri.getAuthority();
4432 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004433 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434 if (cpr != null) {
4435 pi = cpr.info;
4436 } else {
4437 try {
4438 pi = pm.resolveContentProvider(authority,
4439 PackageManager.GET_URI_PERMISSION_PATTERNS);
4440 } catch (RemoteException ex) {
4441 }
4442 }
4443 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004444 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445 return;
4446 }
4447
4448 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4449 }
4450 }
4451
Dianne Hackborn7e269642010-08-25 19:50:20 -07004452 @Override
4453 public IBinder newUriPermissionOwner(String name) {
4454 synchronized(this) {
4455 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4456 return owner.getExternalTokenLocked();
4457 }
4458 }
4459
4460 @Override
4461 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4462 Uri uri, int modeFlags) {
4463 synchronized(this) {
4464 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4465 if (owner == null) {
4466 throw new IllegalArgumentException("Unknown owner: " + token);
4467 }
4468 if (fromUid != Binder.getCallingUid()) {
4469 if (Binder.getCallingUid() != Process.myUid()) {
4470 // Only system code can grant URI permissions on behalf
4471 // of other users.
4472 throw new SecurityException("nice try");
4473 }
4474 }
4475 if (targetPkg == null) {
4476 throw new IllegalArgumentException("null target");
4477 }
4478 if (uri == null) {
4479 throw new IllegalArgumentException("null uri");
4480 }
4481
4482 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4483 }
4484 }
4485
4486 @Override
4487 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4488 synchronized(this) {
4489 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4490 if (owner == null) {
4491 throw new IllegalArgumentException("Unknown owner: " + token);
4492 }
4493
4494 if (uri == null) {
4495 owner.removeUriPermissionsLocked(mode);
4496 } else {
4497 owner.removeUriPermissionLocked(uri, mode);
4498 }
4499 }
4500 }
4501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4503 synchronized (this) {
4504 ProcessRecord app =
4505 who != null ? getRecordForAppLocked(who) : null;
4506 if (app == null) return;
4507
4508 Message msg = Message.obtain();
4509 msg.what = WAIT_FOR_DEBUGGER_MSG;
4510 msg.obj = app;
4511 msg.arg1 = waiting ? 1 : 0;
4512 mHandler.sendMessage(msg);
4513 }
4514 }
4515
4516 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4517 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004518 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004520 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 }
4522
4523 // =========================================================
4524 // TASK MANAGEMENT
4525 // =========================================================
4526
4527 public List getTasks(int maxNum, int flags,
4528 IThumbnailReceiver receiver) {
4529 ArrayList list = new ArrayList();
4530
4531 PendingThumbnailsRecord pending = null;
4532 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004533 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534
4535 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004536 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4538 + ", receiver=" + receiver);
4539
4540 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4541 != PackageManager.PERMISSION_GRANTED) {
4542 if (receiver != null) {
4543 // If the caller wants to wait for pending thumbnails,
4544 // it ain't gonna get them.
4545 try {
4546 receiver.finished();
4547 } catch (RemoteException ex) {
4548 }
4549 }
4550 String msg = "Permission Denial: getTasks() from pid="
4551 + Binder.getCallingPid()
4552 + ", uid=" + Binder.getCallingUid()
4553 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004554 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004555 throw new SecurityException(msg);
4556 }
4557
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004558 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004559 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004560 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004561 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 CharSequence topDescription = null;
4563 TaskRecord curTask = null;
4564 int numActivities = 0;
4565 int numRunning = 0;
4566 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004567 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004569 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004570
4571 // Initialize state for next task if needed.
4572 if (top == null ||
4573 (top.state == ActivityState.INITIALIZING
4574 && top.task == r.task)) {
4575 top = r;
4576 topDescription = r.description;
4577 curTask = r.task;
4578 numActivities = numRunning = 0;
4579 }
4580
4581 // Add 'r' into the current task.
4582 numActivities++;
4583 if (r.app != null && r.app.thread != null) {
4584 numRunning++;
4585 }
4586 if (topDescription == null) {
4587 topDescription = r.description;
4588 }
4589
Joe Onorato8a9b2202010-02-26 18:56:32 -08004590 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 TAG, r.intent.getComponent().flattenToShortString()
4592 + ": task=" + r.task);
4593
4594 // If the next one is a different task, generate a new
4595 // TaskInfo entry for what we have.
4596 if (next == null || next.task != curTask) {
4597 ActivityManager.RunningTaskInfo ci
4598 = new ActivityManager.RunningTaskInfo();
4599 ci.id = curTask.taskId;
4600 ci.baseActivity = r.intent.getComponent();
4601 ci.topActivity = top.intent.getComponent();
4602 ci.thumbnail = top.thumbnail;
4603 ci.description = topDescription;
4604 ci.numActivities = numActivities;
4605 ci.numRunning = numRunning;
4606 //System.out.println(
4607 // "#" + maxNum + ": " + " descr=" + ci.description);
4608 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004609 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 TAG, "State=" + top.state + "Idle=" + top.idle
4611 + " app=" + top.app
4612 + " thr=" + (top.app != null ? top.app.thread : null));
4613 if (top.state == ActivityState.RESUMED
4614 || top.state == ActivityState.PAUSING) {
4615 if (top.idle && top.app != null
4616 && top.app.thread != null) {
4617 topRecord = top;
4618 topThumbnail = top.app.thread;
4619 } else {
4620 top.thumbnailNeeded = true;
4621 }
4622 }
4623 if (pending == null) {
4624 pending = new PendingThumbnailsRecord(receiver);
4625 }
4626 pending.pendingRecords.add(top);
4627 }
4628 list.add(ci);
4629 maxNum--;
4630 top = null;
4631 }
4632 }
4633
4634 if (pending != null) {
4635 mPendingThumbnails.add(pending);
4636 }
4637 }
4638
Joe Onorato8a9b2202010-02-26 18:56:32 -08004639 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640
4641 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004642 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 try {
4644 topThumbnail.requestThumbnail(topRecord);
4645 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004646 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 sendPendingThumbnail(null, topRecord, null, null, true);
4648 }
4649 }
4650
4651 if (pending == null && receiver != null) {
4652 // In this case all thumbnails were available and the client
4653 // is being asked to be told when the remaining ones come in...
4654 // which is unusually, since the top-most currently running
4655 // activity should never have a canned thumbnail! Oh well.
4656 try {
4657 receiver.finished();
4658 } catch (RemoteException ex) {
4659 }
4660 }
4661
4662 return list;
4663 }
4664
4665 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4666 int flags) {
4667 synchronized (this) {
4668 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4669 "getRecentTasks()");
4670
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004671 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 final int N = mRecentTasks.size();
4674 ArrayList<ActivityManager.RecentTaskInfo> res
4675 = new ArrayList<ActivityManager.RecentTaskInfo>(
4676 maxNum < N ? maxNum : N);
4677 for (int i=0; i<N && maxNum > 0; i++) {
4678 TaskRecord tr = mRecentTasks.get(i);
4679 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4680 || (tr.intent == null)
4681 || ((tr.intent.getFlags()
4682 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4683 ActivityManager.RecentTaskInfo rti
4684 = new ActivityManager.RecentTaskInfo();
4685 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4686 rti.baseIntent = new Intent(
4687 tr.intent != null ? tr.intent : tr.affinityIntent);
4688 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004689
4690 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4691 // Check whether this activity is currently available.
4692 try {
4693 if (rti.origActivity != null) {
4694 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4695 continue;
4696 }
4697 } else if (rti.baseIntent != null) {
4698 if (pm.queryIntentActivities(rti.baseIntent,
4699 null, 0) == null) {
4700 continue;
4701 }
4702 }
4703 } catch (RemoteException e) {
4704 // Will never happen.
4705 }
4706 }
4707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708 res.add(rti);
4709 maxNum--;
4710 }
4711 }
4712 return res;
4713 }
4714 }
4715
4716 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4717 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004718 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719 TaskRecord jt = startTask;
4720
4721 // First look backwards
4722 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004723 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 if (r.task != jt) {
4725 jt = r.task;
4726 if (affinity.equals(jt.affinity)) {
4727 return j;
4728 }
4729 }
4730 }
4731
4732 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004733 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 jt = startTask;
4735 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004736 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004737 if (r.task != jt) {
4738 if (affinity.equals(jt.affinity)) {
4739 return j;
4740 }
4741 jt = r.task;
4742 }
4743 }
4744
4745 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004746 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 return N-1;
4748 }
4749
4750 return -1;
4751 }
4752
4753 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004754 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004755 */
4756 public void moveTaskToFront(int task) {
4757 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4758 "moveTaskToFront()");
4759
4760 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004761 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4762 Binder.getCallingUid(), "Task to front")) {
4763 return;
4764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 final long origId = Binder.clearCallingIdentity();
4766 try {
4767 int N = mRecentTasks.size();
4768 for (int i=0; i<N; i++) {
4769 TaskRecord tr = mRecentTasks.get(i);
4770 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004771 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004772 return;
4773 }
4774 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004775 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4776 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004778 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004779 return;
4780 }
4781 }
4782 } finally {
4783 Binder.restoreCallingIdentity(origId);
4784 }
4785 }
4786 }
4787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 public void moveTaskToBack(int task) {
4789 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4790 "moveTaskToBack()");
4791
4792 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004793 if (mMainStack.mResumedActivity != null
4794 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004795 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4796 Binder.getCallingUid(), "Task to back")) {
4797 return;
4798 }
4799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004801 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004802 Binder.restoreCallingIdentity(origId);
4803 }
4804 }
4805
4806 /**
4807 * Moves an activity, and all of the other activities within the same task, to the bottom
4808 * of the history stack. The activity's order within the task is unchanged.
4809 *
4810 * @param token A reference to the activity we wish to move
4811 * @param nonRoot If false then this only works if the activity is the root
4812 * of a task; if true it will work for any activity in a task.
4813 * @return Returns true if the move completed, false if not.
4814 */
4815 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4816 synchronized(this) {
4817 final long origId = Binder.clearCallingIdentity();
4818 int taskId = getTaskForActivityLocked(token, !nonRoot);
4819 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004820 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004821 }
4822 Binder.restoreCallingIdentity(origId);
4823 }
4824 return false;
4825 }
4826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 public void moveTaskBackwards(int task) {
4828 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4829 "moveTaskBackwards()");
4830
4831 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004832 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4833 Binder.getCallingUid(), "Task backwards")) {
4834 return;
4835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004836 final long origId = Binder.clearCallingIdentity();
4837 moveTaskBackwardsLocked(task);
4838 Binder.restoreCallingIdentity(origId);
4839 }
4840 }
4841
4842 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004843 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 }
4845
4846 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4847 synchronized(this) {
4848 return getTaskForActivityLocked(token, onlyRoot);
4849 }
4850 }
4851
4852 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004853 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004854 TaskRecord lastTask = null;
4855 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004856 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857 if (r == token) {
4858 if (!onlyRoot || lastTask != r.task) {
4859 return r.task.taskId;
4860 }
4861 return -1;
4862 }
4863 lastTask = r.task;
4864 }
4865
4866 return -1;
4867 }
4868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869 public void finishOtherInstances(IBinder token, ComponentName className) {
4870 synchronized(this) {
4871 final long origId = Binder.clearCallingIdentity();
4872
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004873 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 TaskRecord lastTask = null;
4875 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004876 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004877 if (r.realActivity.equals(className)
4878 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004879 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 null, "others")) {
4881 i--;
4882 N--;
4883 }
4884 }
4885 lastTask = r.task;
4886 }
4887
4888 Binder.restoreCallingIdentity(origId);
4889 }
4890 }
4891
4892 // =========================================================
4893 // THUMBNAILS
4894 // =========================================================
4895
4896 public void reportThumbnail(IBinder token,
4897 Bitmap thumbnail, CharSequence description) {
4898 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4899 final long origId = Binder.clearCallingIdentity();
4900 sendPendingThumbnail(null, token, thumbnail, description, true);
4901 Binder.restoreCallingIdentity(origId);
4902 }
4903
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004904 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 Bitmap thumbnail, CharSequence description, boolean always) {
4906 TaskRecord task = null;
4907 ArrayList receivers = null;
4908
4909 //System.out.println("Send pending thumbnail: " + r);
4910
4911 synchronized(this) {
4912 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004913 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 if (index < 0) {
4915 return;
4916 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004917 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 }
4919 if (thumbnail == null) {
4920 thumbnail = r.thumbnail;
4921 description = r.description;
4922 }
4923 if (thumbnail == null && !always) {
4924 // If there is no thumbnail, and this entry is not actually
4925 // going away, then abort for now and pick up the next
4926 // thumbnail we get.
4927 return;
4928 }
4929 task = r.task;
4930
4931 int N = mPendingThumbnails.size();
4932 int i=0;
4933 while (i<N) {
4934 PendingThumbnailsRecord pr =
4935 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4936 //System.out.println("Looking in " + pr.pendingRecords);
4937 if (pr.pendingRecords.remove(r)) {
4938 if (receivers == null) {
4939 receivers = new ArrayList();
4940 }
4941 receivers.add(pr);
4942 if (pr.pendingRecords.size() == 0) {
4943 pr.finished = true;
4944 mPendingThumbnails.remove(i);
4945 N--;
4946 continue;
4947 }
4948 }
4949 i++;
4950 }
4951 }
4952
4953 if (receivers != null) {
4954 final int N = receivers.size();
4955 for (int i=0; i<N; i++) {
4956 try {
4957 PendingThumbnailsRecord pr =
4958 (PendingThumbnailsRecord)receivers.get(i);
4959 pr.receiver.newThumbnail(
4960 task != null ? task.taskId : -1, thumbnail, description);
4961 if (pr.finished) {
4962 pr.receiver.finished();
4963 }
4964 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004965 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004966 }
4967 }
4968 }
4969 }
4970
4971 // =========================================================
4972 // CONTENT PROVIDERS
4973 // =========================================================
4974
4975 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4976 List providers = null;
4977 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004978 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004980 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004981 } catch (RemoteException ex) {
4982 }
4983 if (providers != null) {
4984 final int N = providers.size();
4985 for (int i=0; i<N; i++) {
4986 ProviderInfo cpi =
4987 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004988 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 if (cpr == null) {
4990 cpr = new ContentProviderRecord(cpi, app.info);
4991 mProvidersByClass.put(cpi.name, cpr);
4992 }
4993 app.pubProviders.put(cpi.name, cpr);
4994 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004995 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 }
4997 }
4998 return providers;
4999 }
5000
5001 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005002 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005003 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5004 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5005 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5006 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005007 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 return null;
5009 }
5010 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5011 cpi.exported ? -1 : cpi.applicationInfo.uid)
5012 == PackageManager.PERMISSION_GRANTED) {
5013 return null;
5014 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005015
5016 PathPermission[] pps = cpi.pathPermissions;
5017 if (pps != null) {
5018 int i = pps.length;
5019 while (i > 0) {
5020 i--;
5021 PathPermission pp = pps[i];
5022 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5023 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005024 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005025 return null;
5026 }
5027 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5028 cpi.exported ? -1 : cpi.applicationInfo.uid)
5029 == PackageManager.PERMISSION_GRANTED) {
5030 return null;
5031 }
5032 }
5033 }
5034
Dianne Hackbornb424b632010-08-18 15:59:05 -07005035 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5036 if (perms != null) {
5037 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5038 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5039 return null;
5040 }
5041 }
5042 }
5043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005044 String msg = "Permission Denial: opening provider " + cpi.name
5045 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5046 + ", uid=" + callingUid + ") requires "
5047 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005048 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 return msg;
5050 }
5051
5052 private final ContentProviderHolder getContentProviderImpl(
5053 IApplicationThread caller, String name) {
5054 ContentProviderRecord cpr;
5055 ProviderInfo cpi = null;
5056
5057 synchronized(this) {
5058 ProcessRecord r = null;
5059 if (caller != null) {
5060 r = getRecordForAppLocked(caller);
5061 if (r == null) {
5062 throw new SecurityException(
5063 "Unable to find app for caller " + caller
5064 + " (pid=" + Binder.getCallingPid()
5065 + ") when getting content provider " + name);
5066 }
5067 }
5068
5069 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005070 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 if (cpr != null) {
5072 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005073 String msg;
5074 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5075 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 }
5077
5078 if (r != null && cpr.canRunHere(r)) {
5079 // This provider has been published or is in the process
5080 // of being published... but it is also allowed to run
5081 // in the caller's process, so don't make a connection
5082 // and just let the caller instantiate its own instance.
5083 if (cpr.provider != null) {
5084 // don't give caller the provider object, it needs
5085 // to make its own.
5086 cpr = new ContentProviderRecord(cpr);
5087 }
5088 return cpr;
5089 }
5090
5091 final long origId = Binder.clearCallingIdentity();
5092
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005093 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005094 // return it right away.
5095 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005096 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005097 "Adding provider requested by "
5098 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005099 + cpr.info.processName);
5100 Integer cnt = r.conProviders.get(cpr);
5101 if (cnt == null) {
5102 r.conProviders.put(cpr, new Integer(1));
5103 } else {
5104 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5105 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005106 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005107 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5108 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005109 // make sure to count it as being accessed and thus
5110 // back up on the LRU list. This is good because
5111 // content providers are often expensive to start.
5112 updateLruProcessLocked(cpr.app, false, true);
5113 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005114 } else {
5115 cpr.externals++;
5116 }
5117
5118 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 updateOomAdjLocked(cpr.app);
5120 }
5121
5122 Binder.restoreCallingIdentity(origId);
5123
5124 } else {
5125 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005126 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005127 resolveContentProvider(name,
5128 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005129 } catch (RemoteException ex) {
5130 }
5131 if (cpi == null) {
5132 return null;
5133 }
5134
Dianne Hackbornb424b632010-08-18 15:59:05 -07005135 String msg;
5136 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5137 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 }
5139
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005140 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5141 && !cpi.processName.equals("system")) {
5142 // If this content provider does not run in the system
5143 // process, and the system is not yet ready to run other
5144 // processes, then fail fast instead of hanging.
5145 throw new IllegalArgumentException(
5146 "Attempt to launch content provider before system ready");
5147 }
5148
Dianne Hackborn860755f2010-06-03 18:47:52 -07005149 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005150 final boolean firstClass = cpr == null;
5151 if (firstClass) {
5152 try {
5153 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005154 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005155 getApplicationInfo(
5156 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005157 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005158 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005159 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 + cpi.name);
5161 return null;
5162 }
5163 cpr = new ContentProviderRecord(cpi, ai);
5164 } catch (RemoteException ex) {
5165 // pm is in same process, this will never happen.
5166 }
5167 }
5168
5169 if (r != null && cpr.canRunHere(r)) {
5170 // If this is a multiprocess provider, then just return its
5171 // info and allow the caller to instantiate it. Only do
5172 // this if the provider is the same user as the caller's
5173 // process, or can run as root (so can be in any process).
5174 return cpr;
5175 }
5176
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005177 if (DEBUG_PROVIDER) {
5178 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005179 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005180 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 }
5182
5183 // This is single process, and our app is now connecting to it.
5184 // See if we are already in the process of launching this
5185 // provider.
5186 final int N = mLaunchingProviders.size();
5187 int i;
5188 for (i=0; i<N; i++) {
5189 if (mLaunchingProviders.get(i) == cpr) {
5190 break;
5191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 }
5193
5194 // If the provider is not already being launched, then get it
5195 // started.
5196 if (i >= N) {
5197 final long origId = Binder.clearCallingIdentity();
5198 ProcessRecord proc = startProcessLocked(cpi.processName,
5199 cpr.appInfo, false, 0, "content provider",
5200 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005201 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005203 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005204 + cpi.applicationInfo.packageName + "/"
5205 + cpi.applicationInfo.uid + " for provider "
5206 + name + ": process is bad");
5207 return null;
5208 }
5209 cpr.launchingApp = proc;
5210 mLaunchingProviders.add(cpr);
5211 Binder.restoreCallingIdentity(origId);
5212 }
5213
5214 // Make sure the provider is published (the same provider class
5215 // may be published under multiple names).
5216 if (firstClass) {
5217 mProvidersByClass.put(cpi.name, cpr);
5218 }
5219 mProvidersByName.put(name, cpr);
5220
5221 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005222 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005223 "Adding provider requested by "
5224 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005225 + cpr.info.processName);
5226 Integer cnt = r.conProviders.get(cpr);
5227 if (cnt == null) {
5228 r.conProviders.put(cpr, new Integer(1));
5229 } else {
5230 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 cpr.clients.add(r);
5233 } else {
5234 cpr.externals++;
5235 }
5236 }
5237 }
5238
5239 // Wait for the provider to be published...
5240 synchronized (cpr) {
5241 while (cpr.provider == null) {
5242 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005243 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005244 + cpi.applicationInfo.packageName + "/"
5245 + cpi.applicationInfo.uid + " for provider "
5246 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005247 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 cpi.applicationInfo.packageName,
5249 cpi.applicationInfo.uid, name);
5250 return null;
5251 }
5252 try {
5253 cpr.wait();
5254 } catch (InterruptedException ex) {
5255 }
5256 }
5257 }
5258 return cpr;
5259 }
5260
5261 public final ContentProviderHolder getContentProvider(
5262 IApplicationThread caller, String name) {
5263 if (caller == null) {
5264 String msg = "null IApplicationThread when getting content provider "
5265 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005266 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005267 throw new SecurityException(msg);
5268 }
5269
5270 return getContentProviderImpl(caller, name);
5271 }
5272
5273 private ContentProviderHolder getContentProviderExternal(String name) {
5274 return getContentProviderImpl(null, name);
5275 }
5276
5277 /**
5278 * Drop a content provider from a ProcessRecord's bookkeeping
5279 * @param cpr
5280 */
5281 public void removeContentProvider(IApplicationThread caller, String name) {
5282 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005283 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005285 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005286 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005287 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 return;
5289 }
5290 final ProcessRecord r = getRecordForAppLocked(caller);
5291 if (r == null) {
5292 throw new SecurityException(
5293 "Unable to find app for caller " + caller +
5294 " when removing content provider " + name);
5295 }
5296 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005297 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005298 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005299 + r.info.processName + " from process "
5300 + localCpr.appInfo.processName);
5301 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005303 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005304 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 return;
5306 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005307 Integer cnt = r.conProviders.get(localCpr);
5308 if (cnt == null || cnt.intValue() <= 1) {
5309 localCpr.clients.remove(r);
5310 r.conProviders.remove(localCpr);
5311 } else {
5312 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 }
5315 updateOomAdjLocked();
5316 }
5317 }
5318
5319 private void removeContentProviderExternal(String name) {
5320 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005321 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 if(cpr == null) {
5323 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005324 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005325 return;
5326 }
5327
5328 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005329 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 localCpr.externals--;
5331 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005332 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005333 }
5334 updateOomAdjLocked();
5335 }
5336 }
5337
5338 public final void publishContentProviders(IApplicationThread caller,
5339 List<ContentProviderHolder> providers) {
5340 if (providers == null) {
5341 return;
5342 }
5343
5344 synchronized(this) {
5345 final ProcessRecord r = getRecordForAppLocked(caller);
5346 if (r == null) {
5347 throw new SecurityException(
5348 "Unable to find app for caller " + caller
5349 + " (pid=" + Binder.getCallingPid()
5350 + ") when publishing content providers");
5351 }
5352
5353 final long origId = Binder.clearCallingIdentity();
5354
5355 final int N = providers.size();
5356 for (int i=0; i<N; i++) {
5357 ContentProviderHolder src = providers.get(i);
5358 if (src == null || src.info == null || src.provider == null) {
5359 continue;
5360 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005361 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362 if (dst != null) {
5363 mProvidersByClass.put(dst.info.name, dst);
5364 String names[] = dst.info.authority.split(";");
5365 for (int j = 0; j < names.length; j++) {
5366 mProvidersByName.put(names[j], dst);
5367 }
5368
5369 int NL = mLaunchingProviders.size();
5370 int j;
5371 for (j=0; j<NL; j++) {
5372 if (mLaunchingProviders.get(j) == dst) {
5373 mLaunchingProviders.remove(j);
5374 j--;
5375 NL--;
5376 }
5377 }
5378 synchronized (dst) {
5379 dst.provider = src.provider;
5380 dst.app = r;
5381 dst.notifyAll();
5382 }
5383 updateOomAdjLocked(r);
5384 }
5385 }
5386
5387 Binder.restoreCallingIdentity(origId);
5388 }
5389 }
5390
5391 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005392 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005393 synchronized (mSelf) {
5394 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5395 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005396 if (providers != null) {
5397 for (int i=providers.size()-1; i>=0; i--) {
5398 ProviderInfo pi = (ProviderInfo)providers.get(i);
5399 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5400 Slog.w(TAG, "Not installing system proc provider " + pi.name
5401 + ": not system .apk");
5402 providers.remove(i);
5403 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005404 }
5405 }
5406 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005407 if (providers != null) {
5408 mSystemThread.installSystemProviders(providers);
5409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 }
5411
5412 // =========================================================
5413 // GLOBAL MANAGEMENT
5414 // =========================================================
5415
5416 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5417 ApplicationInfo info, String customProcess) {
5418 String proc = customProcess != null ? customProcess : info.processName;
5419 BatteryStatsImpl.Uid.Proc ps = null;
5420 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5421 synchronized (stats) {
5422 ps = stats.getProcessStatsLocked(info.uid, proc);
5423 }
5424 return new ProcessRecord(ps, thread, info, proc);
5425 }
5426
5427 final ProcessRecord addAppLocked(ApplicationInfo info) {
5428 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5429
5430 if (app == null) {
5431 app = newProcessRecordLocked(null, info, null);
5432 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005433 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005434 }
5435
5436 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5437 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5438 app.persistent = true;
5439 app.maxAdj = CORE_SERVER_ADJ;
5440 }
5441 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5442 mPersistentStartingProcesses.add(app);
5443 startProcessLocked(app, "added application", app.processName);
5444 }
5445
5446 return app;
5447 }
5448
5449 public void unhandledBack() {
5450 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5451 "unhandledBack()");
5452
5453 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005454 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005455 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005456 TAG, "Performing unhandledBack(): stack size = " + count);
5457 if (count > 1) {
5458 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005459 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005460 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5461 Binder.restoreCallingIdentity(origId);
5462 }
5463 }
5464 }
5465
5466 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5467 String name = uri.getAuthority();
5468 ContentProviderHolder cph = getContentProviderExternal(name);
5469 ParcelFileDescriptor pfd = null;
5470 if (cph != null) {
5471 // We record the binder invoker's uid in thread-local storage before
5472 // going to the content provider to open the file. Later, in the code
5473 // that handles all permissions checks, we look for this uid and use
5474 // that rather than the Activity Manager's own uid. The effect is that
5475 // we do the check against the caller's permissions even though it looks
5476 // to the content provider like the Activity Manager itself is making
5477 // the request.
5478 sCallerIdentity.set(new Identity(
5479 Binder.getCallingPid(), Binder.getCallingUid()));
5480 try {
5481 pfd = cph.provider.openFile(uri, "r");
5482 } catch (FileNotFoundException e) {
5483 // do nothing; pfd will be returned null
5484 } finally {
5485 // Ensure that whatever happens, we clean up the identity state
5486 sCallerIdentity.remove();
5487 }
5488
5489 // We've got the fd now, so we're done with the provider.
5490 removeContentProviderExternal(name);
5491 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005492 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 }
5494 return pfd;
5495 }
5496
5497 public void goingToSleep() {
5498 synchronized(this) {
5499 mSleeping = true;
5500 mWindowManager.setEventDispatching(false);
5501
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005502 if (mMainStack.mResumedActivity != null) {
5503 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005505 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005506 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005507
5508 // Initialize the wake times of all processes.
5509 checkExcessiveWakeLocksLocked(false);
5510 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5511 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5512 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 }
5514 }
5515
Dianne Hackborn55280a92009-05-07 15:53:46 -07005516 public boolean shutdown(int timeout) {
5517 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5518 != PackageManager.PERMISSION_GRANTED) {
5519 throw new SecurityException("Requires permission "
5520 + android.Manifest.permission.SHUTDOWN);
5521 }
5522
5523 boolean timedout = false;
5524
5525 synchronized(this) {
5526 mShuttingDown = true;
5527 mWindowManager.setEventDispatching(false);
5528
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005529 if (mMainStack.mResumedActivity != null) {
5530 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005531 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005532 while (mMainStack.mResumedActivity != null
5533 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005534 long delay = endTime - System.currentTimeMillis();
5535 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005536 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005537 timedout = true;
5538 break;
5539 }
5540 try {
5541 this.wait();
5542 } catch (InterruptedException e) {
5543 }
5544 }
5545 }
5546 }
5547
5548 mUsageStatsService.shutdown();
5549 mBatteryStatsService.shutdown();
5550
5551 return timedout;
5552 }
5553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005554 public void wakingUp() {
5555 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005556 if (mMainStack.mGoingToSleep.isHeld()) {
5557 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 }
5559 mWindowManager.setEventDispatching(true);
5560 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005561 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005562 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563 }
5564 }
5565
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005566 public void stopAppSwitches() {
5567 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5568 != PackageManager.PERMISSION_GRANTED) {
5569 throw new SecurityException("Requires permission "
5570 + android.Manifest.permission.STOP_APP_SWITCHES);
5571 }
5572
5573 synchronized(this) {
5574 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5575 + APP_SWITCH_DELAY_TIME;
5576 mDidAppSwitch = false;
5577 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5578 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5579 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5580 }
5581 }
5582
5583 public void resumeAppSwitches() {
5584 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5585 != PackageManager.PERMISSION_GRANTED) {
5586 throw new SecurityException("Requires permission "
5587 + android.Manifest.permission.STOP_APP_SWITCHES);
5588 }
5589
5590 synchronized(this) {
5591 // Note that we don't execute any pending app switches... we will
5592 // let those wait until either the timeout, or the next start
5593 // activity request.
5594 mAppSwitchesAllowedTime = 0;
5595 }
5596 }
5597
5598 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5599 String name) {
5600 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5601 return true;
5602 }
5603
5604 final int perm = checkComponentPermission(
5605 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5606 callingUid, -1);
5607 if (perm == PackageManager.PERMISSION_GRANTED) {
5608 return true;
5609 }
5610
Joe Onorato8a9b2202010-02-26 18:56:32 -08005611 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005612 return false;
5613 }
5614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 public void setDebugApp(String packageName, boolean waitForDebugger,
5616 boolean persistent) {
5617 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5618 "setDebugApp()");
5619
5620 // Note that this is not really thread safe if there are multiple
5621 // callers into it at the same time, but that's not a situation we
5622 // care about.
5623 if (persistent) {
5624 final ContentResolver resolver = mContext.getContentResolver();
5625 Settings.System.putString(
5626 resolver, Settings.System.DEBUG_APP,
5627 packageName);
5628 Settings.System.putInt(
5629 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5630 waitForDebugger ? 1 : 0);
5631 }
5632
5633 synchronized (this) {
5634 if (!persistent) {
5635 mOrigDebugApp = mDebugApp;
5636 mOrigWaitForDebugger = mWaitForDebugger;
5637 }
5638 mDebugApp = packageName;
5639 mWaitForDebugger = waitForDebugger;
5640 mDebugTransient = !persistent;
5641 if (packageName != null) {
5642 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005643 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005644 Binder.restoreCallingIdentity(origId);
5645 }
5646 }
5647 }
5648
5649 public void setAlwaysFinish(boolean enabled) {
5650 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5651 "setAlwaysFinish()");
5652
5653 Settings.System.putInt(
5654 mContext.getContentResolver(),
5655 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5656
5657 synchronized (this) {
5658 mAlwaysFinishActivities = enabled;
5659 }
5660 }
5661
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005662 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005663 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005664 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005666 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 }
5668 }
5669
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005670 public boolean isUserAMonkey() {
5671 // For now the fact that there is a controller implies
5672 // we have a monkey.
5673 synchronized (this) {
5674 return mController != null;
5675 }
5676 }
5677
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005678 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005679 synchronized (this) {
5680 mWatchers.register(watcher);
5681 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005682 }
5683
5684 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005685 synchronized (this) {
5686 mWatchers.unregister(watcher);
5687 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005688 }
5689
Daniel Sandler69a48172010-06-23 16:29:36 -04005690 public void setImmersive(IBinder token, boolean immersive) {
5691 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005692 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005693 if (index < 0) {
5694 throw new IllegalArgumentException();
5695 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005696 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005697 r.immersive = immersive;
5698 }
5699 }
5700
5701 public boolean isImmersive(IBinder token) {
5702 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005703 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005704 if (index < 0) {
5705 throw new IllegalArgumentException();
5706 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005707 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005708 return r.immersive;
5709 }
5710 }
5711
5712 public boolean isTopActivityImmersive() {
5713 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005714 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005715 return (r != null) ? r.immersive : false;
5716 }
5717 }
5718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 public final void enterSafeMode() {
5720 synchronized(this) {
5721 // It only makes sense to do this before the system is ready
5722 // and started launching other packages.
5723 if (!mSystemReady) {
5724 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005725 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 } catch (RemoteException e) {
5727 }
5728
5729 View v = LayoutInflater.from(mContext).inflate(
5730 com.android.internal.R.layout.safe_mode, null);
5731 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5732 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5733 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5734 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5735 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5736 lp.format = v.getBackground().getOpacity();
5737 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5738 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5739 ((WindowManager)mContext.getSystemService(
5740 Context.WINDOW_SERVICE)).addView(v, lp);
5741 }
5742 }
5743 }
5744
5745 public void noteWakeupAlarm(IIntentSender sender) {
5746 if (!(sender instanceof PendingIntentRecord)) {
5747 return;
5748 }
5749 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5750 synchronized (stats) {
5751 if (mBatteryStatsService.isOnBattery()) {
5752 mBatteryStatsService.enforceCallingPermission();
5753 PendingIntentRecord rec = (PendingIntentRecord)sender;
5754 int MY_UID = Binder.getCallingUid();
5755 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5756 BatteryStatsImpl.Uid.Pkg pkg =
5757 stats.getPackageStatsLocked(uid, rec.key.packageName);
5758 pkg.incWakeupsLocked();
5759 }
5760 }
5761 }
5762
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005763 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005764 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005765 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005766 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005767 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005768 // XXX Note: don't acquire main activity lock here, because the window
5769 // manager calls in with its locks held.
5770
5771 boolean killed = false;
5772 synchronized (mPidsSelfLocked) {
5773 int[] types = new int[pids.length];
5774 int worstType = 0;
5775 for (int i=0; i<pids.length; i++) {
5776 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5777 if (proc != null) {
5778 int type = proc.setAdj;
5779 types[i] = type;
5780 if (type > worstType) {
5781 worstType = type;
5782 }
5783 }
5784 }
5785
5786 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5787 // then constrain it so we will kill all hidden procs.
5788 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5789 worstType = HIDDEN_APP_MIN_ADJ;
5790 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005791 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005792 for (int i=0; i<pids.length; i++) {
5793 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5794 if (proc == null) {
5795 continue;
5796 }
5797 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005798 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005799 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005800 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5801 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005803 proc.killedBackground = true;
5804 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005805 }
5806 }
5807 }
5808 return killed;
5809 }
5810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 public final void startRunning(String pkg, String cls, String action,
5812 String data) {
5813 synchronized(this) {
5814 if (mStartRunning) {
5815 return;
5816 }
5817 mStartRunning = true;
5818 mTopComponent = pkg != null && cls != null
5819 ? new ComponentName(pkg, cls) : null;
5820 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5821 mTopData = data;
5822 if (!mSystemReady) {
5823 return;
5824 }
5825 }
5826
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005827 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 }
5829
5830 private void retrieveSettings() {
5831 final ContentResolver resolver = mContext.getContentResolver();
5832 String debugApp = Settings.System.getString(
5833 resolver, Settings.System.DEBUG_APP);
5834 boolean waitForDebugger = Settings.System.getInt(
5835 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5836 boolean alwaysFinishActivities = Settings.System.getInt(
5837 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5838
5839 Configuration configuration = new Configuration();
5840 Settings.System.getConfiguration(resolver, configuration);
5841
5842 synchronized (this) {
5843 mDebugApp = mOrigDebugApp = debugApp;
5844 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5845 mAlwaysFinishActivities = alwaysFinishActivities;
5846 // This happens before any activities are started, so we can
5847 // change mConfiguration in-place.
5848 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005849 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005850 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 }
5852 }
5853
5854 public boolean testIsSystemReady() {
5855 // no need to synchronize(this) just to read & return the value
5856 return mSystemReady;
5857 }
5858
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005859 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 // In the simulator, startRunning will never have been called, which
5861 // normally sets a few crucial variables. Do it here instead.
5862 if (!Process.supportsProcesses()) {
5863 mStartRunning = true;
5864 mTopAction = Intent.ACTION_MAIN;
5865 }
5866
5867 synchronized(this) {
5868 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005869 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005870 return;
5871 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005872
5873 // Check to see if there are any update receivers to run.
5874 if (!mDidUpdate) {
5875 if (mWaitingUpdate) {
5876 return;
5877 }
5878 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5879 List<ResolveInfo> ris = null;
5880 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005881 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005882 intent, null, 0);
5883 } catch (RemoteException e) {
5884 }
5885 if (ris != null) {
5886 for (int i=ris.size()-1; i>=0; i--) {
5887 if ((ris.get(i).activityInfo.applicationInfo.flags
5888 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5889 ris.remove(i);
5890 }
5891 }
5892 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5893 for (int i=0; i<ris.size(); i++) {
5894 ActivityInfo ai = ris.get(i).activityInfo;
5895 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5896 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005897 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005898 finisher = new IIntentReceiver.Stub() {
5899 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005900 String data, Bundle extras, boolean ordered,
5901 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005902 throws RemoteException {
5903 synchronized (ActivityManagerService.this) {
5904 mDidUpdate = true;
5905 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005906 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005907 }
5908 };
5909 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005910 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005911 broadcastIntentLocked(null, null, intent, null, finisher,
5912 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005913 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005914 mWaitingUpdate = true;
5915 }
5916 }
5917 }
5918 if (mWaitingUpdate) {
5919 return;
5920 }
5921 mDidUpdate = true;
5922 }
5923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005924 mSystemReady = true;
5925 if (!mStartRunning) {
5926 return;
5927 }
5928 }
5929
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005930 ArrayList<ProcessRecord> procsToKill = null;
5931 synchronized(mPidsSelfLocked) {
5932 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5933 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5934 if (!isAllowedWhileBooting(proc.info)){
5935 if (procsToKill == null) {
5936 procsToKill = new ArrayList<ProcessRecord>();
5937 }
5938 procsToKill.add(proc);
5939 }
5940 }
5941 }
5942
5943 if (procsToKill != null) {
5944 synchronized(this) {
5945 for (int i=procsToKill.size()-1; i>=0; i--) {
5946 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005947 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005948 removeProcessLocked(proc, true);
5949 }
5950 }
5951 }
5952
Joe Onorato8a9b2202010-02-26 18:56:32 -08005953 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005954 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 SystemClock.uptimeMillis());
5956
5957 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005958 // Make sure we have no pre-ready processes sitting around.
5959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5961 ResolveInfo ri = mContext.getPackageManager()
5962 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005963 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 CharSequence errorMsg = null;
5965 if (ri != null) {
5966 ActivityInfo ai = ri.activityInfo;
5967 ApplicationInfo app = ai.applicationInfo;
5968 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5969 mTopAction = Intent.ACTION_FACTORY_TEST;
5970 mTopData = null;
5971 mTopComponent = new ComponentName(app.packageName,
5972 ai.name);
5973 } else {
5974 errorMsg = mContext.getResources().getText(
5975 com.android.internal.R.string.factorytest_not_system);
5976 }
5977 } else {
5978 errorMsg = mContext.getResources().getText(
5979 com.android.internal.R.string.factorytest_no_action);
5980 }
5981 if (errorMsg != null) {
5982 mTopAction = null;
5983 mTopData = null;
5984 mTopComponent = null;
5985 Message msg = Message.obtain();
5986 msg.what = SHOW_FACTORY_ERROR_MSG;
5987 msg.getData().putCharSequence("msg", errorMsg);
5988 mHandler.sendMessage(msg);
5989 }
5990 }
5991 }
5992
5993 retrieveSettings();
5994
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005995 if (goingCallback != null) goingCallback.run();
5996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 synchronized (this) {
5998 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5999 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006000 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006001 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006002 if (apps != null) {
6003 int N = apps.size();
6004 int i;
6005 for (i=0; i<N; i++) {
6006 ApplicationInfo info
6007 = (ApplicationInfo)apps.get(i);
6008 if (info != null &&
6009 !info.packageName.equals("android")) {
6010 addAppLocked(info);
6011 }
6012 }
6013 }
6014 } catch (RemoteException ex) {
6015 // pm is in same process, this will never happen.
6016 }
6017 }
6018
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006019 // Start up initial activity.
6020 mBooting = true;
6021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006023 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006024 Message msg = Message.obtain();
6025 msg.what = SHOW_UID_ERROR_MSG;
6026 mHandler.sendMessage(msg);
6027 }
6028 } catch (RemoteException e) {
6029 }
6030
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006031 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 }
6033 }
6034
Dan Egnorb7f03672009-12-09 16:22:32 -08006035 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006036 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006037 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006038 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006039 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006040 startAppProblemLocked(app);
6041 app.stopFreezingAllLocked();
6042 return handleAppCrashLocked(app);
6043 }
6044
Dan Egnorb7f03672009-12-09 16:22:32 -08006045 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006046 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006048 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006049 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6050 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051 startAppProblemLocked(app);
6052 app.stopFreezingAllLocked();
6053 }
6054
6055 /**
6056 * Generate a process error record, suitable for attachment to a ProcessRecord.
6057 *
6058 * @param app The ProcessRecord in which the error occurred.
6059 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6060 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006061 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006062 * @param shortMsg Short message describing the crash.
6063 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006064 * @param stackTrace Full crash stack trace, may be null.
6065 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006066 * @return Returns a fully-formed AppErrorStateInfo record.
6067 */
6068 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006069 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006072 report.condition = condition;
6073 report.processName = app.processName;
6074 report.pid = app.pid;
6075 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006076 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006077 report.shortMsg = shortMsg;
6078 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006079 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006080
6081 return report;
6082 }
6083
Dan Egnor42471dd2010-01-07 17:25:22 -08006084 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006085 synchronized (this) {
6086 app.crashing = false;
6087 app.crashingReport = null;
6088 app.notResponding = false;
6089 app.notRespondingReport = null;
6090 if (app.anrDialog == fromDialog) {
6091 app.anrDialog = null;
6092 }
6093 if (app.waitDialog == fromDialog) {
6094 app.waitDialog = null;
6095 }
6096 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006097 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006098 Slog.i(ActivityManagerService.TAG, "Killing "
6099 + app.processName + " (pid=" + app.pid + "): user's request");
6100 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6101 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 Process.killProcess(app.pid);
6103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006104 }
6105 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006106
Dan Egnorb7f03672009-12-09 16:22:32 -08006107 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006108 long now = SystemClock.uptimeMillis();
6109
6110 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6111 app.info.uid);
6112 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6113 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006114 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006116 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006117 app.info.processName, app.info.uid);
6118 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006119 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6120 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006121 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006122 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006123 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006124 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006125 }
6126 }
6127 if (!app.persistent) {
6128 // We don't want to start this process again until the user
6129 // explicitly does so... but for persistent process, we really
6130 // need to keep it running. If a persistent process is actually
6131 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006132 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006133 app.info.processName);
6134 mBadProcesses.put(app.info.processName, app.info.uid, now);
6135 app.bad = true;
6136 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6137 app.removed = true;
6138 removeProcessLocked(app, false);
6139 return false;
6140 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006141 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006142 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006143 if (r.app == app) {
6144 // If the top running activity is from this crashing
6145 // process, then terminate it to avoid getting in a loop.
6146 Slog.w(TAG, " Force finishing activity "
6147 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006148 int index = mMainStack.indexOfTokenLocked(r);
6149 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006150 Activity.RESULT_CANCELED, null, "crashed");
6151 // Also terminate an activities below it that aren't yet
6152 // stopped, to avoid a situation where one will get
6153 // re-start our crashing activity once it gets resumed again.
6154 index--;
6155 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006156 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006157 if (r.state == ActivityState.RESUMED
6158 || r.state == ActivityState.PAUSING
6159 || r.state == ActivityState.PAUSED) {
6160 if (!r.isHomeActivity) {
6161 Slog.w(TAG, " Force finishing activity "
6162 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006163 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006164 Activity.RESULT_CANCELED, null, "crashed");
6165 }
6166 }
6167 }
6168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006169 }
6170
6171 // Bump up the crash count of any services currently running in the proc.
6172 if (app.services.size() != 0) {
6173 // Any services running in the application need to be placed
6174 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006175 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006176 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006177 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006178 sr.crashCount++;
6179 }
6180 }
6181
6182 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6183 return true;
6184 }
6185
6186 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006187 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6188 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006189 skipCurrentReceiverLocked(app);
6190 }
6191
6192 void skipCurrentReceiverLocked(ProcessRecord app) {
6193 boolean reschedule = false;
6194 BroadcastRecord r = app.curReceiver;
6195 if (r != null) {
6196 // The current broadcast is waiting for this app's receiver
6197 // to be finished. Looks like that's not going to happen, so
6198 // let the broadcast continue.
6199 logBroadcastReceiverDiscard(r);
6200 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6201 r.resultExtras, r.resultAbort, true);
6202 reschedule = true;
6203 }
6204 r = mPendingBroadcast;
6205 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006206 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006207 "skip & discard pending app " + r);
6208 logBroadcastReceiverDiscard(r);
6209 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6210 r.resultExtras, r.resultAbort, true);
6211 reschedule = true;
6212 }
6213 if (reschedule) {
6214 scheduleBroadcastsLocked();
6215 }
6216 }
6217
Dan Egnor60d87622009-12-16 16:32:58 -08006218 /**
6219 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6220 * The application process will exit immediately after this call returns.
6221 * @param app object of the crashing app, null for the system server
6222 * @param crashInfo describing the exception
6223 */
6224 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6225 ProcessRecord r = findAppProcess(app);
6226
6227 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6228 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006229 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006230 crashInfo.exceptionClassName,
6231 crashInfo.exceptionMessage,
6232 crashInfo.throwFileName,
6233 crashInfo.throwLineNumber);
6234
Dan Egnor42471dd2010-01-07 17:25:22 -08006235 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006236
6237 crashApplication(r, crashInfo);
6238 }
6239
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006240 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006241 IBinder app,
6242 int violationMask,
6243 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006244 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006245
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006246 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006247 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006248 boolean logIt = true;
6249 synchronized (mAlreadyLoggedViolatedStacks) {
6250 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6251 logIt = false;
6252 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006253 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006254 // the relative pain numbers, without logging all
6255 // the stack traces repeatedly. We'd want to do
6256 // likewise in the client code, which also does
6257 // dup suppression, before the Binder call.
6258 } else {
6259 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6260 mAlreadyLoggedViolatedStacks.clear();
6261 }
6262 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6263 }
6264 }
6265 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006266 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006267 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006268 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006269
6270 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6271 AppErrorResult result = new AppErrorResult();
6272 synchronized (this) {
6273 final long origId = Binder.clearCallingIdentity();
6274
6275 Message msg = Message.obtain();
6276 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6277 HashMap<String, Object> data = new HashMap<String, Object>();
6278 data.put("result", result);
6279 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006280 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006281 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006282 msg.obj = data;
6283 mHandler.sendMessage(msg);
6284
6285 Binder.restoreCallingIdentity(origId);
6286 }
6287 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006288 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006289 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006290 }
6291
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006292 // Depending on the policy in effect, there could be a bunch of
6293 // these in quick succession so we try to batch these together to
6294 // minimize disk writes, number of dropbox entries, and maximize
6295 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006296 private void logStrictModeViolationToDropBox(
6297 ProcessRecord process,
6298 StrictMode.ViolationInfo info) {
6299 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006300 return;
6301 }
6302 final boolean isSystemApp = process == null ||
6303 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6304 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6305 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6306 final DropBoxManager dbox = (DropBoxManager)
6307 mContext.getSystemService(Context.DROPBOX_SERVICE);
6308
6309 // Exit early if the dropbox isn't configured to accept this report type.
6310 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6311
6312 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006313 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006314 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6315 synchronized (sb) {
6316 bufferWasEmpty = sb.length() == 0;
6317 appendDropBoxProcessHeaders(process, sb);
6318 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6319 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006320 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6321 if (info.violationNumThisLoop != 0) {
6322 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6323 }
6324 if (info != null && info.durationMillis != -1) {
6325 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006326 }
6327 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006328 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6329 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006330 }
6331 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006332
6333 // Only buffer up to ~64k. Various logging bits truncate
6334 // things at 128k.
6335 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006336 }
6337
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006338 // Flush immediately if the buffer's grown too large, or this
6339 // is a non-system app. Non-system apps are isolated with a
6340 // different tag & policy and not batched.
6341 //
6342 // Batching is useful during internal testing with
6343 // StrictMode settings turned up high. Without batching,
6344 // thousands of separate files could be created on boot.
6345 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006346 new Thread("Error dump: " + dropboxTag) {
6347 @Override
6348 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006349 String report;
6350 synchronized (sb) {
6351 report = sb.toString();
6352 sb.delete(0, sb.length());
6353 sb.trimToSize();
6354 }
6355 if (report.length() != 0) {
6356 dbox.addText(dropboxTag, report);
6357 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006358 }
6359 }.start();
6360 return;
6361 }
6362
6363 // System app batching:
6364 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006365 // An existing dropbox-writing thread is outstanding, so
6366 // we don't need to start it up. The existing thread will
6367 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006368 return;
6369 }
6370
6371 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6372 // (After this point, we shouldn't access AMS internal data structures.)
6373 new Thread("Error dump: " + dropboxTag) {
6374 @Override
6375 public void run() {
6376 // 5 second sleep to let stacks arrive and be batched together
6377 try {
6378 Thread.sleep(5000); // 5 seconds
6379 } catch (InterruptedException e) {}
6380
6381 String errorReport;
6382 synchronized (mStrictModeBuffer) {
6383 errorReport = mStrictModeBuffer.toString();
6384 if (errorReport.length() == 0) {
6385 return;
6386 }
6387 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6388 mStrictModeBuffer.trimToSize();
6389 }
6390 dbox.addText(dropboxTag, errorReport);
6391 }
6392 }.start();
6393 }
6394
Dan Egnor60d87622009-12-16 16:32:58 -08006395 /**
6396 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6397 * @param app object of the crashing app, null for the system server
6398 * @param tag reported by the caller
6399 * @param crashInfo describing the context of the error
6400 * @return true if the process should exit immediately (WTF is fatal)
6401 */
6402 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006403 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006404 ProcessRecord r = findAppProcess(app);
6405
6406 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6407 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006408 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006409 tag, crashInfo.exceptionMessage);
6410
Dan Egnor42471dd2010-01-07 17:25:22 -08006411 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006412
Doug Zongker43866e02010-01-07 12:09:54 -08006413 if (Settings.Secure.getInt(mContext.getContentResolver(),
6414 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006415 crashApplication(r, crashInfo);
6416 return true;
6417 } else {
6418 return false;
6419 }
6420 }
6421
6422 /**
6423 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6424 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6425 */
6426 private ProcessRecord findAppProcess(IBinder app) {
6427 if (app == null) {
6428 return null;
6429 }
6430
6431 synchronized (this) {
6432 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6433 final int NA = apps.size();
6434 for (int ia=0; ia<NA; ia++) {
6435 ProcessRecord p = apps.valueAt(ia);
6436 if (p.thread != null && p.thread.asBinder() == app) {
6437 return p;
6438 }
6439 }
6440 }
6441
Joe Onorato8a9b2202010-02-26 18:56:32 -08006442 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006443 return null;
6444 }
6445 }
6446
6447 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006448 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6449 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006450 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006451 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006452 if (process == null || process.pid == MY_PID) {
6453 sb.append("Process: system_server\n");
6454 } else {
6455 sb.append("Process: ").append(process.processName).append("\n");
6456 }
6457 if (process != null) {
6458 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006459 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006460 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6461 for (String pkg : process.pkgList) {
6462 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006463 try {
Dan Egnora455d192010-03-12 08:52:28 -08006464 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6465 if (pi != null) {
6466 sb.append(" v").append(pi.versionCode);
6467 if (pi.versionName != null) {
6468 sb.append(" (").append(pi.versionName).append(")");
6469 }
6470 }
6471 } catch (RemoteException e) {
6472 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006473 }
Dan Egnora455d192010-03-12 08:52:28 -08006474 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006475 }
Dan Egnora455d192010-03-12 08:52:28 -08006476 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006477 }
6478
6479 private static String processClass(ProcessRecord process) {
6480 if (process == null || process.pid == MY_PID) {
6481 return "system_server";
6482 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6483 return "system_app";
6484 } else {
6485 return "data_app";
6486 }
6487 }
6488
6489 /**
6490 * Write a description of an error (crash, WTF, ANR) to the drop box.
6491 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6492 * @param process which caused the error, null means the system server
6493 * @param activity which triggered the error, null if unknown
6494 * @param parent activity related to the error, null if unknown
6495 * @param subject line related to the error, null if absent
6496 * @param report in long form describing the error, null if absent
6497 * @param logFile to include in the report, null if none
6498 * @param crashInfo giving an application stack trace, null if absent
6499 */
6500 public void addErrorToDropBox(String eventType,
6501 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6502 final String report, final File logFile,
6503 final ApplicationErrorReport.CrashInfo crashInfo) {
6504 // NOTE -- this must never acquire the ActivityManagerService lock,
6505 // otherwise the watchdog may be prevented from resetting the system.
6506
6507 final String dropboxTag = processClass(process) + "_" + eventType;
6508 final DropBoxManager dbox = (DropBoxManager)
6509 mContext.getSystemService(Context.DROPBOX_SERVICE);
6510
6511 // Exit early if the dropbox isn't configured to accept this report type.
6512 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6513
6514 final StringBuilder sb = new StringBuilder(1024);
6515 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006516 if (activity != null) {
6517 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6518 }
6519 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6520 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6521 }
6522 if (parent != null && parent != activity) {
6523 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6524 }
6525 if (subject != null) {
6526 sb.append("Subject: ").append(subject).append("\n");
6527 }
6528 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6529 sb.append("\n");
6530
6531 // Do the rest in a worker thread to avoid blocking the caller on I/O
6532 // (After this point, we shouldn't access AMS internal data structures.)
6533 Thread worker = new Thread("Error dump: " + dropboxTag) {
6534 @Override
6535 public void run() {
6536 if (report != null) {
6537 sb.append(report);
6538 }
6539 if (logFile != null) {
6540 try {
6541 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6542 } catch (IOException e) {
6543 Slog.e(TAG, "Error reading " + logFile, e);
6544 }
6545 }
6546 if (crashInfo != null && crashInfo.stackTrace != null) {
6547 sb.append(crashInfo.stackTrace);
6548 }
6549
6550 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6551 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6552 if (lines > 0) {
6553 sb.append("\n");
6554
6555 // Merge several logcat streams, and take the last N lines
6556 InputStreamReader input = null;
6557 try {
6558 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6559 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6560 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6561
6562 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6563 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6564 input = new InputStreamReader(logcat.getInputStream());
6565
6566 int num;
6567 char[] buf = new char[8192];
6568 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6569 } catch (IOException e) {
6570 Slog.e(TAG, "Error running logcat", e);
6571 } finally {
6572 if (input != null) try { input.close(); } catch (IOException e) {}
6573 }
6574 }
6575
6576 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006577 }
Dan Egnora455d192010-03-12 08:52:28 -08006578 };
6579
6580 if (process == null || process.pid == MY_PID) {
6581 worker.run(); // We may be about to die -- need to run this synchronously
6582 } else {
6583 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006584 }
6585 }
6586
6587 /**
6588 * Bring up the "unexpected error" dialog box for a crashing app.
6589 * Deal with edge cases (intercepts from instrumented applications,
6590 * ActivityController, error intent receivers, that sort of thing).
6591 * @param r the application crashing
6592 * @param crashInfo describing the failure
6593 */
6594 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006595 long timeMillis = System.currentTimeMillis();
6596 String shortMsg = crashInfo.exceptionClassName;
6597 String longMsg = crashInfo.exceptionMessage;
6598 String stackTrace = crashInfo.stackTrace;
6599 if (shortMsg != null && longMsg != null) {
6600 longMsg = shortMsg + ": " + longMsg;
6601 } else if (shortMsg != null) {
6602 longMsg = shortMsg;
6603 }
6604
Dan Egnor60d87622009-12-16 16:32:58 -08006605 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006606 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006607 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006608 try {
6609 String name = r != null ? r.processName : null;
6610 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006611 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006612 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006613 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 + " at watcher's request");
6615 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006616 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006617 }
6618 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006619 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006620 }
6621 }
6622
6623 final long origId = Binder.clearCallingIdentity();
6624
6625 // If this process is running instrumentation, finish it.
6626 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006627 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006629 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6630 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006631 Bundle info = new Bundle();
6632 info.putString("shortMsg", shortMsg);
6633 info.putString("longMsg", longMsg);
6634 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6635 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006636 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006637 }
6638
Dan Egnor60d87622009-12-16 16:32:58 -08006639 // If we can't identify the process or it's already exceeded its crash quota,
6640 // quit right away without showing a crash dialog.
6641 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006642 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006643 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006644 }
6645
6646 Message msg = Message.obtain();
6647 msg.what = SHOW_ERROR_MSG;
6648 HashMap data = new HashMap();
6649 data.put("result", result);
6650 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 msg.obj = data;
6652 mHandler.sendMessage(msg);
6653
6654 Binder.restoreCallingIdentity(origId);
6655 }
6656
6657 int res = result.get();
6658
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006659 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 synchronized (this) {
6661 if (r != null) {
6662 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6663 SystemClock.uptimeMillis());
6664 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006665 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006666 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006667 }
6668 }
6669
6670 if (appErrorIntent != null) {
6671 try {
6672 mContext.startActivity(appErrorIntent);
6673 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006674 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006676 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006677 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006678
6679 Intent createAppErrorIntentLocked(ProcessRecord r,
6680 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6681 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006682 if (report == null) {
6683 return null;
6684 }
6685 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6686 result.setComponent(r.errorReportReceiver);
6687 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6688 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6689 return result;
6690 }
6691
Dan Egnorb7f03672009-12-09 16:22:32 -08006692 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6693 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006694 if (r.errorReportReceiver == null) {
6695 return null;
6696 }
6697
6698 if (!r.crashing && !r.notResponding) {
6699 return null;
6700 }
6701
Dan Egnorb7f03672009-12-09 16:22:32 -08006702 ApplicationErrorReport report = new ApplicationErrorReport();
6703 report.packageName = r.info.packageName;
6704 report.installerPackageName = r.errorReportReceiver.getPackageName();
6705 report.processName = r.processName;
6706 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006707 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006708
Dan Egnorb7f03672009-12-09 16:22:32 -08006709 if (r.crashing) {
6710 report.type = ApplicationErrorReport.TYPE_CRASH;
6711 report.crashInfo = crashInfo;
6712 } else if (r.notResponding) {
6713 report.type = ApplicationErrorReport.TYPE_ANR;
6714 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006715
Dan Egnorb7f03672009-12-09 16:22:32 -08006716 report.anrInfo.activity = r.notRespondingReport.tag;
6717 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6718 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006719 }
6720
Dan Egnorb7f03672009-12-09 16:22:32 -08006721 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006722 }
6723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006724 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6725 // assume our apps are happy - lazy create the list
6726 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6727
6728 synchronized (this) {
6729
6730 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006731 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6732 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006733 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6734 // This one's in trouble, so we'll generate a report for it
6735 // crashes are higher priority (in case there's a crash *and* an anr)
6736 ActivityManager.ProcessErrorStateInfo report = null;
6737 if (app.crashing) {
6738 report = app.crashingReport;
6739 } else if (app.notResponding) {
6740 report = app.notRespondingReport;
6741 }
6742
6743 if (report != null) {
6744 if (errList == null) {
6745 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6746 }
6747 errList.add(report);
6748 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006749 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006750 " crashing = " + app.crashing +
6751 " notResponding = " + app.notResponding);
6752 }
6753 }
6754 }
6755 }
6756
6757 return errList;
6758 }
6759
6760 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6761 // Lazy instantiation of list
6762 List<ActivityManager.RunningAppProcessInfo> runList = null;
6763 synchronized (this) {
6764 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006765 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6766 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006767 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6768 // Generate process state info for running application
6769 ActivityManager.RunningAppProcessInfo currApp =
6770 new ActivityManager.RunningAppProcessInfo(app.processName,
6771 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006772 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006773 if (mHeavyWeightProcess == app) {
6774 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006777 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006778 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6779 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6780 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006781 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6782 } else if (adj >= HOME_APP_ADJ) {
6783 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6784 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006785 } else if (adj >= SECONDARY_SERVER_ADJ) {
6786 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006787 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6788 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6789 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6790 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006791 } else if (adj >= VISIBLE_APP_ADJ) {
6792 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6793 } else {
6794 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6795 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006796 currApp.importanceReasonCode = app.adjTypeCode;
6797 if (app.adjSource instanceof ProcessRecord) {
6798 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006799 } else if (app.adjSource instanceof ActivityRecord) {
6800 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006801 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6802 }
6803 if (app.adjTarget instanceof ComponentName) {
6804 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6805 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006806 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006807 // + " lru=" + currApp.lru);
6808 if (runList == null) {
6809 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6810 }
6811 runList.add(currApp);
6812 }
6813 }
6814 }
6815 return runList;
6816 }
6817
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006818 public List<ApplicationInfo> getRunningExternalApplications() {
6819 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6820 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6821 if (runningApps != null && runningApps.size() > 0) {
6822 Set<String> extList = new HashSet<String>();
6823 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6824 if (app.pkgList != null) {
6825 for (String pkg : app.pkgList) {
6826 extList.add(pkg);
6827 }
6828 }
6829 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006830 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006831 for (String pkg : extList) {
6832 try {
6833 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6834 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6835 retList.add(info);
6836 }
6837 } catch (RemoteException e) {
6838 }
6839 }
6840 }
6841 return retList;
6842 }
6843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006844 @Override
6845 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006846 if (checkCallingPermission(android.Manifest.permission.DUMP)
6847 != PackageManager.PERMISSION_GRANTED) {
6848 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6849 + Binder.getCallingPid()
6850 + ", uid=" + Binder.getCallingUid()
6851 + " without permission "
6852 + android.Manifest.permission.DUMP);
6853 return;
6854 }
6855
6856 boolean dumpAll = false;
6857
6858 int opti = 0;
6859 while (opti < args.length) {
6860 String opt = args[opti];
6861 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6862 break;
6863 }
6864 opti++;
6865 if ("-a".equals(opt)) {
6866 dumpAll = true;
6867 } else if ("-h".equals(opt)) {
6868 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006869 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006870 pw.println(" cmd may be one of:");
6871 pw.println(" activities: activity stack state");
6872 pw.println(" broadcasts: broadcast state");
6873 pw.println(" intents: pending intent state");
6874 pw.println(" processes: process state");
6875 pw.println(" providers: content provider state");
6876 pw.println(" services: service state");
6877 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006878 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006879 } else {
6880 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006881 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006882 }
6883
6884 // Is the caller requesting to dump a particular piece of data?
6885 if (opti < args.length) {
6886 String cmd = args[opti];
6887 opti++;
6888 if ("activities".equals(cmd) || "a".equals(cmd)) {
6889 synchronized (this) {
6890 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006892 return;
6893 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6894 synchronized (this) {
6895 dumpBroadcastsLocked(fd, pw, args, opti, true);
6896 }
6897 return;
6898 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6899 synchronized (this) {
6900 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6901 }
6902 return;
6903 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6904 synchronized (this) {
6905 dumpProcessesLocked(fd, pw, args, opti, true);
6906 }
6907 return;
6908 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6909 synchronized (this) {
6910 dumpProvidersLocked(fd, pw, args, opti, true);
6911 }
6912 return;
6913 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006914 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006915 return;
6916 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6917 synchronized (this) {
6918 dumpServicesLocked(fd, pw, args, opti, true);
6919 }
6920 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006921 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006922 }
6923
6924 // No piece of data specified, dump everything.
6925 synchronized (this) {
6926 boolean needSep;
6927 if (dumpAll) {
6928 pw.println("Providers in Current Activity Manager State:");
6929 }
6930 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6931 if (needSep) {
6932 pw.println(" ");
6933 }
6934 if (dumpAll) {
6935 pw.println("-------------------------------------------------------------------------------");
6936 pw.println("Broadcasts in Current Activity Manager State:");
6937 }
6938 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6939 if (needSep) {
6940 pw.println(" ");
6941 }
6942 if (dumpAll) {
6943 pw.println("-------------------------------------------------------------------------------");
6944 pw.println("Services in Current Activity Manager State:");
6945 }
6946 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6947 if (needSep) {
6948 pw.println(" ");
6949 }
6950 if (dumpAll) {
6951 pw.println("-------------------------------------------------------------------------------");
6952 pw.println("PendingIntents in Current Activity Manager State:");
6953 }
6954 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6955 if (needSep) {
6956 pw.println(" ");
6957 }
6958 if (dumpAll) {
6959 pw.println("-------------------------------------------------------------------------------");
6960 pw.println("Activities in Current Activity Manager State:");
6961 }
6962 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6963 if (needSep) {
6964 pw.println(" ");
6965 }
6966 if (dumpAll) {
6967 pw.println("-------------------------------------------------------------------------------");
6968 pw.println("Processes in Current Activity Manager State:");
6969 }
6970 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6971 }
6972 }
6973
6974 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6975 int opti, boolean dumpAll, boolean needHeader) {
6976 if (needHeader) {
6977 pw.println(" Activity stack:");
6978 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006979 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006980 pw.println(" ");
6981 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006982 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6983 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006984 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006985 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006986 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006987 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006988 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006989 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006990 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006991 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006992 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006993 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006994 pw.println(" ");
6995 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006996 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006999 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007000 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7001 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007002 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007003 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007004
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007005 if (dumpAll && mRecentTasks.size() > 0) {
7006 pw.println(" ");
7007 pw.println("Recent tasks in Current Activity Manager State:");
7008
7009 final int N = mRecentTasks.size();
7010 for (int i=0; i<N; i++) {
7011 TaskRecord tr = mRecentTasks.get(i);
7012 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7013 pw.println(tr);
7014 mRecentTasks.get(i).dump(pw, " ");
7015 }
7016 }
7017
7018 pw.println(" ");
7019 pw.println(" mCurTask: " + mCurTask);
7020
7021 return true;
7022 }
7023
7024 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7025 int opti, boolean dumpAll) {
7026 boolean needSep = false;
7027 int numPers = 0;
7028
7029 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007030 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7031 final int NA = procs.size();
7032 for (int ia=0; ia<NA; ia++) {
7033 if (!needSep) {
7034 pw.println(" All known processes:");
7035 needSep = true;
7036 }
7037 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007038 pw.print(r.persistent ? " *PERS*" : " *APP*");
7039 pw.print(" UID "); pw.print(procs.keyAt(ia));
7040 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007041 r.dump(pw, " ");
7042 if (r.persistent) {
7043 numPers++;
7044 }
7045 }
7046 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007047 }
7048
7049 if (mLruProcesses.size() > 0) {
7050 if (needSep) pw.println(" ");
7051 needSep = true;
7052 pw.println(" Running processes (most recent first):");
7053 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007054 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007055 needSep = true;
7056 }
7057
7058 synchronized (mPidsSelfLocked) {
7059 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 if (needSep) pw.println(" ");
7061 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007062 pw.println(" PID mappings:");
7063 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7064 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7065 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066 }
7067 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007068 }
7069
7070 if (mForegroundProcesses.size() > 0) {
7071 if (needSep) pw.println(" ");
7072 needSep = true;
7073 pw.println(" Foreground Processes:");
7074 for (int i=0; i<mForegroundProcesses.size(); i++) {
7075 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7076 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007077 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007078 }
7079
7080 if (mPersistentStartingProcesses.size() > 0) {
7081 if (needSep) pw.println(" ");
7082 needSep = true;
7083 pw.println(" Persisent processes that are starting:");
7084 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
7085 "Starting Norm", "Restarting PERS", false);
7086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007087
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007088 if (mStartingProcesses.size() > 0) {
7089 if (needSep) pw.println(" ");
7090 needSep = true;
7091 pw.println(" Processes that are starting:");
7092 dumpProcessList(pw, this, mStartingProcesses, " ",
7093 "Starting Norm", "Starting PERS", false);
7094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007095
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007096 if (mRemovedProcesses.size() > 0) {
7097 if (needSep) pw.println(" ");
7098 needSep = true;
7099 pw.println(" Processes that are being removed:");
7100 dumpProcessList(pw, this, mRemovedProcesses, " ",
7101 "Removed Norm", "Removed PERS", false);
7102 }
7103
7104 if (mProcessesOnHold.size() > 0) {
7105 if (needSep) pw.println(" ");
7106 needSep = true;
7107 pw.println(" Processes that are on old until the system is ready:");
7108 dumpProcessList(pw, this, mProcessesOnHold, " ",
7109 "OnHold Norm", "OnHold PERS", false);
7110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007111
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007112 if (mProcessesToGc.size() > 0) {
7113 if (needSep) pw.println(" ");
7114 needSep = true;
7115 pw.println(" Processes that are waiting to GC:");
7116 long now = SystemClock.uptimeMillis();
7117 for (int i=0; i<mProcessesToGc.size(); i++) {
7118 ProcessRecord proc = mProcessesToGc.get(i);
7119 pw.print(" Process "); pw.println(proc);
7120 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7121 pw.print(", last gced=");
7122 pw.print(now-proc.lastRequestedGc);
7123 pw.print(" ms ago, last lowMem=");
7124 pw.print(now-proc.lastLowMemory);
7125 pw.println(" ms ago");
7126
7127 }
7128 }
7129
7130 if (mProcessCrashTimes.getMap().size() > 0) {
7131 if (needSep) pw.println(" ");
7132 needSep = true;
7133 pw.println(" Time since processes crashed:");
7134 long now = SystemClock.uptimeMillis();
7135 for (Map.Entry<String, SparseArray<Long>> procs
7136 : mProcessCrashTimes.getMap().entrySet()) {
7137 SparseArray<Long> uids = procs.getValue();
7138 final int N = uids.size();
7139 for (int i=0; i<N; i++) {
7140 pw.print(" Process "); pw.print(procs.getKey());
7141 pw.print(" uid "); pw.print(uids.keyAt(i));
7142 pw.print(": last crashed ");
7143 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007144 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007145 }
7146 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007148
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007149 if (mBadProcesses.getMap().size() > 0) {
7150 if (needSep) pw.println(" ");
7151 needSep = true;
7152 pw.println(" Bad processes:");
7153 for (Map.Entry<String, SparseArray<Long>> procs
7154 : mBadProcesses.getMap().entrySet()) {
7155 SparseArray<Long> uids = procs.getValue();
7156 final int N = uids.size();
7157 for (int i=0; i<N; i++) {
7158 pw.print(" Bad process "); pw.print(procs.getKey());
7159 pw.print(" uid "); pw.print(uids.keyAt(i));
7160 pw.print(": crashed at time ");
7161 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007162 }
7163 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007166 pw.println(" ");
7167 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007168 if (mHeavyWeightProcess != null) {
7169 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7170 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007171 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007172 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007173 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7174 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7175 || mOrigWaitForDebugger) {
7176 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7177 + " mDebugTransient=" + mDebugTransient
7178 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7179 }
7180 if (mAlwaysFinishActivities || mController != null) {
7181 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7182 + " mController=" + mController);
7183 }
7184 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007185 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186 pw.println(" mStartRunning=" + mStartRunning
7187 + " mSystemReady=" + mSystemReady
7188 + " mBooting=" + mBooting
7189 + " mBooted=" + mBooted
7190 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007191 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7192 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007193 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007195
7196 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007197 }
7198
7199 /**
7200 * There are three ways to call this:
7201 * - no service specified: dump all the services
7202 * - a flattened component name that matched an existing service was specified as the
7203 * first arg: dump that one service
7204 * - the first arg isn't the flattened component name of an existing service:
7205 * dump all services whose component contains the first arg as a substring
7206 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007207 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7208 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007209 String[] newArgs;
7210 String componentNameString;
7211 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007212 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007213 componentNameString = null;
7214 newArgs = EMPTY_STRING_ARRAY;
7215 r = null;
7216 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007217 componentNameString = args[opti];
7218 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007220 synchronized (this) {
7221 r = componentName != null ? mServices.get(componentName) : null;
7222 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007223 newArgs = new String[args.length - opti];
7224 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 }
7226
7227 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007228 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007229 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007230 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7231 synchronized (this) {
7232 for (ServiceRecord r1 : mServices.values()) {
7233 if (componentNameString == null
7234 || r1.name.flattenToString().contains(componentNameString)) {
7235 services.add(r1);
7236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007237 }
7238 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007239 for (int i=0; i<services.size(); i++) {
7240 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007242 }
7243 }
7244
7245 /**
7246 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7247 * there is a thread associated with the service.
7248 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007249 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7250 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007252 if (dumpAll) {
7253 synchronized (this) {
7254 pw.print(" * "); pw.println(r);
7255 r.dump(pw, " ");
7256 }
7257 pw.println("");
7258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007259 if (r.app != null && r.app.thread != null) {
7260 try {
7261 // flush anything that is already in the PrintWriter since the thread is going
7262 // to write to the file descriptor directly
7263 pw.flush();
7264 r.app.thread.dumpService(fd, r, args);
7265 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007266 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007267 } catch (RemoteException e) {
7268 pw.println("got a RemoteException while dumping the service");
7269 }
7270 }
7271 }
7272
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007273 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7274 int opti, boolean dumpAll) {
7275 boolean needSep = false;
7276
7277 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007278 if (mRegisteredReceivers.size() > 0) {
7279 pw.println(" ");
7280 pw.println(" Registered Receivers:");
7281 Iterator it = mRegisteredReceivers.values().iterator();
7282 while (it.hasNext()) {
7283 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007284 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007285 r.dump(pw, " ");
7286 }
7287 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007289 pw.println(" ");
7290 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007291 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007292 needSep = true;
7293 }
7294
7295 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7296 || mPendingBroadcast != null) {
7297 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007298 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007299 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007300 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007301 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7302 pw.println(" Broadcast #" + i + ":");
7303 mParallelBroadcasts.get(i).dump(pw, " ");
7304 }
7305 if (mOrderedBroadcasts.size() > 0) {
7306 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007307 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007308 }
7309 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7310 pw.println(" Serialized Broadcast #" + i + ":");
7311 mOrderedBroadcasts.get(i).dump(pw, " ");
7312 }
7313 pw.println(" ");
7314 pw.println(" Pending broadcast:");
7315 if (mPendingBroadcast != null) {
7316 mPendingBroadcast.dump(pw, " ");
7317 } else {
7318 pw.println(" (null)");
7319 }
7320 needSep = true;
7321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007322
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007323 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007325 pw.println(" Historical broadcasts:");
7326 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7327 BroadcastRecord r = mBroadcastHistory[i];
7328 if (r == null) {
7329 break;
7330 }
7331 pw.println(" Historical Broadcast #" + i + ":");
7332 r.dump(pw, " ");
7333 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007334 needSep = true;
7335 }
7336
7337 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007338 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007339 pw.println(" Sticky broadcasts:");
7340 StringBuilder sb = new StringBuilder(128);
7341 for (Map.Entry<String, ArrayList<Intent>> ent
7342 : mStickyBroadcasts.entrySet()) {
7343 pw.print(" * Sticky action "); pw.print(ent.getKey());
7344 pw.println(":");
7345 ArrayList<Intent> intents = ent.getValue();
7346 final int N = intents.size();
7347 for (int i=0; i<N; i++) {
7348 sb.setLength(0);
7349 sb.append(" Intent: ");
7350 intents.get(i).toShortString(sb, true, false);
7351 pw.println(sb.toString());
7352 Bundle bundle = intents.get(i).getExtras();
7353 if (bundle != null) {
7354 pw.print(" ");
7355 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 }
7357 }
7358 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007359 needSep = true;
7360 }
7361
7362 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007363 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007364 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 pw.println(" mHandler:");
7366 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007367 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007369
7370 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 }
7372
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007373 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7374 int opti, boolean dumpAll) {
7375 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007377 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 if (mServices.size() > 0) {
7379 pw.println(" Active services:");
7380 Iterator<ServiceRecord> it = mServices.values().iterator();
7381 while (it.hasNext()) {
7382 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007383 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 r.dump(pw, " ");
7385 }
7386 needSep = true;
7387 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007390 if (mPendingServices.size() > 0) {
7391 if (needSep) pw.println(" ");
7392 pw.println(" Pending services:");
7393 for (int i=0; i<mPendingServices.size(); i++) {
7394 ServiceRecord r = mPendingServices.get(i);
7395 pw.print(" * Pending "); pw.println(r);
7396 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007397 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007398 needSep = true;
7399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007401 if (mRestartingServices.size() > 0) {
7402 if (needSep) pw.println(" ");
7403 pw.println(" Restarting services:");
7404 for (int i=0; i<mRestartingServices.size(); i++) {
7405 ServiceRecord r = mRestartingServices.get(i);
7406 pw.print(" * Restarting "); pw.println(r);
7407 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007408 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007409 needSep = true;
7410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007412 if (mStoppingServices.size() > 0) {
7413 if (needSep) pw.println(" ");
7414 pw.println(" Stopping services:");
7415 for (int i=0; i<mStoppingServices.size(); i++) {
7416 ServiceRecord r = mStoppingServices.get(i);
7417 pw.print(" * Stopping "); pw.println(r);
7418 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007420 needSep = true;
7421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007422
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007423 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 if (mServiceConnections.size() > 0) {
7425 if (needSep) pw.println(" ");
7426 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007427 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007428 = mServiceConnections.values().iterator();
7429 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007430 ArrayList<ConnectionRecord> r = it.next();
7431 for (int i=0; i<r.size(); i++) {
7432 pw.print(" * "); pw.println(r.get(i));
7433 r.get(i).dump(pw, " ");
7434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007435 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007436 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007437 }
7438 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007439
7440 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007441 }
7442
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007443 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7444 int opti, boolean dumpAll) {
7445 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007447 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007448 if (mProvidersByClass.size() > 0) {
7449 if (needSep) pw.println(" ");
7450 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007451 Iterator<Map.Entry<String, ContentProviderRecord>> it
7452 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007453 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007454 Map.Entry<String, ContentProviderRecord> e = it.next();
7455 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007456 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007457 r.dump(pw, " ");
7458 }
7459 needSep = true;
7460 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007461
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007462 if (mProvidersByName.size() > 0) {
7463 pw.println(" ");
7464 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007465 Iterator<Map.Entry<String, ContentProviderRecord>> it
7466 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007467 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007468 Map.Entry<String, ContentProviderRecord> e = it.next();
7469 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007470 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7471 pw.println(r);
7472 }
7473 needSep = true;
7474 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007476
7477 if (mLaunchingProviders.size() > 0) {
7478 if (needSep) pw.println(" ");
7479 pw.println(" Launching content providers:");
7480 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7481 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7482 pw.println(mLaunchingProviders.get(i));
7483 }
7484 needSep = true;
7485 }
7486
7487 if (mGrantedUriPermissions.size() > 0) {
7488 pw.println();
7489 pw.println("Granted Uri Permissions:");
7490 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7491 int uid = mGrantedUriPermissions.keyAt(i);
7492 HashMap<Uri, UriPermission> perms
7493 = mGrantedUriPermissions.valueAt(i);
7494 pw.print(" * UID "); pw.print(uid);
7495 pw.println(" holds:");
7496 for (UriPermission perm : perms.values()) {
7497 pw.print(" "); pw.println(perm);
7498 perm.dump(pw, " ");
7499 }
7500 }
7501 needSep = true;
7502 }
7503
7504 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007505 }
7506
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007507 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7508 int opti, boolean dumpAll) {
7509 boolean needSep = false;
7510
7511 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007512 if (this.mIntentSenderRecords.size() > 0) {
7513 Iterator<WeakReference<PendingIntentRecord>> it
7514 = mIntentSenderRecords.values().iterator();
7515 while (it.hasNext()) {
7516 WeakReference<PendingIntentRecord> ref = it.next();
7517 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007518 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007519 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007520 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007521 rec.dump(pw, " ");
7522 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007523 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007524 }
7525 }
7526 }
7527 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007528
7529 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007530 }
7531
7532 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007533 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534 TaskRecord lastTask = null;
7535 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007536 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007537 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007538 if (lastTask != r.task) {
7539 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007540 pw.print(prefix);
7541 pw.print(full ? "* " : " ");
7542 pw.println(lastTask);
7543 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007544 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007546 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007547 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7548 pw.print(" #"); pw.print(i); pw.print(": ");
7549 pw.println(r);
7550 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007551 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007553 }
7554 }
7555
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007556 private static String buildOomTag(String prefix, String space, int val, int base) {
7557 if (val == base) {
7558 if (space == null) return prefix;
7559 return prefix + " ";
7560 }
7561 return prefix + "+" + Integer.toString(val-base);
7562 }
7563
7564 private static final int dumpProcessList(PrintWriter pw,
7565 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007566 String prefix, String normalLabel, String persistentLabel,
7567 boolean inclOomAdj) {
7568 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007569 final int N = list.size()-1;
7570 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007571 ProcessRecord r = (ProcessRecord)list.get(i);
7572 if (false) {
7573 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7574 + " #" + i + ":");
7575 r.dump(pw, prefix + " ");
7576 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007577 String oomAdj;
7578 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007579 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007580 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007581 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7582 } else if (r.setAdj >= HOME_APP_ADJ) {
7583 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7584 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7585 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7586 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7587 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007588 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7589 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7590 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7591 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007592 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7593 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7594 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7595 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007596 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007597 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007598 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007599 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007600 } else {
7601 oomAdj = Integer.toString(r.setAdj);
7602 }
7603 String schedGroup;
7604 switch (r.setSchedGroup) {
7605 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7606 schedGroup = "B";
7607 break;
7608 case Process.THREAD_GROUP_DEFAULT:
7609 schedGroup = "F";
7610 break;
7611 default:
7612 schedGroup = Integer.toString(r.setSchedGroup);
7613 break;
7614 }
7615 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007616 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007617 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007618 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007619 pw.print(prefix);
7620 pw.print(" ");
7621 if (r.adjTarget instanceof ComponentName) {
7622 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7623 } else if (r.adjTarget != null) {
7624 pw.print(r.adjTarget.toString());
7625 } else {
7626 pw.print("{null}");
7627 }
7628 pw.print("<=");
7629 if (r.adjSource instanceof ProcessRecord) {
7630 pw.print("Proc{");
7631 pw.print(((ProcessRecord)r.adjSource).toShortString());
7632 pw.println("}");
7633 } else if (r.adjSource != null) {
7634 pw.println(r.adjSource.toString());
7635 } else {
7636 pw.println("{null}");
7637 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007639 } else {
7640 pw.println(String.format("%s%s #%2d: %s",
7641 prefix, (r.persistent ? persistentLabel : normalLabel),
7642 i, r.toString()));
7643 }
7644 if (r.persistent) {
7645 numPers++;
7646 }
7647 }
7648 return numPers;
7649 }
7650
Dianne Hackborn472ad872010-04-07 17:31:48 -07007651 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007653 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007654 long uptime = SystemClock.uptimeMillis();
7655 long realtime = SystemClock.elapsedRealtime();
7656
7657 if (isCheckinRequest) {
7658 // short checkin version
7659 pw.println(uptime + "," + realtime);
7660 pw.flush();
7661 } else {
7662 pw.println("Applications Memory Usage (kB):");
7663 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7664 }
7665 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7666 ProcessRecord r = (ProcessRecord)list.get(i);
7667 if (r.thread != null) {
7668 if (!isCheckinRequest) {
7669 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7670 pw.flush();
7671 }
7672 try {
7673 r.thread.asBinder().dump(fd, args);
7674 } catch (RemoteException e) {
7675 if (!isCheckinRequest) {
7676 pw.println("Got RemoteException!");
7677 pw.flush();
7678 }
7679 }
7680 }
7681 }
7682 }
7683
7684 /**
7685 * Searches array of arguments for the specified string
7686 * @param args array of argument strings
7687 * @param value value to search for
7688 * @return true if the value is contained in the array
7689 */
7690 private static boolean scanArgs(String[] args, String value) {
7691 if (args != null) {
7692 for (String arg : args) {
7693 if (value.equals(arg)) {
7694 return true;
7695 }
7696 }
7697 }
7698 return false;
7699 }
7700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 private final void killServicesLocked(ProcessRecord app,
7702 boolean allowRestart) {
7703 // Report disconnected services.
7704 if (false) {
7705 // XXX we are letting the client link to the service for
7706 // death notifications.
7707 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007708 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007710 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007712 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713 = r.connections.values().iterator();
7714 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007715 ArrayList<ConnectionRecord> cl = jt.next();
7716 for (int i=0; i<cl.size(); i++) {
7717 ConnectionRecord c = cl.get(i);
7718 if (c.binding.client != app) {
7719 try {
7720 //c.conn.connected(r.className, null);
7721 } catch (Exception e) {
7722 // todo: this should be asynchronous!
7723 Slog.w(TAG, "Exception thrown disconnected servce "
7724 + r.shortName
7725 + " from app " + app.processName, e);
7726 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007727 }
7728 }
7729 }
7730 }
7731 }
7732 }
7733 }
7734
7735 // Clean up any connections this application has to other services.
7736 if (app.connections.size() > 0) {
7737 Iterator<ConnectionRecord> it = app.connections.iterator();
7738 while (it.hasNext()) {
7739 ConnectionRecord r = it.next();
7740 removeConnectionLocked(r, app, null);
7741 }
7742 }
7743 app.connections.clear();
7744
7745 if (app.services.size() != 0) {
7746 // Any services running in the application need to be placed
7747 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007748 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007750 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 synchronized (sr.stats.getBatteryStats()) {
7752 sr.stats.stopLaunchedLocked();
7753 }
7754 sr.app = null;
7755 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007756 if (mStoppingServices.remove(sr)) {
7757 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
7758 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007759
7760 boolean hasClients = sr.bindings.size() > 0;
7761 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762 Iterator<IntentBindRecord> bindings
7763 = sr.bindings.values().iterator();
7764 while (bindings.hasNext()) {
7765 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007766 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007767 + ": shouldUnbind=" + b.hasBound);
7768 b.binder = null;
7769 b.requested = b.received = b.hasBound = false;
7770 }
7771 }
7772
7773 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007774 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007775 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007776 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777 sr.crashCount, sr.shortName, app.pid);
7778 bringDownServiceLocked(sr, true);
7779 } else if (!allowRestart) {
7780 bringDownServiceLocked(sr, true);
7781 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007782 boolean canceled = scheduleServiceRestartLocked(sr, true);
7783
7784 // Should the service remain running? Note that in the
7785 // extreme case of so many attempts to deliver a command
7786 // that it failed, that we also will stop it here.
7787 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7788 if (sr.pendingStarts.size() == 0) {
7789 sr.startRequested = false;
7790 if (!hasClients) {
7791 // Whoops, no reason to restart!
7792 bringDownServiceLocked(sr, true);
7793 }
7794 }
7795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007796 }
7797 }
7798
7799 if (!allowRestart) {
7800 app.services.clear();
7801 }
7802 }
7803
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007804 // Make sure we have no more records on the stopping list.
7805 int i = mStoppingServices.size();
7806 while (i > 0) {
7807 i--;
7808 ServiceRecord sr = mStoppingServices.get(i);
7809 if (sr.app == app) {
7810 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007811 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007812 }
7813 }
7814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007815 app.executingServices.clear();
7816 }
7817
7818 private final void removeDyingProviderLocked(ProcessRecord proc,
7819 ContentProviderRecord cpr) {
7820 synchronized (cpr) {
7821 cpr.launchingApp = null;
7822 cpr.notifyAll();
7823 }
7824
7825 mProvidersByClass.remove(cpr.info.name);
7826 String names[] = cpr.info.authority.split(";");
7827 for (int j = 0; j < names.length; j++) {
7828 mProvidersByName.remove(names[j]);
7829 }
7830
7831 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7832 while (cit.hasNext()) {
7833 ProcessRecord capp = cit.next();
7834 if (!capp.persistent && capp.thread != null
7835 && capp.pid != 0
7836 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007837 Slog.i(TAG, "Kill " + capp.processName
7838 + " (pid " + capp.pid + "): provider " + cpr.info.name
7839 + " in dying process " + proc.processName);
7840 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7841 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 Process.killProcess(capp.pid);
7843 }
7844 }
7845
7846 mLaunchingProviders.remove(cpr);
7847 }
7848
7849 /**
7850 * Main code for cleaning up a process when it has gone away. This is
7851 * called both as a result of the process dying, or directly when stopping
7852 * a process when running in single process mode.
7853 */
7854 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7855 boolean restarting, int index) {
7856 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007857 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007858 }
7859
Dianne Hackborn36124872009-10-08 16:22:03 -07007860 mProcessesToGc.remove(app);
7861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 // Dismiss any open dialogs.
7863 if (app.crashDialog != null) {
7864 app.crashDialog.dismiss();
7865 app.crashDialog = null;
7866 }
7867 if (app.anrDialog != null) {
7868 app.anrDialog.dismiss();
7869 app.anrDialog = null;
7870 }
7871 if (app.waitDialog != null) {
7872 app.waitDialog.dismiss();
7873 app.waitDialog = null;
7874 }
7875
7876 app.crashing = false;
7877 app.notResponding = false;
7878
7879 app.resetPackageList();
7880 app.thread = null;
7881 app.forcingToForeground = null;
7882 app.foregroundServices = false;
7883
7884 killServicesLocked(app, true);
7885
7886 boolean restart = false;
7887
7888 int NL = mLaunchingProviders.size();
7889
7890 // Remove published content providers.
7891 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007892 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007893 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007894 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 cpr.provider = null;
7896 cpr.app = null;
7897
7898 // See if someone is waiting for this provider... in which
7899 // case we don't remove it, but just let it restart.
7900 int i = 0;
7901 if (!app.bad) {
7902 for (; i<NL; i++) {
7903 if (mLaunchingProviders.get(i) == cpr) {
7904 restart = true;
7905 break;
7906 }
7907 }
7908 } else {
7909 i = NL;
7910 }
7911
7912 if (i >= NL) {
7913 removeDyingProviderLocked(app, cpr);
7914 NL = mLaunchingProviders.size();
7915 }
7916 }
7917 app.pubProviders.clear();
7918 }
7919
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007920 // Take care of any launching providers waiting for this process.
7921 if (checkAppInLaunchingProvidersLocked(app, false)) {
7922 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007925 // Unregister from connected content providers.
7926 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007927 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007928 while (it.hasNext()) {
7929 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7930 cpr.clients.remove(app);
7931 }
7932 app.conProviders.clear();
7933 }
7934
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007935 // At this point there may be remaining entries in mLaunchingProviders
7936 // where we were the only one waiting, so they are no longer of use.
7937 // Look for these and clean up if found.
7938 // XXX Commented out for now. Trying to figure out a way to reproduce
7939 // the actual situation to identify what is actually going on.
7940 if (false) {
7941 for (int i=0; i<NL; i++) {
7942 ContentProviderRecord cpr = (ContentProviderRecord)
7943 mLaunchingProviders.get(i);
7944 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7945 synchronized (cpr) {
7946 cpr.launchingApp = null;
7947 cpr.notifyAll();
7948 }
7949 }
7950 }
7951 }
7952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007953 skipCurrentReceiverLocked(app);
7954
7955 // Unregister any receivers.
7956 if (app.receivers.size() > 0) {
7957 Iterator<ReceiverList> it = app.receivers.iterator();
7958 while (it.hasNext()) {
7959 removeReceiverLocked(it.next());
7960 }
7961 app.receivers.clear();
7962 }
7963
Christopher Tate181fafa2009-05-14 11:12:14 -07007964 // If the app is undergoing backup, tell the backup manager about it
7965 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007966 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007967 try {
7968 IBackupManager bm = IBackupManager.Stub.asInterface(
7969 ServiceManager.getService(Context.BACKUP_SERVICE));
7970 bm.agentDisconnected(app.info.packageName);
7971 } catch (RemoteException e) {
7972 // can't happen; backup manager is local
7973 }
7974 }
7975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007976 // If the caller is restarting this app, then leave it in its
7977 // current lists and let the caller take care of it.
7978 if (restarting) {
7979 return;
7980 }
7981
7982 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007983 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007984 "Removing non-persistent process during cleanup: " + app);
7985 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007986 if (mHeavyWeightProcess == app) {
7987 mHeavyWeightProcess = null;
7988 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007990 } else if (!app.removed) {
7991 // This app is persistent, so we need to keep its record around.
7992 // If it is not already on the pending app list, add it there
7993 // and start a new process for it.
7994 app.thread = null;
7995 app.forcingToForeground = null;
7996 app.foregroundServices = false;
7997 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7998 mPersistentStartingProcesses.add(app);
7999 restart = true;
8000 }
8001 }
8002 mProcessesOnHold.remove(app);
8003
The Android Open Source Project4df24232009-03-05 14:34:35 -08008004 if (app == mHomeProcess) {
8005 mHomeProcess = null;
8006 }
8007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008008 if (restart) {
8009 // We have components that still need to be running in the
8010 // process, so re-launch it.
8011 mProcessNames.put(app.processName, app.info.uid, app);
8012 startProcessLocked(app, "restart", app.processName);
8013 } else if (app.pid > 0 && app.pid != MY_PID) {
8014 // Goodbye!
8015 synchronized (mPidsSelfLocked) {
8016 mPidsSelfLocked.remove(app.pid);
8017 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8018 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008019 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020 }
8021 }
8022
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008023 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8024 // Look through the content providers we are waiting to have launched,
8025 // and if any run in this process then either schedule a restart of
8026 // the process or kill the client waiting for it if this process has
8027 // gone bad.
8028 int NL = mLaunchingProviders.size();
8029 boolean restart = false;
8030 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008031 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008032 if (cpr.launchingApp == app) {
8033 if (!alwaysBad && !app.bad) {
8034 restart = true;
8035 } else {
8036 removeDyingProviderLocked(app, cpr);
8037 NL = mLaunchingProviders.size();
8038 }
8039 }
8040 }
8041 return restart;
8042 }
8043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 // =========================================================
8045 // SERVICES
8046 // =========================================================
8047
8048 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8049 ActivityManager.RunningServiceInfo info =
8050 new ActivityManager.RunningServiceInfo();
8051 info.service = r.name;
8052 if (r.app != null) {
8053 info.pid = r.app.pid;
8054 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008055 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008056 info.process = r.processName;
8057 info.foreground = r.isForeground;
8058 info.activeSince = r.createTime;
8059 info.started = r.startRequested;
8060 info.clientCount = r.connections.size();
8061 info.crashCount = r.crashCount;
8062 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008063 if (r.isForeground) {
8064 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8065 }
8066 if (r.startRequested) {
8067 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8068 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008069 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008070 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8071 }
8072 if (r.app != null && r.app.persistent) {
8073 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8074 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008075
8076 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8077 for (int i=0; i<connl.size(); i++) {
8078 ConnectionRecord conn = connl.get(i);
8079 if (conn.clientLabel != 0) {
8080 info.clientPackage = conn.binding.client.info.packageName;
8081 info.clientLabel = conn.clientLabel;
8082 return info;
8083 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008084 }
8085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086 return info;
8087 }
8088
8089 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8090 int flags) {
8091 synchronized (this) {
8092 ArrayList<ActivityManager.RunningServiceInfo> res
8093 = new ArrayList<ActivityManager.RunningServiceInfo>();
8094
8095 if (mServices.size() > 0) {
8096 Iterator<ServiceRecord> it = mServices.values().iterator();
8097 while (it.hasNext() && res.size() < maxNum) {
8098 res.add(makeRunningServiceInfoLocked(it.next()));
8099 }
8100 }
8101
8102 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8103 ServiceRecord r = mRestartingServices.get(i);
8104 ActivityManager.RunningServiceInfo info =
8105 makeRunningServiceInfoLocked(r);
8106 info.restarting = r.nextRestartTime;
8107 res.add(info);
8108 }
8109
8110 return res;
8111 }
8112 }
8113
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008114 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8115 synchronized (this) {
8116 ServiceRecord r = mServices.get(name);
8117 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008118 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8119 for (int i=0; i<conn.size(); i++) {
8120 if (conn.get(i).clientIntent != null) {
8121 return conn.get(i).clientIntent;
8122 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008123 }
8124 }
8125 }
8126 }
8127 return null;
8128 }
8129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008130 private final ServiceRecord findServiceLocked(ComponentName name,
8131 IBinder token) {
8132 ServiceRecord r = mServices.get(name);
8133 return r == token ? r : null;
8134 }
8135
8136 private final class ServiceLookupResult {
8137 final ServiceRecord record;
8138 final String permission;
8139
8140 ServiceLookupResult(ServiceRecord _record, String _permission) {
8141 record = _record;
8142 permission = _permission;
8143 }
8144 };
8145
8146 private ServiceLookupResult findServiceLocked(Intent service,
8147 String resolvedType) {
8148 ServiceRecord r = null;
8149 if (service.getComponent() != null) {
8150 r = mServices.get(service.getComponent());
8151 }
8152 if (r == null) {
8153 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8154 r = mServicesByIntent.get(filter);
8155 }
8156
8157 if (r == null) {
8158 try {
8159 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008160 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008161 service, resolvedType, 0);
8162 ServiceInfo sInfo =
8163 rInfo != null ? rInfo.serviceInfo : null;
8164 if (sInfo == null) {
8165 return null;
8166 }
8167
8168 ComponentName name = new ComponentName(
8169 sInfo.applicationInfo.packageName, sInfo.name);
8170 r = mServices.get(name);
8171 } catch (RemoteException ex) {
8172 // pm is in same process, this will never happen.
8173 }
8174 }
8175 if (r != null) {
8176 int callingPid = Binder.getCallingPid();
8177 int callingUid = Binder.getCallingUid();
8178 if (checkComponentPermission(r.permission,
8179 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8180 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008181 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008182 + " from pid=" + callingPid
8183 + ", uid=" + callingUid
8184 + " requires " + r.permission);
8185 return new ServiceLookupResult(null, r.permission);
8186 }
8187 return new ServiceLookupResult(r, null);
8188 }
8189 return null;
8190 }
8191
8192 private class ServiceRestarter implements Runnable {
8193 private ServiceRecord mService;
8194
8195 void setService(ServiceRecord service) {
8196 mService = service;
8197 }
8198
8199 public void run() {
8200 synchronized(ActivityManagerService.this) {
8201 performServiceRestartLocked(mService);
8202 }
8203 }
8204 }
8205
8206 private ServiceLookupResult retrieveServiceLocked(Intent service,
8207 String resolvedType, int callingPid, int callingUid) {
8208 ServiceRecord r = null;
8209 if (service.getComponent() != null) {
8210 r = mServices.get(service.getComponent());
8211 }
8212 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8213 r = mServicesByIntent.get(filter);
8214 if (r == null) {
8215 try {
8216 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008217 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008218 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 ServiceInfo sInfo =
8220 rInfo != null ? rInfo.serviceInfo : null;
8221 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008222 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 ": not found");
8224 return null;
8225 }
8226
8227 ComponentName name = new ComponentName(
8228 sInfo.applicationInfo.packageName, sInfo.name);
8229 r = mServices.get(name);
8230 if (r == null) {
8231 filter = new Intent.FilterComparison(service.cloneFilter());
8232 ServiceRestarter res = new ServiceRestarter();
8233 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8234 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8235 synchronized (stats) {
8236 ss = stats.getServiceStatsLocked(
8237 sInfo.applicationInfo.uid, sInfo.packageName,
8238 sInfo.name);
8239 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008240 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008241 res.setService(r);
8242 mServices.put(name, r);
8243 mServicesByIntent.put(filter, r);
8244
8245 // Make sure this component isn't in the pending list.
8246 int N = mPendingServices.size();
8247 for (int i=0; i<N; i++) {
8248 ServiceRecord pr = mPendingServices.get(i);
8249 if (pr.name.equals(name)) {
8250 mPendingServices.remove(i);
8251 i--;
8252 N--;
8253 }
8254 }
8255 }
8256 } catch (RemoteException ex) {
8257 // pm is in same process, this will never happen.
8258 }
8259 }
8260 if (r != null) {
8261 if (checkComponentPermission(r.permission,
8262 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8263 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008264 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008265 + " from pid=" + Binder.getCallingPid()
8266 + ", uid=" + Binder.getCallingUid()
8267 + " requires " + r.permission);
8268 return new ServiceLookupResult(null, r.permission);
8269 }
8270 return new ServiceLookupResult(r, null);
8271 }
8272 return null;
8273 }
8274
8275 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8276 long now = SystemClock.uptimeMillis();
8277 if (r.executeNesting == 0 && r.app != null) {
8278 if (r.app.executingServices.size() == 0) {
8279 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8280 msg.obj = r.app;
8281 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8282 }
8283 r.app.executingServices.add(r);
8284 }
8285 r.executeNesting++;
8286 r.executingStart = now;
8287 }
8288
8289 private final void sendServiceArgsLocked(ServiceRecord r,
8290 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008291 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008292 if (N == 0) {
8293 return;
8294 }
8295
Dianne Hackborn39792d22010-08-19 18:01:52 -07008296 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008297 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008298 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008299 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8300 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008301 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008302 // If somehow we got a dummy start at the front, then
8303 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008304 continue;
8305 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008306 si.deliveredTime = SystemClock.uptimeMillis();
8307 r.deliveredStarts.add(si);
8308 si.deliveryCount++;
8309 if (si.targetPermissionUid >= 0) {
8310 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008311 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008312 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008313 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008314 bumpServiceExecutingLocked(r);
8315 if (!oomAdjusted) {
8316 oomAdjusted = true;
8317 updateOomAdjLocked(r.app);
8318 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008319 int flags = 0;
8320 if (si.deliveryCount > 0) {
8321 flags |= Service.START_FLAG_RETRY;
8322 }
8323 if (si.doneExecutingCount > 0) {
8324 flags |= Service.START_FLAG_REDELIVERY;
8325 }
8326 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008327 } catch (RemoteException e) {
8328 // Remote process gone... we'll let the normal cleanup take
8329 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008330 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008331 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008332 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008333 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008334 break;
8335 }
8336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008337 }
8338
8339 private final boolean requestServiceBindingLocked(ServiceRecord r,
8340 IntentBindRecord i, boolean rebind) {
8341 if (r.app == null || r.app.thread == null) {
8342 // If service is not currently running, can't yet bind.
8343 return false;
8344 }
8345 if ((!i.requested || rebind) && i.apps.size() > 0) {
8346 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008347 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
8348 + " in " + i + ": shouldUnbind=" + i.hasBound);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008349 bumpServiceExecutingLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8351 if (!rebind) {
8352 i.requested = true;
8353 }
8354 i.hasBound = true;
8355 i.doRebind = false;
8356 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008357 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008358 return false;
8359 }
8360 }
8361 return true;
8362 }
8363
8364 private final void requestServiceBindingsLocked(ServiceRecord r) {
8365 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8366 while (bindings.hasNext()) {
8367 IntentBindRecord i = bindings.next();
8368 if (!requestServiceBindingLocked(r, i, false)) {
8369 break;
8370 }
8371 }
8372 }
8373
8374 private final void realStartServiceLocked(ServiceRecord r,
8375 ProcessRecord app) throws RemoteException {
8376 if (app.thread == null) {
8377 throw new RemoteException();
8378 }
8379
8380 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008381 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008382
8383 app.services.add(r);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008384 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008386 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008387
8388 boolean created = false;
8389 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008390 mStringBuilder.setLength(0);
8391 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008392 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008394 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008395 synchronized (r.stats.getBatteryStats()) {
8396 r.stats.startLaunchedLocked();
8397 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008398 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008399 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008400 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008401 created = true;
8402 } finally {
8403 if (!created) {
8404 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008405 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008406 }
8407 }
8408
8409 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008410
8411 // If the service is in the started state, and there are no
8412 // pending arguments, then fake up one so its onStartCommand() will
8413 // be called.
8414 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8415 r.lastStartId++;
8416 if (r.lastStartId < 1) {
8417 r.lastStartId = 1;
8418 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008419 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008420 }
8421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008422 sendServiceArgsLocked(r, true);
8423 }
8424
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008425 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8426 boolean allowCancel) {
8427 boolean canceled = false;
8428
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008429 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008430 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008431 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008432
8433 // Any delivered but not yet finished starts should be put back
8434 // on the pending list.
8435 final int N = r.deliveredStarts.size();
8436 if (N > 0) {
8437 for (int i=N-1; i>=0; i--) {
8438 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008439 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008440 if (si.intent == null) {
8441 // We'll generate this again if needed.
8442 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8443 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8444 r.pendingStarts.add(0, si);
8445 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8446 dur *= 2;
8447 if (minDuration < dur) minDuration = dur;
8448 if (resetTime < dur) resetTime = dur;
8449 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008450 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008451 + r.name);
8452 canceled = true;
8453 }
8454 }
8455 r.deliveredStarts.clear();
8456 }
8457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008458 r.totalRestartCount++;
8459 if (r.restartDelay == 0) {
8460 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008461 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008462 } else {
8463 // If it has been a "reasonably long time" since the service
8464 // was started, then reset our restart duration back to
8465 // the beginning, so we don't infinitely increase the duration
8466 // on a service that just occasionally gets killed (which is
8467 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008468 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008469 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008470 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008472 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008473 if (r.restartDelay < minDuration) {
8474 r.restartDelay = minDuration;
8475 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008476 }
8477 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008478
8479 r.nextRestartTime = now + r.restartDelay;
8480
8481 // Make sure that we don't end up restarting a bunch of services
8482 // all at the same time.
8483 boolean repeat;
8484 do {
8485 repeat = false;
8486 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8487 ServiceRecord r2 = mRestartingServices.get(i);
8488 if (r2 != r && r.nextRestartTime
8489 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8490 && r.nextRestartTime
8491 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8492 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8493 r.restartDelay = r.nextRestartTime - now;
8494 repeat = true;
8495 break;
8496 }
8497 }
8498 } while (repeat);
8499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008500 if (!mRestartingServices.contains(r)) {
8501 mRestartingServices.add(r);
8502 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008503
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008504 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008506 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008507 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008509 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008510 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008511 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008512 r.shortName, r.restartDelay);
8513
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008514 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 }
8516
8517 final void performServiceRestartLocked(ServiceRecord r) {
8518 if (!mRestartingServices.contains(r)) {
8519 return;
8520 }
8521 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8522 }
8523
8524 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8525 if (r.restartDelay == 0) {
8526 return false;
8527 }
8528 r.resetRestartCounter();
8529 mRestartingServices.remove(r);
8530 mHandler.removeCallbacks(r.restarter);
8531 return true;
8532 }
8533
8534 private final boolean bringUpServiceLocked(ServiceRecord r,
8535 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008536 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 //r.dump(" ");
8538
Dianne Hackborn36124872009-10-08 16:22:03 -07008539 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 sendServiceArgsLocked(r, false);
8541 return true;
8542 }
8543
8544 if (!whileRestarting && r.restartDelay > 0) {
8545 // If waiting for a restart, then do nothing.
8546 return true;
8547 }
8548
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008549 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008551 // We are now bringing the service up, so no longer in the
8552 // restarting state.
8553 mRestartingServices.remove(r);
8554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 final String appName = r.processName;
8556 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8557 if (app != null && app.thread != null) {
8558 try {
8559 realStartServiceLocked(r, app);
8560 return true;
8561 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008562 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008563 }
8564
8565 // If a dead object exception was thrown -- fall through to
8566 // restart the application.
8567 }
8568
Dianne Hackborn36124872009-10-08 16:22:03 -07008569 // Not running -- get it started, and enqueue this service record
8570 // to be executed when the app comes up.
8571 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8572 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008573 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008574 + r.appInfo.packageName + "/"
8575 + r.appInfo.uid + " for service "
8576 + r.intent.getIntent() + ": process is bad");
8577 bringDownServiceLocked(r, true);
8578 return false;
8579 }
8580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008581 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008582 mPendingServices.add(r);
8583 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008585 return true;
8586 }
8587
8588 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008589 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008590 //r.dump(" ");
8591
8592 // Does it still need to run?
8593 if (!force && r.startRequested) {
8594 return;
8595 }
8596 if (r.connections.size() > 0) {
8597 if (!force) {
8598 // XXX should probably keep a count of the number of auto-create
8599 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008600 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008601 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008602 ArrayList<ConnectionRecord> cr = it.next();
8603 for (int i=0; i<cr.size(); i++) {
8604 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8605 return;
8606 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 }
8608 }
8609 }
8610
8611 // Report to all of the connections that the service is no longer
8612 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008613 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008615 ArrayList<ConnectionRecord> c = it.next();
8616 for (int i=0; i<c.size(); i++) {
8617 try {
8618 c.get(i).conn.connected(r.name, null);
8619 } catch (Exception e) {
8620 Slog.w(TAG, "Failure disconnecting service " + r.name +
8621 " to connection " + c.get(i).conn.asBinder() +
8622 " (in " + c.get(i).binding.client.processName + ")", e);
8623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008624 }
8625 }
8626 }
8627
8628 // Tell the service that it has been unbound.
8629 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8630 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8631 while (it.hasNext()) {
8632 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008633 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008634 + ": hasBound=" + ibr.hasBound);
8635 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8636 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008637 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
8638 + " for " + ibr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 bumpServiceExecutingLocked(r);
8640 updateOomAdjLocked(r.app);
8641 ibr.hasBound = false;
8642 r.app.thread.scheduleUnbindService(r,
8643 ibr.intent.getIntent());
8644 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008645 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008646 + r.shortName, e);
8647 serviceDoneExecutingLocked(r, true);
8648 }
8649 }
8650 }
8651 }
8652
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008653 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008654 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008655 System.identityHashCode(r), r.shortName,
8656 (r.app != null) ? r.app.pid : -1);
8657
8658 mServices.remove(r.name);
8659 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 r.totalRestartCount = 0;
8661 unscheduleServiceRestartLocked(r);
8662
8663 // Also make sure it is not on the pending list.
8664 int N = mPendingServices.size();
8665 for (int i=0; i<N; i++) {
8666 if (mPendingServices.get(i) == r) {
8667 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008668 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 i--;
8670 N--;
8671 }
8672 }
8673
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008674 r.cancelNotification();
8675 r.isForeground = false;
8676 r.foregroundId = 0;
8677 r.foregroundNoti = null;
8678
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008679 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008680 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008681 r.pendingStarts.clear();
8682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 if (r.app != null) {
8684 synchronized (r.stats.getBatteryStats()) {
8685 r.stats.stopLaunchedLocked();
8686 }
8687 r.app.services.remove(r);
8688 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008690 if (DEBUG_SERVICE) {
8691 RuntimeException here = new RuntimeException();
8692 here.fillInStackTrace();
8693 Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
8694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008695 bumpServiceExecutingLocked(r);
8696 mStoppingServices.add(r);
8697 updateOomAdjLocked(r.app);
8698 r.app.thread.scheduleStopService(r);
8699 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008700 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008701 + r.shortName, e);
8702 serviceDoneExecutingLocked(r, true);
8703 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008704 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008705 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008706 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008707 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008708 }
8709 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008710 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008711 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008712 }
8713 }
8714
8715 ComponentName startServiceLocked(IApplicationThread caller,
8716 Intent service, String resolvedType,
8717 int callingPid, int callingUid) {
8718 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008719 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008720 + " type=" + resolvedType + " args=" + service.getExtras());
8721
8722 if (caller != null) {
8723 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8724 if (callerApp == null) {
8725 throw new SecurityException(
8726 "Unable to find app for caller " + caller
8727 + " (pid=" + Binder.getCallingPid()
8728 + ") when starting service " + service);
8729 }
8730 }
8731
8732 ServiceLookupResult res =
8733 retrieveServiceLocked(service, resolvedType,
8734 callingPid, callingUid);
8735 if (res == null) {
8736 return null;
8737 }
8738 if (res.record == null) {
8739 return new ComponentName("!", res.permission != null
8740 ? res.permission : "private to package");
8741 }
8742 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07008743 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
8744 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008746 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 }
8748 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008749 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008750 r.lastStartId++;
8751 if (r.lastStartId < 1) {
8752 r.lastStartId = 1;
8753 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008754 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
8755 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008756 r.lastActivity = SystemClock.uptimeMillis();
8757 synchronized (r.stats.getBatteryStats()) {
8758 r.stats.startRunningLocked();
8759 }
8760 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8761 return new ComponentName("!", "Service process is bad");
8762 }
8763 return r.name;
8764 }
8765 }
8766
8767 public ComponentName startService(IApplicationThread caller, Intent service,
8768 String resolvedType) {
8769 // Refuse possible leaked file descriptors
8770 if (service != null && service.hasFileDescriptors() == true) {
8771 throw new IllegalArgumentException("File descriptors passed in Intent");
8772 }
8773
8774 synchronized(this) {
8775 final int callingPid = Binder.getCallingPid();
8776 final int callingUid = Binder.getCallingUid();
8777 final long origId = Binder.clearCallingIdentity();
8778 ComponentName res = startServiceLocked(caller, service,
8779 resolvedType, callingPid, callingUid);
8780 Binder.restoreCallingIdentity(origId);
8781 return res;
8782 }
8783 }
8784
8785 ComponentName startServiceInPackage(int uid,
8786 Intent service, String resolvedType) {
8787 synchronized(this) {
8788 final long origId = Binder.clearCallingIdentity();
8789 ComponentName res = startServiceLocked(null, service,
8790 resolvedType, -1, uid);
8791 Binder.restoreCallingIdentity(origId);
8792 return res;
8793 }
8794 }
8795
8796 public int stopService(IApplicationThread caller, Intent service,
8797 String resolvedType) {
8798 // Refuse possible leaked file descriptors
8799 if (service != null && service.hasFileDescriptors() == true) {
8800 throw new IllegalArgumentException("File descriptors passed in Intent");
8801 }
8802
8803 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008804 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 + " type=" + resolvedType);
8806
8807 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8808 if (caller != null && callerApp == null) {
8809 throw new SecurityException(
8810 "Unable to find app for caller " + caller
8811 + " (pid=" + Binder.getCallingPid()
8812 + ") when stopping service " + service);
8813 }
8814
8815 // If this service is active, make sure it is stopped.
8816 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8817 if (r != null) {
8818 if (r.record != null) {
8819 synchronized (r.record.stats.getBatteryStats()) {
8820 r.record.stats.stopRunningLocked();
8821 }
8822 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008823 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008824 final long origId = Binder.clearCallingIdentity();
8825 bringDownServiceLocked(r.record, false);
8826 Binder.restoreCallingIdentity(origId);
8827 return 1;
8828 }
8829 return -1;
8830 }
8831 }
8832
8833 return 0;
8834 }
8835
8836 public IBinder peekService(Intent service, String resolvedType) {
8837 // Refuse possible leaked file descriptors
8838 if (service != null && service.hasFileDescriptors() == true) {
8839 throw new IllegalArgumentException("File descriptors passed in Intent");
8840 }
8841
8842 IBinder ret = null;
8843
8844 synchronized(this) {
8845 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8846
8847 if (r != null) {
8848 // r.record is null if findServiceLocked() failed the caller permission check
8849 if (r.record == null) {
8850 throw new SecurityException(
8851 "Permission Denial: Accessing service " + r.record.name
8852 + " from pid=" + Binder.getCallingPid()
8853 + ", uid=" + Binder.getCallingUid()
8854 + " requires " + r.permission);
8855 }
8856 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8857 if (ib != null) {
8858 ret = ib.binder;
8859 }
8860 }
8861 }
8862
8863 return ret;
8864 }
8865
8866 public boolean stopServiceToken(ComponentName className, IBinder token,
8867 int startId) {
8868 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008869 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008870 + " " + token + " startId=" + startId);
8871 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008872 if (r != null) {
8873 if (startId >= 0) {
8874 // Asked to only stop if done with all work. Note that
8875 // to avoid leaks, we will take this as dropping all
8876 // start items up to and including this one.
8877 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8878 if (si != null) {
8879 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008880 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
8881 cur.removeUriPermissionsLocked();
8882 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008883 break;
8884 }
8885 }
8886 }
8887
8888 if (r.lastStartId != startId) {
8889 return false;
8890 }
8891
8892 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008893 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008894 + " is last, but have " + r.deliveredStarts.size()
8895 + " remaining args");
8896 }
8897 }
8898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008899 synchronized (r.stats.getBatteryStats()) {
8900 r.stats.stopRunningLocked();
8901 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008902 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008903 }
8904 final long origId = Binder.clearCallingIdentity();
8905 bringDownServiceLocked(r, false);
8906 Binder.restoreCallingIdentity(origId);
8907 return true;
8908 }
8909 }
8910 return false;
8911 }
8912
8913 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008914 int id, Notification notification, boolean removeNotification) {
8915 final long origId = Binder.clearCallingIdentity();
8916 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 synchronized(this) {
8918 ServiceRecord r = findServiceLocked(className, token);
8919 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008920 if (id != 0) {
8921 if (notification == null) {
8922 throw new IllegalArgumentException("null notification");
8923 }
8924 if (r.foregroundId != id) {
8925 r.cancelNotification();
8926 r.foregroundId = id;
8927 }
8928 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8929 r.foregroundNoti = notification;
8930 r.isForeground = true;
8931 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008932 if (r.app != null) {
8933 updateServiceForegroundLocked(r.app, true);
8934 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008935 } else {
8936 if (r.isForeground) {
8937 r.isForeground = false;
8938 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008939 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008940 updateServiceForegroundLocked(r.app, true);
8941 }
8942 }
8943 if (removeNotification) {
8944 r.cancelNotification();
8945 r.foregroundId = 0;
8946 r.foregroundNoti = null;
8947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008948 }
8949 }
8950 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008951 } finally {
8952 Binder.restoreCallingIdentity(origId);
8953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008954 }
8955
8956 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8957 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008958 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008959 if (sr.isForeground) {
8960 anyForeground = true;
8961 break;
8962 }
8963 }
8964 if (anyForeground != proc.foregroundServices) {
8965 proc.foregroundServices = anyForeground;
8966 if (oomAdj) {
8967 updateOomAdjLocked();
8968 }
8969 }
8970 }
8971
8972 public int bindService(IApplicationThread caller, IBinder token,
8973 Intent service, String resolvedType,
8974 IServiceConnection connection, int flags) {
8975 // Refuse possible leaked file descriptors
8976 if (service != null && service.hasFileDescriptors() == true) {
8977 throw new IllegalArgumentException("File descriptors passed in Intent");
8978 }
8979
8980 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008981 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 + " type=" + resolvedType + " conn=" + connection.asBinder()
8983 + " flags=0x" + Integer.toHexString(flags));
8984 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8985 if (callerApp == null) {
8986 throw new SecurityException(
8987 "Unable to find app for caller " + caller
8988 + " (pid=" + Binder.getCallingPid()
8989 + ") when binding service " + service);
8990 }
8991
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008992 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008993 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008994 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008995 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008996 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008997 return 0;
8998 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008999 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000 }
9001
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009002 int clientLabel = 0;
9003 PendingIntent clientIntent = null;
9004
9005 if (callerApp.info.uid == Process.SYSTEM_UID) {
9006 // Hacky kind of thing -- allow system stuff to tell us
9007 // what they are, so we can report this elsewhere for
9008 // others to know why certain services are running.
9009 try {
9010 clientIntent = (PendingIntent)service.getParcelableExtra(
9011 Intent.EXTRA_CLIENT_INTENT);
9012 } catch (RuntimeException e) {
9013 }
9014 if (clientIntent != null) {
9015 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9016 if (clientLabel != 0) {
9017 // There are no useful extras in the intent, trash them.
9018 // System code calling with this stuff just needs to know
9019 // this will happen.
9020 service = service.cloneFilter();
9021 }
9022 }
9023 }
9024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009025 ServiceLookupResult res =
9026 retrieveServiceLocked(service, resolvedType,
9027 Binder.getCallingPid(), Binder.getCallingUid());
9028 if (res == null) {
9029 return 0;
9030 }
9031 if (res.record == null) {
9032 return -1;
9033 }
9034 ServiceRecord s = res.record;
9035
9036 final long origId = Binder.clearCallingIdentity();
9037
9038 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009039 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009040 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 }
9042
9043 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9044 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009045 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046
9047 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009048 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9049 if (clist == null) {
9050 clist = new ArrayList<ConnectionRecord>();
9051 s.connections.put(binder, clist);
9052 }
9053 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 b.connections.add(c);
9055 if (activity != null) {
9056 if (activity.connections == null) {
9057 activity.connections = new HashSet<ConnectionRecord>();
9058 }
9059 activity.connections.add(c);
9060 }
9061 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009062 clist = mServiceConnections.get(binder);
9063 if (clist == null) {
9064 clist = new ArrayList<ConnectionRecord>();
9065 mServiceConnections.put(binder, clist);
9066 }
9067 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068
9069 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9070 s.lastActivity = SystemClock.uptimeMillis();
9071 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9072 return 0;
9073 }
9074 }
9075
9076 if (s.app != null) {
9077 // This could have made the service more important.
9078 updateOomAdjLocked(s.app);
9079 }
9080
Joe Onorato8a9b2202010-02-26 18:56:32 -08009081 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009082 + ": received=" + b.intent.received
9083 + " apps=" + b.intent.apps.size()
9084 + " doRebind=" + b.intent.doRebind);
9085
9086 if (s.app != null && b.intent.received) {
9087 // Service is already running, so we can immediately
9088 // publish the connection.
9089 try {
9090 c.conn.connected(s.name, b.intent.binder);
9091 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009092 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009093 + " to connection " + c.conn.asBinder()
9094 + " (in " + c.binding.client.processName + ")", e);
9095 }
9096
9097 // If this is the first app connected back to this binding,
9098 // and the service had previously asked to be told when
9099 // rebound, then do so.
9100 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9101 requestServiceBindingLocked(s, b.intent, true);
9102 }
9103 } else if (!b.intent.requested) {
9104 requestServiceBindingLocked(s, b.intent, false);
9105 }
9106
9107 Binder.restoreCallingIdentity(origId);
9108 }
9109
9110 return 1;
9111 }
9112
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009113 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009114 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009115 IBinder binder = c.conn.asBinder();
9116 AppBindRecord b = c.binding;
9117 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009118 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9119 if (clist != null) {
9120 clist.remove(c);
9121 if (clist.size() == 0) {
9122 s.connections.remove(binder);
9123 }
9124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 b.connections.remove(c);
9126 if (c.activity != null && c.activity != skipAct) {
9127 if (c.activity.connections != null) {
9128 c.activity.connections.remove(c);
9129 }
9130 }
9131 if (b.client != skipApp) {
9132 b.client.connections.remove(c);
9133 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009134 clist = mServiceConnections.get(binder);
9135 if (clist != null) {
9136 clist.remove(c);
9137 if (clist.size() == 0) {
9138 mServiceConnections.remove(binder);
9139 }
9140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009141
9142 if (b.connections.size() == 0) {
9143 b.intent.apps.remove(b.client);
9144 }
9145
Joe Onorato8a9b2202010-02-26 18:56:32 -08009146 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 + ": shouldUnbind=" + b.intent.hasBound);
9148 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9149 && b.intent.hasBound) {
9150 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009151 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
9152 + " from " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 bumpServiceExecutingLocked(s);
9154 updateOomAdjLocked(s.app);
9155 b.intent.hasBound = false;
9156 // Assume the client doesn't want to know about a rebind;
9157 // we will deal with that later if it asks for one.
9158 b.intent.doRebind = false;
9159 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9160 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009161 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009162 serviceDoneExecutingLocked(s, true);
9163 }
9164 }
9165
9166 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9167 bringDownServiceLocked(s, false);
9168 }
9169 }
9170
9171 public boolean unbindService(IServiceConnection connection) {
9172 synchronized (this) {
9173 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009174 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009175 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9176 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009177 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 + connection.asBinder());
9179 return false;
9180 }
9181
9182 final long origId = Binder.clearCallingIdentity();
9183
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009184 while (clist.size() > 0) {
9185 ConnectionRecord r = clist.get(0);
9186 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009187
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009188 if (r.binding.service.app != null) {
9189 // This could have made the service less important.
9190 updateOomAdjLocked(r.binding.service.app);
9191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 }
9193
9194 Binder.restoreCallingIdentity(origId);
9195 }
9196
9197 return true;
9198 }
9199
9200 public void publishService(IBinder token, Intent intent, IBinder service) {
9201 // Refuse possible leaked file descriptors
9202 if (intent != null && intent.hasFileDescriptors() == true) {
9203 throw new IllegalArgumentException("File descriptors passed in Intent");
9204 }
9205
9206 synchronized(this) {
9207 if (!(token instanceof ServiceRecord)) {
9208 throw new IllegalArgumentException("Invalid service token");
9209 }
9210 ServiceRecord r = (ServiceRecord)token;
9211
9212 final long origId = Binder.clearCallingIdentity();
9213
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009214 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 + " " + intent + ": " + service);
9216 if (r != null) {
9217 Intent.FilterComparison filter
9218 = new Intent.FilterComparison(intent);
9219 IntentBindRecord b = r.bindings.get(filter);
9220 if (b != null && !b.received) {
9221 b.binder = service;
9222 b.requested = true;
9223 b.received = true;
9224 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009225 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009226 = r.connections.values().iterator();
9227 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009228 ArrayList<ConnectionRecord> clist = it.next();
9229 for (int i=0; i<clist.size(); i++) {
9230 ConnectionRecord c = clist.get(i);
9231 if (!filter.equals(c.binding.intent.intent)) {
9232 if (DEBUG_SERVICE) Slog.v(
9233 TAG, "Not publishing to: " + c);
9234 if (DEBUG_SERVICE) Slog.v(
9235 TAG, "Bound intent: " + c.binding.intent.intent);
9236 if (DEBUG_SERVICE) Slog.v(
9237 TAG, "Published intent: " + intent);
9238 continue;
9239 }
9240 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9241 try {
9242 c.conn.connected(r.name, service);
9243 } catch (Exception e) {
9244 Slog.w(TAG, "Failure sending service " + r.name +
9245 " to connection " + c.conn.asBinder() +
9246 " (in " + c.binding.client.processName + ")", e);
9247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009248 }
9249 }
9250 }
9251 }
9252
9253 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9254
9255 Binder.restoreCallingIdentity(origId);
9256 }
9257 }
9258 }
9259
9260 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9261 // Refuse possible leaked file descriptors
9262 if (intent != null && intent.hasFileDescriptors() == true) {
9263 throw new IllegalArgumentException("File descriptors passed in Intent");
9264 }
9265
9266 synchronized(this) {
9267 if (!(token instanceof ServiceRecord)) {
9268 throw new IllegalArgumentException("Invalid service token");
9269 }
9270 ServiceRecord r = (ServiceRecord)token;
9271
9272 final long origId = Binder.clearCallingIdentity();
9273
9274 if (r != null) {
9275 Intent.FilterComparison filter
9276 = new Intent.FilterComparison(intent);
9277 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009278 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 + " at " + b + ": apps="
9280 + (b != null ? b.apps.size() : 0));
9281 if (b != null) {
9282 if (b.apps.size() > 0) {
9283 // Applications have already bound since the last
9284 // unbind, so just rebind right here.
9285 requestServiceBindingLocked(r, b, true);
9286 } else {
9287 // Note to tell the service the next time there is
9288 // a new client.
9289 b.doRebind = true;
9290 }
9291 }
9292
9293 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9294
9295 Binder.restoreCallingIdentity(origId);
9296 }
9297 }
9298 }
9299
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009300 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009301 synchronized(this) {
9302 if (!(token instanceof ServiceRecord)) {
9303 throw new IllegalArgumentException("Invalid service token");
9304 }
9305 ServiceRecord r = (ServiceRecord)token;
9306 boolean inStopping = mStoppingServices.contains(token);
9307 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009309 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009310 + " with incorrect token: given " + token
9311 + ", expected " + r);
9312 return;
9313 }
9314
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009315 if (type == 1) {
9316 // This is a call from a service start... take care of
9317 // book-keeping.
9318 r.callStart = true;
9319 switch (res) {
9320 case Service.START_STICKY_COMPATIBILITY:
9321 case Service.START_STICKY: {
9322 // We are done with the associated start arguments.
9323 r.findDeliveredStart(startId, true);
9324 // Don't stop if killed.
9325 r.stopIfKilled = false;
9326 break;
9327 }
9328 case Service.START_NOT_STICKY: {
9329 // We are done with the associated start arguments.
9330 r.findDeliveredStart(startId, true);
9331 if (r.lastStartId == startId) {
9332 // There is no more work, and this service
9333 // doesn't want to hang around if killed.
9334 r.stopIfKilled = true;
9335 }
9336 break;
9337 }
9338 case Service.START_REDELIVER_INTENT: {
9339 // We'll keep this item until they explicitly
9340 // call stop for it, but keep track of the fact
9341 // that it was delivered.
9342 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9343 if (si != null) {
9344 si.deliveryCount = 0;
9345 si.doneExecutingCount++;
9346 // Don't stop if killed.
9347 r.stopIfKilled = true;
9348 }
9349 break;
9350 }
9351 default:
9352 throw new IllegalArgumentException(
9353 "Unknown service start result: " + res);
9354 }
9355 if (res == Service.START_STICKY_COMPATIBILITY) {
9356 r.callStart = false;
9357 }
9358 }
9359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 final long origId = Binder.clearCallingIdentity();
9361 serviceDoneExecutingLocked(r, inStopping);
9362 Binder.restoreCallingIdentity(origId);
9363 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009364 Slog.w(TAG, "Done executing unknown service from pid "
9365 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 }
9367 }
9368 }
9369
9370 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009371 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9372 + ": nesting=" + r.executeNesting
9373 + ", inStopping=" + inStopping + ", app=" + r.app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009374 r.executeNesting--;
9375 if (r.executeNesting <= 0 && r.app != null) {
9376 r.app.executingServices.remove(r);
9377 if (r.app.executingServices.size() == 0) {
9378 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9379 }
9380 if (inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009381 if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009382 mStoppingServices.remove(r);
9383 }
9384 updateOomAdjLocked(r.app);
9385 }
9386 }
9387
9388 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009389 String anrMessage = null;
9390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009391 synchronized(this) {
9392 if (proc.executingServices.size() == 0 || proc.thread == null) {
9393 return;
9394 }
9395 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9396 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9397 ServiceRecord timeout = null;
9398 long nextTime = 0;
9399 while (it.hasNext()) {
9400 ServiceRecord sr = it.next();
9401 if (sr.executingStart < maxTime) {
9402 timeout = sr;
9403 break;
9404 }
9405 if (sr.executingStart > nextTime) {
9406 nextTime = sr.executingStart;
9407 }
9408 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009409 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009410 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009411 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009412 } else {
9413 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9414 msg.obj = proc;
9415 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9416 }
9417 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009418
9419 if (anrMessage != null) {
9420 appNotResponding(proc, null, null, anrMessage);
9421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009422 }
9423
9424 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009425 // BACKUP AND RESTORE
9426 // =========================================================
9427
9428 // Cause the target app to be launched if necessary and its backup agent
9429 // instantiated. The backup agent will invoke backupAgentCreated() on the
9430 // activity manager to announce its creation.
9431 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009432 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009433 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9434
9435 synchronized(this) {
9436 // !!! TODO: currently no check here that we're already bound
9437 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9438 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9439 synchronized (stats) {
9440 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9441 }
9442
9443 BackupRecord r = new BackupRecord(ss, app, backupMode);
9444 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9445 // startProcessLocked() returns existing proc's record if it's already running
9446 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009447 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009448 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009449 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009450 return false;
9451 }
9452
9453 r.app = proc;
9454 mBackupTarget = r;
9455 mBackupAppName = app.packageName;
9456
Christopher Tate6fa95972009-06-05 18:43:55 -07009457 // Try not to kill the process during backup
9458 updateOomAdjLocked(proc);
9459
Christopher Tate181fafa2009-05-14 11:12:14 -07009460 // If the process is already attached, schedule the creation of the backup agent now.
9461 // If it is not yet live, this will be done when it attaches to the framework.
9462 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009463 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009464 try {
9465 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9466 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009467 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009468 }
9469 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009470 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009471 }
9472 // Invariants: at this point, the target app process exists and the application
9473 // is either already running or in the process of coming up. mBackupTarget and
9474 // mBackupAppName describe the app, so that when it binds back to the AM we
9475 // know that it's scheduled for a backup-agent operation.
9476 }
9477
9478 return true;
9479 }
9480
9481 // A backup agent has just come up
9482 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009483 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009484 + " = " + agent);
9485
9486 synchronized(this) {
9487 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009488 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009489 return;
9490 }
9491
Christopher Tate043dadc2009-06-02 16:11:00 -07009492 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009493 try {
9494 IBackupManager bm = IBackupManager.Stub.asInterface(
9495 ServiceManager.getService(Context.BACKUP_SERVICE));
9496 bm.agentConnected(agentPackageName, agent);
9497 } catch (RemoteException e) {
9498 // can't happen; the backup manager service is local
9499 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009500 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009501 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009502 } finally {
9503 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009504 }
9505 }
9506 }
9507
9508 // done with this agent
9509 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009510 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009511 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009512 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009513 return;
9514 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009515
9516 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009517 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009518 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009519 return;
9520 }
9521
Christopher Tate181fafa2009-05-14 11:12:14 -07009522 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009523 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009524 return;
9525 }
9526
Christopher Tate6fa95972009-06-05 18:43:55 -07009527 ProcessRecord proc = mBackupTarget.app;
9528 mBackupTarget = null;
9529 mBackupAppName = null;
9530
9531 // Not backing this app up any more; reset its OOM adjustment
9532 updateOomAdjLocked(proc);
9533
Christopher Tatec7b31e32009-06-10 15:49:30 -07009534 // If the app crashed during backup, 'thread' will be null here
9535 if (proc.thread != null) {
9536 try {
9537 proc.thread.scheduleDestroyBackupAgent(appInfo);
9538 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009539 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009540 e.printStackTrace();
9541 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009542 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009543 }
9544 }
9545 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009546 // BROADCASTS
9547 // =========================================================
9548
Josh Bartel7f208742010-02-25 11:01:44 -06009549 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 List cur) {
9551 final ContentResolver resolver = mContext.getContentResolver();
9552 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9553 if (list == null) {
9554 return cur;
9555 }
9556 int N = list.size();
9557 for (int i=0; i<N; i++) {
9558 Intent intent = list.get(i);
9559 if (filter.match(resolver, intent, true, TAG) >= 0) {
9560 if (cur == null) {
9561 cur = new ArrayList<Intent>();
9562 }
9563 cur.add(intent);
9564 }
9565 }
9566 return cur;
9567 }
9568
9569 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009570 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009571 + mBroadcastsScheduled);
9572
9573 if (mBroadcastsScheduled) {
9574 return;
9575 }
9576 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9577 mBroadcastsScheduled = true;
9578 }
9579
9580 public Intent registerReceiver(IApplicationThread caller,
9581 IIntentReceiver receiver, IntentFilter filter, String permission) {
9582 synchronized(this) {
9583 ProcessRecord callerApp = null;
9584 if (caller != null) {
9585 callerApp = getRecordForAppLocked(caller);
9586 if (callerApp == null) {
9587 throw new SecurityException(
9588 "Unable to find app for caller " + caller
9589 + " (pid=" + Binder.getCallingPid()
9590 + ") when registering receiver " + receiver);
9591 }
9592 }
9593
9594 List allSticky = null;
9595
9596 // Look for any matching sticky broadcasts...
9597 Iterator actions = filter.actionsIterator();
9598 if (actions != null) {
9599 while (actions.hasNext()) {
9600 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009601 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009602 }
9603 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009604 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009605 }
9606
9607 // The first sticky in the list is returned directly back to
9608 // the client.
9609 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9610
Joe Onorato8a9b2202010-02-26 18:56:32 -08009611 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009612 + ": " + sticky);
9613
9614 if (receiver == null) {
9615 return sticky;
9616 }
9617
9618 ReceiverList rl
9619 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9620 if (rl == null) {
9621 rl = new ReceiverList(this, callerApp,
9622 Binder.getCallingPid(),
9623 Binder.getCallingUid(), receiver);
9624 if (rl.app != null) {
9625 rl.app.receivers.add(rl);
9626 } else {
9627 try {
9628 receiver.asBinder().linkToDeath(rl, 0);
9629 } catch (RemoteException e) {
9630 return sticky;
9631 }
9632 rl.linkedToDeath = true;
9633 }
9634 mRegisteredReceivers.put(receiver.asBinder(), rl);
9635 }
9636 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9637 rl.add(bf);
9638 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009639 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009640 }
9641 mReceiverResolver.addFilter(bf);
9642
9643 // Enqueue broadcasts for all existing stickies that match
9644 // this filter.
9645 if (allSticky != null) {
9646 ArrayList receivers = new ArrayList();
9647 receivers.add(bf);
9648
9649 int N = allSticky.size();
9650 for (int i=0; i<N; i++) {
9651 Intent intent = (Intent)allSticky.get(i);
9652 BroadcastRecord r = new BroadcastRecord(intent, null,
9653 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009654 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009655 if (mParallelBroadcasts.size() == 0) {
9656 scheduleBroadcastsLocked();
9657 }
9658 mParallelBroadcasts.add(r);
9659 }
9660 }
9661
9662 return sticky;
9663 }
9664 }
9665
9666 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009667 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009668
9669 boolean doNext = false;
9670
9671 synchronized(this) {
9672 ReceiverList rl
9673 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9674 if (rl != null) {
9675 if (rl.curBroadcast != null) {
9676 BroadcastRecord r = rl.curBroadcast;
9677 doNext = finishReceiverLocked(
9678 receiver.asBinder(), r.resultCode, r.resultData,
9679 r.resultExtras, r.resultAbort, true);
9680 }
9681
9682 if (rl.app != null) {
9683 rl.app.receivers.remove(rl);
9684 }
9685 removeReceiverLocked(rl);
9686 if (rl.linkedToDeath) {
9687 rl.linkedToDeath = false;
9688 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9689 }
9690 }
9691 }
9692
9693 if (!doNext) {
9694 return;
9695 }
9696
9697 final long origId = Binder.clearCallingIdentity();
9698 processNextBroadcast(false);
9699 trimApplications();
9700 Binder.restoreCallingIdentity(origId);
9701 }
9702
9703 void removeReceiverLocked(ReceiverList rl) {
9704 mRegisteredReceivers.remove(rl.receiver.asBinder());
9705 int N = rl.size();
9706 for (int i=0; i<N; i++) {
9707 mReceiverResolver.removeFilter(rl.get(i));
9708 }
9709 }
9710
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009711 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9712 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9713 ProcessRecord r = mLruProcesses.get(i);
9714 if (r.thread != null) {
9715 try {
9716 r.thread.dispatchPackageBroadcast(cmd, packages);
9717 } catch (RemoteException ex) {
9718 }
9719 }
9720 }
9721 }
9722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009723 private final int broadcastIntentLocked(ProcessRecord callerApp,
9724 String callerPackage, Intent intent, String resolvedType,
9725 IIntentReceiver resultTo, int resultCode, String resultData,
9726 Bundle map, String requiredPermission,
9727 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9728 intent = new Intent(intent);
9729
Joe Onorato8a9b2202010-02-26 18:56:32 -08009730 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009731 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9732 + " ordered=" + ordered);
9733 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009734 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009735 }
9736
9737 // Handle special intents: if this broadcast is from the package
9738 // manager about a package being removed, we need to remove all of
9739 // its activities from the history stack.
9740 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9741 intent.getAction());
9742 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9743 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009744 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009745 || uidRemoved) {
9746 if (checkComponentPermission(
9747 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9748 callingPid, callingUid, -1)
9749 == PackageManager.PERMISSION_GRANTED) {
9750 if (uidRemoved) {
9751 final Bundle intentExtras = intent.getExtras();
9752 final int uid = intentExtras != null
9753 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9754 if (uid >= 0) {
9755 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9756 synchronized (bs) {
9757 bs.removeUidStatsLocked(uid);
9758 }
9759 }
9760 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009761 // If resources are unvailble just force stop all
9762 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009763 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009764 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9765 if (list != null && (list.length > 0)) {
9766 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009767 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009768 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009769 sendPackageBroadcastLocked(
9770 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009771 }
9772 } else {
9773 Uri data = intent.getData();
9774 String ssp;
9775 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9776 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9777 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009778 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009779 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009780 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9781 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9782 new String[] {ssp});
9783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 }
9785 }
9786 }
9787 } else {
9788 String msg = "Permission Denial: " + intent.getAction()
9789 + " broadcast from " + callerPackage + " (pid=" + callingPid
9790 + ", uid=" + callingUid + ")"
9791 + " requires "
9792 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009793 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 throw new SecurityException(msg);
9795 }
9796 }
9797
9798 /*
9799 * If this is the time zone changed action, queue up a message that will reset the timezone
9800 * of all currently running processes. This message will get queued up before the broadcast
9801 * happens.
9802 */
9803 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9804 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9805 }
9806
Dianne Hackborn854060af2009-07-09 18:14:31 -07009807 /*
9808 * Prevent non-system code (defined here to be non-persistent
9809 * processes) from sending protected broadcasts.
9810 */
9811 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9812 || callingUid == Process.SHELL_UID || callingUid == 0) {
9813 // Always okay.
9814 } else if (callerApp == null || !callerApp.persistent) {
9815 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009816 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009817 intent.getAction())) {
9818 String msg = "Permission Denial: not allowed to send broadcast "
9819 + intent.getAction() + " from pid="
9820 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009821 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009822 throw new SecurityException(msg);
9823 }
9824 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009825 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009826 return BROADCAST_SUCCESS;
9827 }
9828 }
9829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 // Add to the sticky list if requested.
9831 if (sticky) {
9832 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9833 callingPid, callingUid)
9834 != PackageManager.PERMISSION_GRANTED) {
9835 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9836 + callingPid + ", uid=" + callingUid
9837 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009838 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 throw new SecurityException(msg);
9840 }
9841 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009842 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009843 + " and enforce permission " + requiredPermission);
9844 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9845 }
9846 if (intent.getComponent() != null) {
9847 throw new SecurityException(
9848 "Sticky broadcasts can't target a specific component");
9849 }
9850 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9851 if (list == null) {
9852 list = new ArrayList<Intent>();
9853 mStickyBroadcasts.put(intent.getAction(), list);
9854 }
9855 int N = list.size();
9856 int i;
9857 for (i=0; i<N; i++) {
9858 if (intent.filterEquals(list.get(i))) {
9859 // This sticky already exists, replace it.
9860 list.set(i, new Intent(intent));
9861 break;
9862 }
9863 }
9864 if (i >= N) {
9865 list.add(new Intent(intent));
9866 }
9867 }
9868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009869 // Figure out who all will receive this broadcast.
9870 List receivers = null;
9871 List<BroadcastFilter> registeredReceivers = null;
9872 try {
9873 if (intent.getComponent() != null) {
9874 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009875 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009876 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 if (ai != null) {
9878 receivers = new ArrayList();
9879 ResolveInfo ri = new ResolveInfo();
9880 ri.activityInfo = ai;
9881 receivers.add(ri);
9882 }
9883 } else {
9884 // Need to resolve the intent to interested receivers...
9885 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9886 == 0) {
9887 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009888 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009889 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009890 }
Mihai Preda074edef2009-05-18 17:13:31 +02009891 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 }
9893 } catch (RemoteException ex) {
9894 // pm is in same process, this will never happen.
9895 }
9896
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009897 final boolean replacePending =
9898 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9899
Joe Onorato8a9b2202010-02-26 18:56:32 -08009900 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009901 + " replacePending=" + replacePending);
9902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9904 if (!ordered && NR > 0) {
9905 // If we are not serializing this broadcast, then send the
9906 // registered receivers separately so they don't wait for the
9907 // components to be launched.
9908 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9909 callerPackage, callingPid, callingUid, requiredPermission,
9910 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009911 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009912 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009913 TAG, "Enqueueing parallel broadcast " + r
9914 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009915 boolean replaced = false;
9916 if (replacePending) {
9917 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9918 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009919 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009920 "***** DROPPING PARALLEL: " + intent);
9921 mParallelBroadcasts.set(i, r);
9922 replaced = true;
9923 break;
9924 }
9925 }
9926 }
9927 if (!replaced) {
9928 mParallelBroadcasts.add(r);
9929 scheduleBroadcastsLocked();
9930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009931 registeredReceivers = null;
9932 NR = 0;
9933 }
9934
9935 // Merge into one list.
9936 int ir = 0;
9937 if (receivers != null) {
9938 // A special case for PACKAGE_ADDED: do not allow the package
9939 // being added to see this broadcast. This prevents them from
9940 // using this as a back door to get run as soon as they are
9941 // installed. Maybe in the future we want to have a special install
9942 // broadcast or such for apps, but we'd like to deliberately make
9943 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009944 String skipPackages[] = null;
9945 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9946 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9947 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9948 Uri data = intent.getData();
9949 if (data != null) {
9950 String pkgName = data.getSchemeSpecificPart();
9951 if (pkgName != null) {
9952 skipPackages = new String[] { pkgName };
9953 }
9954 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009955 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009956 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009957 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009958 if (skipPackages != null && (skipPackages.length > 0)) {
9959 for (String skipPackage : skipPackages) {
9960 if (skipPackage != null) {
9961 int NT = receivers.size();
9962 for (int it=0; it<NT; it++) {
9963 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9964 if (curt.activityInfo.packageName.equals(skipPackage)) {
9965 receivers.remove(it);
9966 it--;
9967 NT--;
9968 }
9969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009970 }
9971 }
9972 }
9973
9974 int NT = receivers != null ? receivers.size() : 0;
9975 int it = 0;
9976 ResolveInfo curt = null;
9977 BroadcastFilter curr = null;
9978 while (it < NT && ir < NR) {
9979 if (curt == null) {
9980 curt = (ResolveInfo)receivers.get(it);
9981 }
9982 if (curr == null) {
9983 curr = registeredReceivers.get(ir);
9984 }
9985 if (curr.getPriority() >= curt.priority) {
9986 // Insert this broadcast record into the final list.
9987 receivers.add(it, curr);
9988 ir++;
9989 curr = null;
9990 it++;
9991 NT++;
9992 } else {
9993 // Skip to the next ResolveInfo in the final list.
9994 it++;
9995 curt = null;
9996 }
9997 }
9998 }
9999 while (ir < NR) {
10000 if (receivers == null) {
10001 receivers = new ArrayList();
10002 }
10003 receivers.add(registeredReceivers.get(ir));
10004 ir++;
10005 }
10006
10007 if ((receivers != null && receivers.size() > 0)
10008 || resultTo != null) {
10009 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10010 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010011 receivers, resultTo, resultCode, resultData, map, ordered,
10012 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010013 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010014 TAG, "Enqueueing ordered broadcast " + r
10015 + ": prev had " + mOrderedBroadcasts.size());
10016 if (DEBUG_BROADCAST) {
10017 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010018 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010019 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010020 boolean replaced = false;
10021 if (replacePending) {
10022 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10023 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010024 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010025 "***** DROPPING ORDERED: " + intent);
10026 mOrderedBroadcasts.set(i, r);
10027 replaced = true;
10028 break;
10029 }
10030 }
10031 }
10032 if (!replaced) {
10033 mOrderedBroadcasts.add(r);
10034 scheduleBroadcastsLocked();
10035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010036 }
10037
10038 return BROADCAST_SUCCESS;
10039 }
10040
10041 public final int broadcastIntent(IApplicationThread caller,
10042 Intent intent, String resolvedType, IIntentReceiver resultTo,
10043 int resultCode, String resultData, Bundle map,
10044 String requiredPermission, boolean serialized, boolean sticky) {
10045 // Refuse possible leaked file descriptors
10046 if (intent != null && intent.hasFileDescriptors() == true) {
10047 throw new IllegalArgumentException("File descriptors passed in Intent");
10048 }
10049
10050 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010051 int flags = intent.getFlags();
10052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 if (!mSystemReady) {
10054 // if the caller really truly claims to know what they're doing, go
10055 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10057 intent = new Intent(intent);
10058 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10059 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080010060 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010061 + " before boot completion");
10062 throw new IllegalStateException("Cannot broadcast before boot completed");
10063 }
10064 }
10065
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010066 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10067 throw new IllegalArgumentException(
10068 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10069 }
10070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010071 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10072 final int callingPid = Binder.getCallingPid();
10073 final int callingUid = Binder.getCallingUid();
10074 final long origId = Binder.clearCallingIdentity();
10075 int res = broadcastIntentLocked(callerApp,
10076 callerApp != null ? callerApp.info.packageName : null,
10077 intent, resolvedType, resultTo,
10078 resultCode, resultData, map, requiredPermission, serialized,
10079 sticky, callingPid, callingUid);
10080 Binder.restoreCallingIdentity(origId);
10081 return res;
10082 }
10083 }
10084
10085 int broadcastIntentInPackage(String packageName, int uid,
10086 Intent intent, String resolvedType, IIntentReceiver resultTo,
10087 int resultCode, String resultData, Bundle map,
10088 String requiredPermission, boolean serialized, boolean sticky) {
10089 synchronized(this) {
10090 final long origId = Binder.clearCallingIdentity();
10091 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10092 resultTo, resultCode, resultData, map, requiredPermission,
10093 serialized, sticky, -1, uid);
10094 Binder.restoreCallingIdentity(origId);
10095 return res;
10096 }
10097 }
10098
10099 public final void unbroadcastIntent(IApplicationThread caller,
10100 Intent intent) {
10101 // Refuse possible leaked file descriptors
10102 if (intent != null && intent.hasFileDescriptors() == true) {
10103 throw new IllegalArgumentException("File descriptors passed in Intent");
10104 }
10105
10106 synchronized(this) {
10107 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10108 != PackageManager.PERMISSION_GRANTED) {
10109 String msg = "Permission Denial: unbroadcastIntent() from pid="
10110 + Binder.getCallingPid()
10111 + ", uid=" + Binder.getCallingUid()
10112 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010113 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 throw new SecurityException(msg);
10115 }
10116 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10117 if (list != null) {
10118 int N = list.size();
10119 int i;
10120 for (i=0; i<N; i++) {
10121 if (intent.filterEquals(list.get(i))) {
10122 list.remove(i);
10123 break;
10124 }
10125 }
10126 }
10127 }
10128 }
10129
10130 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10131 String resultData, Bundle resultExtras, boolean resultAbort,
10132 boolean explicit) {
10133 if (mOrderedBroadcasts.size() == 0) {
10134 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010135 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010136 }
10137 return false;
10138 }
10139 BroadcastRecord r = mOrderedBroadcasts.get(0);
10140 if (r.receiver == null) {
10141 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010142 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010143 }
10144 return false;
10145 }
10146 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010147 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 return false;
10149 }
10150 int state = r.state;
10151 r.state = r.IDLE;
10152 if (state == r.IDLE) {
10153 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010154 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 }
10156 }
10157 r.receiver = null;
10158 r.intent.setComponent(null);
10159 if (r.curApp != null) {
10160 r.curApp.curReceiver = null;
10161 }
10162 if (r.curFilter != null) {
10163 r.curFilter.receiverList.curBroadcast = null;
10164 }
10165 r.curFilter = null;
10166 r.curApp = null;
10167 r.curComponent = null;
10168 r.curReceiver = null;
10169 mPendingBroadcast = null;
10170
10171 r.resultCode = resultCode;
10172 r.resultData = resultData;
10173 r.resultExtras = resultExtras;
10174 r.resultAbort = resultAbort;
10175
10176 // We will process the next receiver right now if this is finishing
10177 // an app receiver (which is always asynchronous) or after we have
10178 // come back from calling a receiver.
10179 return state == BroadcastRecord.APP_RECEIVE
10180 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10181 }
10182
10183 public void finishReceiver(IBinder who, int resultCode, String resultData,
10184 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010185 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010186
10187 // Refuse possible leaked file descriptors
10188 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10189 throw new IllegalArgumentException("File descriptors passed in Bundle");
10190 }
10191
10192 boolean doNext;
10193
10194 final long origId = Binder.clearCallingIdentity();
10195
10196 synchronized(this) {
10197 doNext = finishReceiverLocked(
10198 who, resultCode, resultData, resultExtras, resultAbort, true);
10199 }
10200
10201 if (doNext) {
10202 processNextBroadcast(false);
10203 }
10204 trimApplications();
10205
10206 Binder.restoreCallingIdentity(origId);
10207 }
10208
10209 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10210 if (r.nextReceiver > 0) {
10211 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10212 if (curReceiver instanceof BroadcastFilter) {
10213 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010214 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010215 System.identityHashCode(r),
10216 r.intent.getAction(),
10217 r.nextReceiver - 1,
10218 System.identityHashCode(bf));
10219 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010220 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010221 System.identityHashCode(r),
10222 r.intent.getAction(),
10223 r.nextReceiver - 1,
10224 ((ResolveInfo)curReceiver).toString());
10225 }
10226 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010227 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010228 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010229 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 System.identityHashCode(r),
10231 r.intent.getAction(),
10232 r.nextReceiver,
10233 "NONE");
10234 }
10235 }
10236
10237 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010238 ProcessRecord app = null;
10239 String anrMessage = null;
10240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010241 synchronized (this) {
10242 if (mOrderedBroadcasts.size() == 0) {
10243 return;
10244 }
10245 long now = SystemClock.uptimeMillis();
10246 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010247 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010248 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010250 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010252 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010253 return;
10254 }
10255
Joe Onorato8a9b2202010-02-26 18:56:32 -080010256 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010257 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010258 r.anrCount++;
10259
10260 // Current receiver has passed its expiration date.
10261 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010262 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010263 return;
10264 }
10265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010267 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010268 logBroadcastReceiverDiscard(r);
10269 if (curReceiver instanceof BroadcastFilter) {
10270 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10271 if (bf.receiverList.pid != 0
10272 && bf.receiverList.pid != MY_PID) {
10273 synchronized (this.mPidsSelfLocked) {
10274 app = this.mPidsSelfLocked.get(
10275 bf.receiverList.pid);
10276 }
10277 }
10278 } else {
10279 app = r.curApp;
10280 }
10281
10282 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010283 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 }
10285
10286 if (mPendingBroadcast == r) {
10287 mPendingBroadcast = null;
10288 }
10289
10290 // Move on to the next receiver.
10291 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10292 r.resultExtras, r.resultAbort, true);
10293 scheduleBroadcastsLocked();
10294 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010295
10296 if (anrMessage != null) {
10297 appNotResponding(app, null, null, anrMessage);
10298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 }
10300
10301 private final void processCurBroadcastLocked(BroadcastRecord r,
10302 ProcessRecord app) throws RemoteException {
10303 if (app.thread == null) {
10304 throw new RemoteException();
10305 }
10306 r.receiver = app.thread.asBinder();
10307 r.curApp = app;
10308 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010309 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010310
10311 // Tell the application to launch this receiver.
10312 r.intent.setComponent(r.curComponent);
10313
10314 boolean started = false;
10315 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010316 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010317 "Delivering to component " + r.curComponent
10318 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010319 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10321 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10322 started = true;
10323 } finally {
10324 if (!started) {
10325 r.receiver = null;
10326 r.curApp = null;
10327 app.curReceiver = null;
10328 }
10329 }
10330
10331 }
10332
10333 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010334 Intent intent, int resultCode, String data, Bundle extras,
10335 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010336 if (app != null && app.thread != null) {
10337 // If we have an app thread, do the call through that so it is
10338 // correctly ordered with other one-way calls.
10339 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010340 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010341 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010342 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010343 }
10344 }
10345
10346 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10347 BroadcastFilter filter, boolean ordered) {
10348 boolean skip = false;
10349 if (filter.requiredPermission != null) {
10350 int perm = checkComponentPermission(filter.requiredPermission,
10351 r.callingPid, r.callingUid, -1);
10352 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010353 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 + r.intent.toString()
10355 + " from " + r.callerPackage + " (pid="
10356 + r.callingPid + ", uid=" + r.callingUid + ")"
10357 + " requires " + filter.requiredPermission
10358 + " due to registered receiver " + filter);
10359 skip = true;
10360 }
10361 }
10362 if (r.requiredPermission != null) {
10363 int perm = checkComponentPermission(r.requiredPermission,
10364 filter.receiverList.pid, filter.receiverList.uid, -1);
10365 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010366 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 + r.intent.toString()
10368 + " to " + filter.receiverList.app
10369 + " (pid=" + filter.receiverList.pid
10370 + ", uid=" + filter.receiverList.uid + ")"
10371 + " requires " + r.requiredPermission
10372 + " due to sender " + r.callerPackage
10373 + " (uid " + r.callingUid + ")");
10374 skip = true;
10375 }
10376 }
10377
10378 if (!skip) {
10379 // If this is not being sent as an ordered broadcast, then we
10380 // don't want to touch the fields that keep track of the current
10381 // state of ordered broadcasts.
10382 if (ordered) {
10383 r.receiver = filter.receiverList.receiver.asBinder();
10384 r.curFilter = filter;
10385 filter.receiverList.curBroadcast = r;
10386 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010387 if (filter.receiverList.app != null) {
10388 // Bump hosting application to no longer be in background
10389 // scheduling class. Note that we can't do that if there
10390 // isn't an app... but we can only be in that case for
10391 // things that directly call the IActivityManager API, which
10392 // are already core system stuff so don't matter for this.
10393 r.curApp = filter.receiverList.app;
10394 filter.receiverList.app.curReceiver = r;
10395 updateOomAdjLocked();
10396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010397 }
10398 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010399 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010401 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010402 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403 }
10404 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10405 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010406 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010407 if (ordered) {
10408 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10409 }
10410 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010411 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010412 if (ordered) {
10413 r.receiver = null;
10414 r.curFilter = null;
10415 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010416 if (filter.receiverList.app != null) {
10417 filter.receiverList.app.curReceiver = null;
10418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010419 }
10420 }
10421 }
10422 }
10423
Dianne Hackborn12527f92009-11-11 17:39:50 -080010424 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10425 if (r.callingUid < 0) {
10426 // This was from a registerReceiver() call; ignore it.
10427 return;
10428 }
10429 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10430 MAX_BROADCAST_HISTORY-1);
10431 r.finishTime = SystemClock.uptimeMillis();
10432 mBroadcastHistory[0] = r;
10433 }
10434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 private final void processNextBroadcast(boolean fromMsg) {
10436 synchronized(this) {
10437 BroadcastRecord r;
10438
Joe Onorato8a9b2202010-02-26 18:56:32 -080010439 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010440 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010441 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010442
10443 updateCpuStats();
10444
10445 if (fromMsg) {
10446 mBroadcastsScheduled = false;
10447 }
10448
10449 // First, deliver any non-serialized broadcasts right away.
10450 while (mParallelBroadcasts.size() > 0) {
10451 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010452 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010453 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010454 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010455 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 for (int i=0; i<N; i++) {
10457 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010458 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010459 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 + target + ": " + r);
10461 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10462 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010463 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010464 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010465 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010466 }
10467
10468 // Now take care of the next serialized one...
10469
10470 // If we are waiting for a process to come up to handle the next
10471 // broadcast, then do nothing at this point. Just in case, we
10472 // check that the process we're waiting for still exists.
10473 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010474 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010475 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010476 + mPendingBroadcast.curApp);
10477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010478
10479 boolean isDead;
10480 synchronized (mPidsSelfLocked) {
10481 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10482 }
10483 if (!isDead) {
10484 // It's still alive, so keep waiting
10485 return;
10486 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010487 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010488 + " died before responding to broadcast");
10489 mPendingBroadcast = null;
10490 }
10491 }
10492
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010493 boolean looped = false;
10494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010495 do {
10496 if (mOrderedBroadcasts.size() == 0) {
10497 // No more broadcasts pending, so all done!
10498 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010499 if (looped) {
10500 // If we had finished the last ordered broadcast, then
10501 // make sure all processes have correct oom and sched
10502 // adjustments.
10503 updateOomAdjLocked();
10504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010505 return;
10506 }
10507 r = mOrderedBroadcasts.get(0);
10508 boolean forceReceive = false;
10509
10510 // Ensure that even if something goes awry with the timeout
10511 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010512 // and continue to make progress.
10513 //
10514 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10515 // receivers don't get executed with with timeouts. They're intended for
10516 // one time heavy lifting after system upgrades and can take
10517 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010519 if (mSystemReady && r.dispatchTime > 0) {
10520 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010521 if ((numReceivers > 0) &&
10522 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010523 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524 + " now=" + now
10525 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010526 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010527 + " intent=" + r.intent
10528 + " numReceivers=" + numReceivers
10529 + " nextReceiver=" + r.nextReceiver
10530 + " state=" + r.state);
10531 broadcastTimeout(); // forcibly finish this broadcast
10532 forceReceive = true;
10533 r.state = BroadcastRecord.IDLE;
10534 }
10535 }
10536
10537 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010538 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 "processNextBroadcast() called when not idle (state="
10540 + r.state + ")");
10541 return;
10542 }
10543
10544 if (r.receivers == null || r.nextReceiver >= numReceivers
10545 || r.resultAbort || forceReceive) {
10546 // No more receivers for this broadcast! Send the final
10547 // result if requested...
10548 if (r.resultTo != null) {
10549 try {
10550 if (DEBUG_BROADCAST) {
10551 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010552 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010553 + " seq=" + seq + " app=" + r.callerApp);
10554 }
10555 performReceive(r.callerApp, r.resultTo,
10556 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010557 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010558 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010559 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010560 }
10561 }
10562
Joe Onorato8a9b2202010-02-26 18:56:32 -080010563 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010564 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10565
Joe Onorato8a9b2202010-02-26 18:56:32 -080010566 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010567 + r);
10568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010569 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010570 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010571 mOrderedBroadcasts.remove(0);
10572 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010573 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010574 continue;
10575 }
10576 } while (r == null);
10577
10578 // Get the next receiver...
10579 int recIdx = r.nextReceiver++;
10580
10581 // Keep track of when this receiver started, and make sure there
10582 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010583 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010584 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010585 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010586
Joe Onorato8a9b2202010-02-26 18:56:32 -080010587 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010588 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010589 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010590 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010591 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010593 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010594 }
10595
10596 Object nextReceiver = r.receivers.get(recIdx);
10597 if (nextReceiver instanceof BroadcastFilter) {
10598 // Simple case: this is a registered receiver who gets
10599 // a direct call.
10600 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010601 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010602 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010603 + filter + ": " + r);
10604 deliverToRegisteredReceiver(r, filter, r.ordered);
10605 if (r.receiver == null || !r.ordered) {
10606 // The receiver has already finished, so schedule to
10607 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010608 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10609 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010610 r.state = BroadcastRecord.IDLE;
10611 scheduleBroadcastsLocked();
10612 }
10613 return;
10614 }
10615
10616 // Hard case: need to instantiate the receiver, possibly
10617 // starting its application process to host it.
10618
10619 ResolveInfo info =
10620 (ResolveInfo)nextReceiver;
10621
10622 boolean skip = false;
10623 int perm = checkComponentPermission(info.activityInfo.permission,
10624 r.callingPid, r.callingUid,
10625 info.activityInfo.exported
10626 ? -1 : info.activityInfo.applicationInfo.uid);
10627 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010628 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010629 + r.intent.toString()
10630 + " from " + r.callerPackage + " (pid=" + r.callingPid
10631 + ", uid=" + r.callingUid + ")"
10632 + " requires " + info.activityInfo.permission
10633 + " due to receiver " + info.activityInfo.packageName
10634 + "/" + info.activityInfo.name);
10635 skip = true;
10636 }
10637 if (r.callingUid != Process.SYSTEM_UID &&
10638 r.requiredPermission != null) {
10639 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010640 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010641 checkPermission(r.requiredPermission,
10642 info.activityInfo.applicationInfo.packageName);
10643 } catch (RemoteException e) {
10644 perm = PackageManager.PERMISSION_DENIED;
10645 }
10646 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010647 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648 + r.intent + " to "
10649 + info.activityInfo.applicationInfo.packageName
10650 + " requires " + r.requiredPermission
10651 + " due to sender " + r.callerPackage
10652 + " (uid " + r.callingUid + ")");
10653 skip = true;
10654 }
10655 }
10656 if (r.curApp != null && r.curApp.crashing) {
10657 // If the target process is crashing, just skip it.
10658 skip = true;
10659 }
10660
10661 if (skip) {
10662 r.receiver = null;
10663 r.curFilter = null;
10664 r.state = BroadcastRecord.IDLE;
10665 scheduleBroadcastsLocked();
10666 return;
10667 }
10668
10669 r.state = BroadcastRecord.APP_RECEIVE;
10670 String targetProcess = info.activityInfo.processName;
10671 r.curComponent = new ComponentName(
10672 info.activityInfo.applicationInfo.packageName,
10673 info.activityInfo.name);
10674 r.curReceiver = info.activityInfo;
10675
10676 // Is this receiver's application already running?
10677 ProcessRecord app = getProcessRecordLocked(targetProcess,
10678 info.activityInfo.applicationInfo.uid);
10679 if (app != null && app.thread != null) {
10680 try {
10681 processCurBroadcastLocked(r, app);
10682 return;
10683 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010684 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010685 + r.curComponent, e);
10686 }
10687
10688 // If a dead object exception was thrown -- fall through to
10689 // restart the application.
10690 }
10691
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010692 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010693 if ((r.curApp=startProcessLocked(targetProcess,
10694 info.activityInfo.applicationInfo, true,
10695 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010696 "broadcast", r.curComponent,
10697 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10698 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010699 // Ah, this recipient is unavailable. Finish it if necessary,
10700 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010701 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 + info.activityInfo.applicationInfo.packageName + "/"
10703 + info.activityInfo.applicationInfo.uid + " for broadcast "
10704 + r.intent + ": process is bad");
10705 logBroadcastReceiverDiscard(r);
10706 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10707 r.resultExtras, r.resultAbort, true);
10708 scheduleBroadcastsLocked();
10709 r.state = BroadcastRecord.IDLE;
10710 return;
10711 }
10712
10713 mPendingBroadcast = r;
10714 }
10715 }
10716
10717 // =========================================================
10718 // INSTRUMENTATION
10719 // =========================================================
10720
10721 public boolean startInstrumentation(ComponentName className,
10722 String profileFile, int flags, Bundle arguments,
10723 IInstrumentationWatcher watcher) {
10724 // Refuse possible leaked file descriptors
10725 if (arguments != null && arguments.hasFileDescriptors()) {
10726 throw new IllegalArgumentException("File descriptors passed in Bundle");
10727 }
10728
10729 synchronized(this) {
10730 InstrumentationInfo ii = null;
10731 ApplicationInfo ai = null;
10732 try {
10733 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010734 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010736 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010737 } catch (PackageManager.NameNotFoundException e) {
10738 }
10739 if (ii == null) {
10740 reportStartInstrumentationFailure(watcher, className,
10741 "Unable to find instrumentation info for: " + className);
10742 return false;
10743 }
10744 if (ai == null) {
10745 reportStartInstrumentationFailure(watcher, className,
10746 "Unable to find instrumentation target package: " + ii.targetPackage);
10747 return false;
10748 }
10749
10750 int match = mContext.getPackageManager().checkSignatures(
10751 ii.targetPackage, ii.packageName);
10752 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10753 String msg = "Permission Denial: starting instrumentation "
10754 + className + " from pid="
10755 + Binder.getCallingPid()
10756 + ", uid=" + Binder.getCallingPid()
10757 + " not allowed because package " + ii.packageName
10758 + " does not have a signature matching the target "
10759 + ii.targetPackage;
10760 reportStartInstrumentationFailure(watcher, className, msg);
10761 throw new SecurityException(msg);
10762 }
10763
10764 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010765 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010766 ProcessRecord app = addAppLocked(ai);
10767 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010768 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 app.instrumentationProfileFile = profileFile;
10770 app.instrumentationArguments = arguments;
10771 app.instrumentationWatcher = watcher;
10772 app.instrumentationResultClass = className;
10773 Binder.restoreCallingIdentity(origId);
10774 }
10775
10776 return true;
10777 }
10778
10779 /**
10780 * Report errors that occur while attempting to start Instrumentation. Always writes the
10781 * error to the logs, but if somebody is watching, send the report there too. This enables
10782 * the "am" command to report errors with more information.
10783 *
10784 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10785 * @param cn The component name of the instrumentation.
10786 * @param report The error report.
10787 */
10788 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10789 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010790 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010791 try {
10792 if (watcher != null) {
10793 Bundle results = new Bundle();
10794 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10795 results.putString("Error", report);
10796 watcher.instrumentationStatus(cn, -1, results);
10797 }
10798 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010799 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010800 }
10801 }
10802
10803 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10804 if (app.instrumentationWatcher != null) {
10805 try {
10806 // NOTE: IInstrumentationWatcher *must* be oneway here
10807 app.instrumentationWatcher.instrumentationFinished(
10808 app.instrumentationClass,
10809 resultCode,
10810 results);
10811 } catch (RemoteException e) {
10812 }
10813 }
10814 app.instrumentationWatcher = null;
10815 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010816 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 app.instrumentationProfileFile = null;
10818 app.instrumentationArguments = null;
10819
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010820 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010821 }
10822
10823 public void finishInstrumentation(IApplicationThread target,
10824 int resultCode, Bundle results) {
10825 // Refuse possible leaked file descriptors
10826 if (results != null && results.hasFileDescriptors()) {
10827 throw new IllegalArgumentException("File descriptors passed in Intent");
10828 }
10829
10830 synchronized(this) {
10831 ProcessRecord app = getRecordForAppLocked(target);
10832 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010833 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010834 return;
10835 }
10836 final long origId = Binder.clearCallingIdentity();
10837 finishInstrumentationLocked(app, resultCode, results);
10838 Binder.restoreCallingIdentity(origId);
10839 }
10840 }
10841
10842 // =========================================================
10843 // CONFIGURATION
10844 // =========================================================
10845
10846 public ConfigurationInfo getDeviceConfigurationInfo() {
10847 ConfigurationInfo config = new ConfigurationInfo();
10848 synchronized (this) {
10849 config.reqTouchScreen = mConfiguration.touchscreen;
10850 config.reqKeyboardType = mConfiguration.keyboard;
10851 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010852 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10853 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010854 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10855 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010856 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10857 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010858 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10859 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010860 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010861 }
10862 return config;
10863 }
10864
10865 public Configuration getConfiguration() {
10866 Configuration ci;
10867 synchronized(this) {
10868 ci = new Configuration(mConfiguration);
10869 }
10870 return ci;
10871 }
10872
10873 public void updateConfiguration(Configuration values) {
10874 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10875 "updateConfiguration()");
10876
10877 synchronized(this) {
10878 if (values == null && mWindowManager != null) {
10879 // sentinel: fetch the current configuration from the window manager
10880 values = mWindowManager.computeNewConfiguration();
10881 }
10882
10883 final long origId = Binder.clearCallingIdentity();
10884 updateConfigurationLocked(values, null);
10885 Binder.restoreCallingIdentity(origId);
10886 }
10887 }
10888
10889 /**
10890 * Do either or both things: (1) change the current configuration, and (2)
10891 * make sure the given activity is running with the (now) current
10892 * configuration. Returns true if the activity has been left running, or
10893 * false if <var>starting</var> is being destroyed to match the new
10894 * configuration.
10895 */
10896 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010897 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 int changes = 0;
10899
10900 boolean kept = true;
10901
10902 if (values != null) {
10903 Configuration newConfig = new Configuration(mConfiguration);
10904 changes = newConfig.updateFrom(values);
10905 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010906 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010907 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 }
10909
Doug Zongker2bec3d42009-12-04 12:52:44 -080010910 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010911
10912 if (values.locale != null) {
10913 saveLocaleLocked(values.locale,
10914 !values.locale.equals(mConfiguration.locale),
10915 values.userSetLocale);
10916 }
10917
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010918 mConfigurationSeq++;
10919 if (mConfigurationSeq <= 0) {
10920 mConfigurationSeq = 1;
10921 }
10922 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010924 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010925
10926 AttributeCache ac = AttributeCache.instance();
10927 if (ac != null) {
10928 ac.updateConfiguration(mConfiguration);
10929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010930
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010931 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10932 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10933 msg.obj = new Configuration(mConfiguration);
10934 mHandler.sendMessage(msg);
10935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010937 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10938 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010939 try {
10940 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010941 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010942 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010943 app.thread.scheduleConfigurationChanged(mConfiguration);
10944 }
10945 } catch (Exception e) {
10946 }
10947 }
10948 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010949 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10950 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10952 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010953 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10954 broadcastIntentLocked(null, null,
10955 new Intent(Intent.ACTION_LOCALE_CHANGED),
10956 null, null, 0, null, null,
10957 null, false, false, MY_PID, Process.SYSTEM_UID);
10958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959 }
10960 }
10961
10962 if (changes != 0 && starting == null) {
10963 // If the configuration changed, and the caller is not already
10964 // in the process of starting an activity, then find the top
10965 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010966 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010967 }
10968
10969 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010970 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010971 if (kept) {
10972 // If this didn't result in the starting activity being
10973 // destroyed, then we need to make sure at this point that all
10974 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010975 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010977 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 }
10979 }
10980
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010981 if (values != null && mWindowManager != null) {
10982 mWindowManager.setNewConfiguration(mConfiguration);
10983 }
10984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 return kept;
10986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987
10988 /**
10989 * Save the locale. You must be inside a synchronized (this) block.
10990 */
10991 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10992 if(isDiff) {
10993 SystemProperties.set("user.language", l.getLanguage());
10994 SystemProperties.set("user.region", l.getCountry());
10995 }
10996
10997 if(isPersist) {
10998 SystemProperties.set("persist.sys.language", l.getLanguage());
10999 SystemProperties.set("persist.sys.country", l.getCountry());
11000 SystemProperties.set("persist.sys.localevar", l.getVariant());
11001 }
11002 }
11003
11004 // =========================================================
11005 // LIFETIME MANAGEMENT
11006 // =========================================================
11007
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011008 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11009 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011010 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011011 // This adjustment has already been computed. If we are calling
11012 // from the top, we may have already computed our adjustment with
11013 // an earlier hidden adjustment that isn't really for us... if
11014 // so, use the new hidden adjustment.
11015 if (!recursed && app.hidden) {
11016 app.curAdj = hiddenAdj;
11017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 return app.curAdj;
11019 }
11020
11021 if (app.thread == null) {
11022 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011023 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011024 return (app.curAdj=EMPTY_APP_ADJ);
11025 }
11026
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011027 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11028 // The max adjustment doesn't allow this app to be anything
11029 // below foreground, so it is not worth doing work for it.
11030 app.adjType = "fixed";
11031 app.adjSeq = mAdjSeq;
11032 app.curRawAdj = app.maxAdj;
11033 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11034 return (app.curAdj=app.maxAdj);
11035 }
11036
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011037 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011038 app.adjSource = null;
11039 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011040 app.empty = false;
11041 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042
The Android Open Source Project4df24232009-03-05 14:34:35 -080011043 // Determine the importance of the process, starting with most
11044 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011045 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011046 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011048 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 // The last app on the list is the foreground app.
11050 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011051 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011052 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011053 } else if (app.instrumentationClass != null) {
11054 // Don't want to kill running instrumentation.
11055 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011056 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011057 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011058 } else if (app.persistentActivities > 0) {
11059 // Special persistent activities... shouldn't be used these days.
11060 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011061 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011062 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063 } else if (app.curReceiver != null ||
11064 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11065 // An app that is currently receiving a broadcast also
11066 // counts as being in the foreground.
11067 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011068 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011069 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 } else if (app.executingServices.size() > 0) {
11071 // An app that is currently executing a service callback also
11072 // counts as being in the foreground.
11073 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011074 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011075 app.adjType = "exec-service";
11076 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011078 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011079 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011080 app.adjType = "foreground-service";
11081 } else if (app.forcingToForeground != null) {
11082 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011083 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011084 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011085 app.adjType = "force-foreground";
11086 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011087 } else if (app == mHeavyWeightProcess) {
11088 // We don't want to kill the current heavy-weight process.
11089 adj = HEAVY_WEIGHT_APP_ADJ;
11090 schedGroup = Process.THREAD_GROUP_DEFAULT;
11091 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011092 } else if (app == mHomeProcess) {
11093 // This process is hosting what we currently consider to be the
11094 // home app, so we don't want to let it go into the background.
11095 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011096 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011097 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011098 } else if ((N=app.activities.size()) != 0) {
11099 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011100 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011101 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011102 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011103 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011104 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011105 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011106 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011107 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011108 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011110 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011111 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011112 break;
11113 }
11114 }
11115 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011116 // A very not-needed process. If this is lower in the lru list,
11117 // we will push it in to the empty bucket.
11118 app.hidden = true;
11119 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011120 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011121 adj = hiddenAdj;
11122 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011123 }
11124
Joe Onorato8a9b2202010-02-26 18:56:32 -080011125 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011126
The Android Open Source Project4df24232009-03-05 14:34:35 -080011127 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 // there are applications dependent on our services or providers, but
11129 // this gives us a baseline and makes sure we don't get into an
11130 // infinite recursion.
11131 app.adjSeq = mAdjSeq;
11132 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011133
Christopher Tate6fa95972009-06-05 18:43:55 -070011134 if (mBackupTarget != null && app == mBackupTarget.app) {
11135 // If possible we want to avoid killing apps while they're being backed up
11136 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011137 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011138 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011139 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011140 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011141 }
11142 }
11143
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011144 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11145 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011146 final long now = SystemClock.uptimeMillis();
11147 // This process is more important if the top activity is
11148 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011149 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011151 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 if (s.startRequested) {
11153 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11154 // This service has seen some activity within
11155 // recent memory, so we will keep its process ahead
11156 // of the background processes.
11157 if (adj > SECONDARY_SERVER_ADJ) {
11158 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011159 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011160 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011161 }
11162 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011163 // If we have let the service slide into the background
11164 // state, still have some text describing what it is doing
11165 // even though the service no longer has an impact.
11166 if (adj > SECONDARY_SERVER_ADJ) {
11167 app.adjType = "started-bg-services";
11168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011170 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11171 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011172 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 = s.connections.values().iterator();
11174 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011175 ArrayList<ConnectionRecord> clist = kt.next();
11176 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11177 // XXX should compute this based on the max of
11178 // all connected clients.
11179 ConnectionRecord cr = clist.get(i);
11180 if (cr.binding.client == app) {
11181 // Binding to ourself is not interesting.
11182 continue;
11183 }
11184 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11185 ProcessRecord client = cr.binding.client;
11186 int myHiddenAdj = hiddenAdj;
11187 if (myHiddenAdj > client.hiddenAdj) {
11188 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11189 myHiddenAdj = client.hiddenAdj;
11190 } else {
11191 myHiddenAdj = VISIBLE_APP_ADJ;
11192 }
11193 }
11194 int clientAdj = computeOomAdjLocked(
11195 client, myHiddenAdj, TOP_APP, true);
11196 if (adj > clientAdj) {
11197 adj = clientAdj >= VISIBLE_APP_ADJ
11198 ? clientAdj : VISIBLE_APP_ADJ;
11199 if (!client.hidden) {
11200 app.hidden = false;
11201 }
11202 app.adjType = "service";
11203 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11204 .REASON_SERVICE_IN_USE;
11205 app.adjSource = cr.binding.client;
11206 app.adjTarget = s.name;
11207 }
11208 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11209 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11210 schedGroup = Process.THREAD_GROUP_DEFAULT;
11211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 }
11213 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011214 ActivityRecord a = cr.activity;
11215 //if (a != null) {
11216 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11217 //}
11218 if (a != null && adj > FOREGROUND_APP_ADJ &&
11219 (a.state == ActivityState.RESUMED
11220 || a.state == ActivityState.PAUSING)) {
11221 adj = FOREGROUND_APP_ADJ;
11222 schedGroup = Process.THREAD_GROUP_DEFAULT;
11223 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011224 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011225 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11226 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011227 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011228 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 }
11231 }
11232 }
11233 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011234
11235 // Finally, f this process has active services running in it, we
11236 // would like to avoid killing it unless it would prevent the current
11237 // application from running. By default we put the process in
11238 // with the rest of the background processes; as we scan through
11239 // its services we may bump it up from there.
11240 if (adj > hiddenAdj) {
11241 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011242 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011243 app.adjType = "bg-services";
11244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245 }
11246
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011247 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11248 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011249 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011250 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11251 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011252 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011253 if (cpr.clients.size() != 0) {
11254 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11255 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11256 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011257 if (client == app) {
11258 // Being our own client is not interesting.
11259 continue;
11260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011261 int myHiddenAdj = hiddenAdj;
11262 if (myHiddenAdj > client.hiddenAdj) {
11263 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11264 myHiddenAdj = client.hiddenAdj;
11265 } else {
11266 myHiddenAdj = FOREGROUND_APP_ADJ;
11267 }
11268 }
11269 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011270 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011271 if (adj > clientAdj) {
11272 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011273 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011274 if (!client.hidden) {
11275 app.hidden = false;
11276 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011277 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011278 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11279 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011280 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011281 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011283 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11284 schedGroup = Process.THREAD_GROUP_DEFAULT;
11285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011286 }
11287 }
11288 // If the provider has external (non-framework) process
11289 // dependencies, ensure that its adjustment is at least
11290 // FOREGROUND_APP_ADJ.
11291 if (cpr.externals != 0) {
11292 if (adj > FOREGROUND_APP_ADJ) {
11293 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011294 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011295 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011296 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011297 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298 }
11299 }
11300 }
11301 }
11302
11303 app.curRawAdj = adj;
11304
Joe Onorato8a9b2202010-02-26 18:56:32 -080011305 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011306 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11307 if (adj > app.maxAdj) {
11308 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011309 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011310 schedGroup = Process.THREAD_GROUP_DEFAULT;
11311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 }
11313
11314 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011315 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011317 return adj;
11318 }
11319
11320 /**
11321 * Ask a given process to GC right now.
11322 */
11323 final void performAppGcLocked(ProcessRecord app) {
11324 try {
11325 app.lastRequestedGc = SystemClock.uptimeMillis();
11326 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011327 if (app.reportLowMemory) {
11328 app.reportLowMemory = false;
11329 app.thread.scheduleLowMemory();
11330 } else {
11331 app.thread.processInBackground();
11332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011333 }
11334 } catch (Exception e) {
11335 // whatever.
11336 }
11337 }
11338
11339 /**
11340 * Returns true if things are idle enough to perform GCs.
11341 */
Josh Bartel7f208742010-02-25 11:01:44 -060011342 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011343 return mParallelBroadcasts.size() == 0
11344 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011345 && (mSleeping || (mMainStack.mResumedActivity != null &&
11346 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 }
11348
11349 /**
11350 * Perform GCs on all processes that are waiting for it, but only
11351 * if things are idle.
11352 */
11353 final void performAppGcsLocked() {
11354 final int N = mProcessesToGc.size();
11355 if (N <= 0) {
11356 return;
11357 }
Josh Bartel7f208742010-02-25 11:01:44 -060011358 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011359 while (mProcessesToGc.size() > 0) {
11360 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011361 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011362 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11363 <= SystemClock.uptimeMillis()) {
11364 // To avoid spamming the system, we will GC processes one
11365 // at a time, waiting a few seconds between each.
11366 performAppGcLocked(proc);
11367 scheduleAppGcsLocked();
11368 return;
11369 } else {
11370 // It hasn't been long enough since we last GCed this
11371 // process... put it in the list to wait for its time.
11372 addProcessToGcListLocked(proc);
11373 break;
11374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011375 }
11376 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011377
11378 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011379 }
11380 }
11381
11382 /**
11383 * If all looks good, perform GCs on all processes waiting for them.
11384 */
11385 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011386 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 performAppGcsLocked();
11388 return;
11389 }
11390 // Still not idle, wait some more.
11391 scheduleAppGcsLocked();
11392 }
11393
11394 /**
11395 * Schedule the execution of all pending app GCs.
11396 */
11397 final void scheduleAppGcsLocked() {
11398 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011399
11400 if (mProcessesToGc.size() > 0) {
11401 // Schedule a GC for the time to the next process.
11402 ProcessRecord proc = mProcessesToGc.get(0);
11403 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11404
11405 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11406 long now = SystemClock.uptimeMillis();
11407 if (when < (now+GC_TIMEOUT)) {
11408 when = now + GC_TIMEOUT;
11409 }
11410 mHandler.sendMessageAtTime(msg, when);
11411 }
11412 }
11413
11414 /**
11415 * Add a process to the array of processes waiting to be GCed. Keeps the
11416 * list in sorted order by the last GC time. The process can't already be
11417 * on the list.
11418 */
11419 final void addProcessToGcListLocked(ProcessRecord proc) {
11420 boolean added = false;
11421 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11422 if (mProcessesToGc.get(i).lastRequestedGc <
11423 proc.lastRequestedGc) {
11424 added = true;
11425 mProcessesToGc.add(i+1, proc);
11426 break;
11427 }
11428 }
11429 if (!added) {
11430 mProcessesToGc.add(0, proc);
11431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 }
11433
11434 /**
11435 * Set up to ask a process to GC itself. This will either do it
11436 * immediately, or put it on the list of processes to gc the next
11437 * time things are idle.
11438 */
11439 final void scheduleAppGcLocked(ProcessRecord app) {
11440 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011441 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 return;
11443 }
11444 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011445 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 scheduleAppGcsLocked();
11447 }
11448 }
11449
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011450 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11451 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11452 if (mLastWakeLockCheckTime == 0) {
11453 doKills = false;
11454 }
11455 if (stats.isScreenOn()) {
11456 doKills = false;
11457 }
11458 final long curRealtime = SystemClock.elapsedRealtime();
11459 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11460 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011461 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011462 doKills = false;
11463 }
11464 int i = mLruProcesses.size();
11465 while (i > 0) {
11466 i--;
11467 ProcessRecord app = mLruProcesses.get(i);
11468 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11469 long wtime;
11470 synchronized (stats) {
11471 wtime = stats.getProcessWakeTime(app.info.uid,
11472 app.pid, curRealtime);
11473 }
11474 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011475 if (false) {
11476 StringBuilder sb = new StringBuilder(128);
11477 sb.append("Wake for ");
11478 app.toShortString(sb);
11479 sb.append(": over ");
11480 TimeUtils.formatDuration(timeSince, sb);
11481 sb.append(" used ");
11482 TimeUtils.formatDuration(timeUsed, sb);
11483 sb.append(" (");
11484 sb.append((timeUsed*100)/timeSince);
11485 sb.append("%)");
11486 Slog.i(TAG, sb.toString());
11487 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011488 // If a process has held a wake lock for more
11489 // than 50% of the time during this period,
11490 // that sounds pad. Kill!
11491 if (doKills && timeSince > 0
11492 && ((timeUsed*100)/timeSince) >= 50) {
11493 Slog.i(TAG, "Excessive wake lock in " + app.processName
11494 + " (pid " + app.pid + "): held " + timeUsed
11495 + " during " + timeSince);
11496 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11497 app.processName, app.setAdj, "excessive wake lock");
11498 Process.killProcessQuiet(app.pid);
11499 } else {
11500 app.lastWakeTime = wtime;
11501 }
11502 }
11503 }
11504 }
11505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506 private final boolean updateOomAdjLocked(
11507 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11508 app.hiddenAdj = hiddenAdj;
11509
11510 if (app.thread == null) {
11511 return true;
11512 }
11513
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011514 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011515
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011516 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011517 if (app.curRawAdj != app.setRawAdj) {
11518 if (app.curRawAdj > FOREGROUND_APP_ADJ
11519 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11520 // If this app is transitioning from foreground to
11521 // non-foreground, have it do a gc.
11522 scheduleAppGcLocked(app);
11523 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11524 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11525 // Likewise do a gc when an app is moving in to the
11526 // background (such as a service stopping).
11527 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011528 // And note its current wake lock time.
11529 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11530 synchronized (stats) {
11531 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11532 app.pid, SystemClock.elapsedRealtime());
11533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 }
11535 app.setRawAdj = app.curRawAdj;
11536 }
11537 if (adj != app.setAdj) {
11538 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011539 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011540 TAG, "Set app " + app.processName +
11541 " oom adj to " + adj);
11542 app.setAdj = adj;
11543 } else {
11544 return false;
11545 }
11546 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011547 if (app.setSchedGroup != app.curSchedGroup) {
11548 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011549 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011550 "Setting process group of " + app.processName
11551 + " to " + app.curSchedGroup);
11552 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011553 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011554 try {
11555 Process.setProcessGroup(app.pid, app.curSchedGroup);
11556 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011557 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011558 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011559 e.printStackTrace();
11560 } finally {
11561 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011562 }
11563 }
11564 if (false) {
11565 if (app.thread != null) {
11566 try {
11567 app.thread.setSchedulingGroup(app.curSchedGroup);
11568 } catch (RemoteException e) {
11569 }
11570 }
11571 }
11572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011573 }
11574
11575 return true;
11576 }
11577
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011578 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011579 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011581 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011582 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011583 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011584 }
11585 }
11586 return resumedActivity;
11587 }
11588
11589 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011590 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011591 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11592 int curAdj = app.curAdj;
11593 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11594 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11595
11596 mAdjSeq++;
11597
11598 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11599 if (res) {
11600 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11601 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11602 if (nowHidden != wasHidden) {
11603 // Changed to/from hidden state, so apps after it in the LRU
11604 // list may also be changed.
11605 updateOomAdjLocked();
11606 }
11607 }
11608 return res;
11609 }
11610
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011611 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011613 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11615
11616 if (false) {
11617 RuntimeException e = new RuntimeException();
11618 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011619 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 }
11621
11622 mAdjSeq++;
11623
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011624 // Let's determine how many processes we have running vs.
11625 // how many slots we have for background processes; we may want
11626 // to put multiple processes in a slot of there are enough of
11627 // them.
11628 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11629 int factor = (mLruProcesses.size()-4)/numSlots;
11630 if (factor < 1) factor = 1;
11631 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011632 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011634 // First try updating the OOM adjustment for each of the
11635 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011636 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011637 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11638 while (i > 0) {
11639 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011640 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011641 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011643 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011645 step++;
11646 if (step >= factor) {
11647 step = 0;
11648 curHiddenAdj++;
11649 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011650 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011651 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011652 if (!app.killedBackground) {
11653 numHidden++;
11654 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011655 Slog.i(TAG, "No longer want " + app.processName
11656 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011657 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11658 app.processName, app.setAdj, "too many background");
11659 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011660 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011661 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011662 }
11663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011664 } else {
11665 didOomAdj = false;
11666 }
11667 }
11668
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011669 // If we return false, we will fall back on killing processes to
11670 // have a fixed limit. Do this if a limit has been requested; else
11671 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11673 }
11674
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011675 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676 synchronized (this) {
11677 int i;
11678
11679 // First remove any unused application processes whose package
11680 // has been removed.
11681 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11682 final ProcessRecord app = mRemovedProcesses.get(i);
11683 if (app.activities.size() == 0
11684 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011685 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011686 TAG, "Exiting empty application process "
11687 + app.processName + " ("
11688 + (app.thread != null ? app.thread.asBinder() : null)
11689 + ")\n");
11690 if (app.pid > 0 && app.pid != MY_PID) {
11691 Process.killProcess(app.pid);
11692 } else {
11693 try {
11694 app.thread.scheduleExit();
11695 } catch (Exception e) {
11696 // Ignore exceptions.
11697 }
11698 }
11699 cleanUpApplicationRecordLocked(app, false, -1);
11700 mRemovedProcesses.remove(i);
11701
11702 if (app.persistent) {
11703 if (app.persistent) {
11704 addAppLocked(app.info);
11705 }
11706 }
11707 }
11708 }
11709
11710 // Now try updating the OOM adjustment for each of the
11711 // application processes based on their current state.
11712 // If the setOomAdj() API is not supported, then go with our
11713 // back-up plan...
11714 if (!updateOomAdjLocked()) {
11715
11716 // Count how many processes are running services.
11717 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011718 for (i=mLruProcesses.size()-1; i>=0; i--) {
11719 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011720
11721 if (app.persistent || app.services.size() != 0
11722 || app.curReceiver != null
11723 || app.persistentActivities > 0) {
11724 // Don't count processes holding services against our
11725 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011726 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011727 TAG, "Not trimming app " + app + " with services: "
11728 + app.services);
11729 numServiceProcs++;
11730 }
11731 }
11732
11733 int curMaxProcs = mProcessLimit;
11734 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11735 if (mAlwaysFinishActivities) {
11736 curMaxProcs = 1;
11737 }
11738 curMaxProcs += numServiceProcs;
11739
11740 // Quit as many processes as we can to get down to the desired
11741 // process count. First remove any processes that no longer
11742 // have activites running in them.
11743 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011744 i<mLruProcesses.size()
11745 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011746 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011747 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011748 // Quit an application only if it is not currently
11749 // running any activities.
11750 if (!app.persistent && app.activities.size() == 0
11751 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011752 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011753 TAG, "Exiting empty application process "
11754 + app.processName + " ("
11755 + (app.thread != null ? app.thread.asBinder() : null)
11756 + ")\n");
11757 if (app.pid > 0 && app.pid != MY_PID) {
11758 Process.killProcess(app.pid);
11759 } else {
11760 try {
11761 app.thread.scheduleExit();
11762 } catch (Exception e) {
11763 // Ignore exceptions.
11764 }
11765 }
11766 // todo: For now we assume the application is not buggy
11767 // or evil, and will quit as a result of our request.
11768 // Eventually we need to drive this off of the death
11769 // notification, and kill the process if it takes too long.
11770 cleanUpApplicationRecordLocked(app, false, i);
11771 i--;
11772 }
11773 }
11774
11775 // If we still have too many processes, now from the least
11776 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011777 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011778 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 " of " + curMaxProcs + " processes");
11780 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011781 i<mLruProcesses.size()
11782 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011783 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011784 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 // Quit the application only if we have a state saved for
11786 // all of its activities.
11787 boolean canQuit = !app.persistent && app.curReceiver == null
11788 && app.services.size() == 0
11789 && app.persistentActivities == 0;
11790 int NUMA = app.activities.size();
11791 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011792 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011793 TAG, "Looking to quit " + app.processName);
11794 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011795 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011796 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 TAG, " " + r.intent.getComponent().flattenToShortString()
11798 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11799 canQuit = (r.haveState || !r.stateNotNeeded)
11800 && !r.visible && r.stopped;
11801 }
11802 if (canQuit) {
11803 // Finish all of the activities, and then the app itself.
11804 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011805 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011806 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011807 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 }
11809 r.resultTo = null;
11810 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011811 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011812 + app.processName + " ("
11813 + (app.thread != null ? app.thread.asBinder() : null)
11814 + ")\n");
11815 if (app.pid > 0 && app.pid != MY_PID) {
11816 Process.killProcess(app.pid);
11817 } else {
11818 try {
11819 app.thread.scheduleExit();
11820 } catch (Exception e) {
11821 // Ignore exceptions.
11822 }
11823 }
11824 // todo: For now we assume the application is not buggy
11825 // or evil, and will quit as a result of our request.
11826 // Eventually we need to drive this off of the death
11827 // notification, and kill the process if it takes too long.
11828 cleanUpApplicationRecordLocked(app, false, i);
11829 i--;
11830 //dump();
11831 }
11832 }
11833
11834 }
11835
11836 int curMaxActivities = MAX_ACTIVITIES;
11837 if (mAlwaysFinishActivities) {
11838 curMaxActivities = 1;
11839 }
11840
11841 // Finally, if there are too many activities now running, try to
11842 // finish as many as we can to get back down to the limit.
11843 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011844 i<mMainStack.mLRUActivities.size()
11845 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011847 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011848 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011849
11850 // We can finish this one if we have its icicle saved and
11851 // it is not persistent.
11852 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11853 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011854 final int origSize = mMainStack.mLRUActivities.size();
11855 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856
11857 // This will remove it from the LRU list, so keep
11858 // our index at the same value. Note that this check to
11859 // see if the size changes is just paranoia -- if
11860 // something unexpected happens, we don't want to end up
11861 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011862 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011863 i--;
11864 }
11865 }
11866 }
11867 }
11868 }
11869
11870 /** This method sends the specified signal to each of the persistent apps */
11871 public void signalPersistentProcesses(int sig) throws RemoteException {
11872 if (sig != Process.SIGNAL_USR1) {
11873 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11874 }
11875
11876 synchronized (this) {
11877 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11878 != PackageManager.PERMISSION_GRANTED) {
11879 throw new SecurityException("Requires permission "
11880 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11881 }
11882
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011883 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11884 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011885 if (r.thread != null && r.persistent) {
11886 Process.sendSignal(r.pid, sig);
11887 }
11888 }
11889 }
11890 }
11891
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011892 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011893 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011894
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011895 try {
11896 synchronized (this) {
11897 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11898 // its own permission.
11899 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11900 != PackageManager.PERMISSION_GRANTED) {
11901 throw new SecurityException("Requires permission "
11902 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011903 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011904
11905 if (start && fd == null) {
11906 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011907 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011908
11909 ProcessRecord proc = null;
11910 try {
11911 int pid = Integer.parseInt(process);
11912 synchronized (mPidsSelfLocked) {
11913 proc = mPidsSelfLocked.get(pid);
11914 }
11915 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011916 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011917
11918 if (proc == null) {
11919 HashMap<String, SparseArray<ProcessRecord>> all
11920 = mProcessNames.getMap();
11921 SparseArray<ProcessRecord> procs = all.get(process);
11922 if (procs != null && procs.size() > 0) {
11923 proc = procs.valueAt(0);
11924 }
11925 }
11926
11927 if (proc == null || proc.thread == null) {
11928 throw new IllegalArgumentException("Unknown process: " + process);
11929 }
11930
11931 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11932 if (isSecure) {
11933 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11934 throw new SecurityException("Process not debuggable: " + proc);
11935 }
11936 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011937
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011938 proc.thread.profilerControl(start, path, fd);
11939 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011940 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011941 }
11942 } catch (RemoteException e) {
11943 throw new IllegalStateException("Process disappeared");
11944 } finally {
11945 if (fd != null) {
11946 try {
11947 fd.close();
11948 } catch (IOException e) {
11949 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011950 }
11951 }
11952 }
11953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11955 public void monitor() {
11956 synchronized (this) { }
11957 }
11958}