blob: 4762ddb4af096022a8fbd257878d895cf02092e6 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
58import android.content.Intent;
59import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070060import android.content.IIntentReceiver;
61import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070062import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.content.pm.ActivityInfo;
64import android.content.pm.ApplicationInfo;
65import android.content.pm.ConfigurationInfo;
66import android.content.pm.IPackageDataObserver;
67import android.content.pm.IPackageManager;
68import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080069import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070071import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.ProviderInfo;
73import android.content.pm.ResolveInfo;
74import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070075import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.res.Configuration;
77import android.graphics.Bitmap;
78import android.net.Uri;
79import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080080import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070082import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.FileUtils;
87import android.os.Handler;
88import android.os.IBinder;
89import android.os.IPermissionController;
90import android.os.Looper;
91import android.os.Message;
92import android.os.Parcel;
93import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070095import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.RemoteException;
97import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070098import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.SystemClock;
100import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.Config;
103import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800104import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800105import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.util.PrintWriterPrinter;
107import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700108import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.view.Gravity;
110import android.view.LayoutInflater;
111import android.view.View;
112import android.view.WindowManager;
113import android.view.WindowManagerPolicy;
114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.File;
116import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200118import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800119import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.PrintWriter;
121import java.lang.IllegalStateException;
122import java.lang.ref.WeakReference;
123import java.util.ArrayList;
124import java.util.HashMap;
125import java.util.HashSet;
126import java.util.Iterator;
127import java.util.List;
128import java.util.Locale;
129import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700130import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700131import java.util.concurrent.atomic.AtomicBoolean;
132import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133
134public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
135 static final String TAG = "ActivityManager";
136 static final boolean DEBUG = false;
137 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
138 static final boolean DEBUG_SWITCH = localLOGV || false;
139 static final boolean DEBUG_TASKS = localLOGV || false;
140 static final boolean DEBUG_PAUSE = localLOGV || false;
141 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
142 static final boolean DEBUG_TRANSITION = localLOGV || false;
143 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700144 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean DEBUG_SERVICE = localLOGV || false;
146 static final boolean DEBUG_VISBILITY = localLOGV || false;
147 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700148 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800149 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700151 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700152 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700153 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean VALIDATE_TOKENS = false;
155 static final boolean SHOW_ACTIVITY_START_TIME = true;
156
157 // Control over CPU and battery monitoring.
158 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
159 static final boolean MONITOR_CPU_USAGE = true;
160 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
161 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
162 static final boolean MONITOR_THREAD_CPU_USAGE = false;
163
Dianne Hackborn1655be42009-05-08 14:29:01 -0700164 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700165 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 private static final String SYSTEM_SECURE = "ro.secure";
168
169 // This is the maximum number of application processes we would like
170 // to have running. Due to the asynchronous nature of things, we can
171 // temporarily go beyond this limit.
172 static final int MAX_PROCESSES = 2;
173
174 // Set to false to leave processes running indefinitely, relying on
175 // the kernel killing them as resources are required.
176 static final boolean ENFORCE_PROCESS_LIMIT = false;
177
178 // This is the maximum number of activities that we would like to have
179 // running at a given time.
180 static final int MAX_ACTIVITIES = 20;
181
182 // Maximum number of recent tasks that we can remember.
183 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700184
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700185 // Amount of time after a call to stopAppSwitches() during which we will
186 // prevent further untrusted switches from happening.
187 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188
189 // How long we wait for a launched process to attach to the activity manager
190 // before we decide it's never going to come up for real.
191 static final int PROC_START_TIMEOUT = 10*1000;
192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 // How long to wait after going idle before forcing apps to GC.
194 static final int GC_TIMEOUT = 5*1000;
195
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700196 // The minimum amount of time between successive GC requests for a process.
197 static final int GC_MIN_INTERVAL = 60*1000;
198
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700199 // The rate at which we check for apps using excessive wake locks -- 15 mins.
200 static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 // How long we allow a receiver to run before giving up on it.
203 static final int BROADCAST_TIMEOUT = 10*1000;
204
205 // How long we wait for a service to finish executing.
206 static final int SERVICE_TIMEOUT = 20*1000;
207
208 // How long a service needs to be running until restarting its process
209 // is no longer considered to be a relaunch of the service.
210 static final int SERVICE_RESTART_DURATION = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // How long a service needs to be running until it will start back at
213 // SERVICE_RESTART_DURATION after being killed.
214 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
215
216 // Multiplying factor to increase restart duration time by, for each time
217 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
218 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
219
220 // The minimum amount of time between restarting services that we allow.
221 // That is, when multiple services are restarting, we won't allow each
222 // to restart less than this amount of time from the last one.
223 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // Maximum amount of time for there to be no activity on a service before
226 // we consider it non-essential and allow its process to go on the
227 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700228 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
230 // How long we wait until we timeout on key dispatching.
231 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
232
233 // The minimum time we allow between crashes, for us to consider this
234 // application to be bad and stop and its services and reject broadcasts.
235 static final int MIN_CRASH_INTERVAL = 60*1000;
236
237 // How long we wait until we timeout on key dispatching during instrumentation.
238 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
239
240 // OOM adjustments for processes in various states:
241
242 // This is a process without anything currently running in it. Definitely
243 // the first to go! Value set in system/rootdir/init.rc on startup.
244 // This value is initalized in the constructor, careful when refering to
245 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800246 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // This is a process only hosting activities that are not visible,
249 // so it can be killed without any disruption. Value set in
250 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800251 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 static int HIDDEN_APP_MIN_ADJ;
253
The Android Open Source Project4df24232009-03-05 14:34:35 -0800254 // This is a process holding the home application -- we want to try
255 // avoiding killing it, even if it would normally be in the background,
256 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800257 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800258
Christopher Tate6fa95972009-06-05 18:43:55 -0700259 // This is a process currently hosting a backup operation. Killing it
260 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800261 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 // This is a process holding a secondary server -- killing it will not
264 // have much of an impact as far as the user is concerned. Value set in
265 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800266 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700268 // This is a process with a heavy-weight application. It is in the
269 // background, but we want to try to avoid killing it. Value set in
270 // system/rootdir/init.rc on startup.
271 static final int HEAVY_WEIGHT_APP_ADJ;
272
273 // This is a process only hosting components that are perceptible to the
274 // user, and we really want to avoid killing them, but they are not
275 // immediately visible. An example is background music playback. Value set in
276 // system/rootdir/init.rc on startup.
277 static final int PERCEPTIBLE_APP_ADJ;
278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 // This is a process only hosting activities that are visible to the
280 // user, so we'd prefer they don't disappear. Value set in
281 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283
284 // This is the process running the current foreground app. We'd really
285 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
288 // This is a process running a core server, such as telephony. Definitely
289 // don't want to kill it, but doing so is not completely fatal.
290 static final int CORE_SERVER_ADJ = -12;
291
292 // The system process runs at the default adjustment.
293 static final int SYSTEM_ADJ = -16;
294
295 // Memory pages are 4K.
296 static final int PAGE_SIZE = 4*1024;
297
298 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800299 static final int EMPTY_APP_MEM;
300 static final int HIDDEN_APP_MEM;
301 static final int HOME_APP_MEM;
302 static final int BACKUP_APP_MEM;
303 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700304 static final int HEAVY_WEIGHT_APP_MEM;
305 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int VISIBLE_APP_MEM;
307 static final int FOREGROUND_APP_MEM;
308
309 // The minimum number of hidden apps we want to be able to keep around,
310 // without empty apps being able to push them out of memory.
311 static final int MIN_HIDDEN_APPS = 2;
312
Dianne Hackborn8633e682010-04-22 16:03:41 -0700313 // The maximum number of hidden processes we will keep around before
314 // killing them; this is just a control to not let us go too crazy with
315 // keeping around processes on devices with large amounts of RAM.
316 static final int MAX_HIDDEN_APPS = 15;
317
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800318 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700319 // been idle for less than 15 seconds.
320 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800321
322 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700323 // been idle for less than 120 seconds.
324 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800325
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700326 static int getIntProp(String name, boolean allowZero) {
327 String str = SystemProperties.get(name);
328 if (str == null) {
329 throw new IllegalArgumentException("Property not defined: " + name);
330 }
331 int val = Integer.valueOf(str);
332 if (val == 0 && !allowZero) {
333 throw new IllegalArgumentException("Property must not be zero: " + name);
334 }
335 return val;
336 }
337
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800338 static {
339 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700340 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
341 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
342 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
343 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
344 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
345 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
346 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
347 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
348 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
349 // These days we use the last empty slot for hidden apps as well.
350 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
351 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
352 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
353 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
354 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
355 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
356 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
357 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
358 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
359 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
Dan Egnor42471dd2010-01-07 17:25:22 -0800362 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
364 static final String[] EMPTY_STRING_ARRAY = new String[0];
365
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700366 public ActivityStack mMainStack;
367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700369 * Description of a request to start a new activity, which has been held
370 * due to app switches being disabled.
371 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700372 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700373 ActivityRecord r;
374 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700375 Uri[] grantedUriPermissions;
376 int grantedMode;
377 boolean onlyIfNeeded;
378 }
379
380 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
381 = new ArrayList<PendingActivityLaunch>();
382
383 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 * List of all active broadcasts that are to be executed immediately
385 * (without waiting for another broadcast to finish). Currently this only
386 * contains broadcasts to registered receivers, to avoid spinning up
387 * a bunch of processes to execute IntentReceiver components.
388 */
389 final ArrayList<BroadcastRecord> mParallelBroadcasts
390 = new ArrayList<BroadcastRecord>();
391
392 /**
393 * List of all active broadcasts that are to be executed one at a time.
394 * The object at the top of the list is the currently activity broadcasts;
395 * those after it are waiting for the top to finish..
396 */
397 final ArrayList<BroadcastRecord> mOrderedBroadcasts
398 = new ArrayList<BroadcastRecord>();
399
400 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800401 * Historical data of past broadcasts, for debugging.
402 */
403 static final int MAX_BROADCAST_HISTORY = 100;
404 final BroadcastRecord[] mBroadcastHistory
405 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * Set when we current have a BROADCAST_INTENT_MSG in flight.
409 */
410 boolean mBroadcastsScheduled = false;
411
412 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 * Activity we have told the window manager to have key focus.
414 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700415 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700416 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 * List of intents that were used to start the most recent tasks.
418 */
419 final ArrayList<TaskRecord> mRecentTasks
420 = new ArrayList<TaskRecord>();
421
422 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 * All of the applications we currently have running organized by name.
424 * The keys are strings of the application package name (as
425 * returned by the package manager), and the keys are ApplicationRecord
426 * objects.
427 */
428 final ProcessMap<ProcessRecord> mProcessNames
429 = new ProcessMap<ProcessRecord>();
430
431 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700432 * The currently running heavy-weight process, if any.
433 */
434 ProcessRecord mHeavyWeightProcess = null;
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * The last time that various processes have crashed.
438 */
439 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
440
441 /**
442 * Set of applications that we consider to be bad, and will reject
443 * incoming broadcasts from (which the user has no control over).
444 * Processes are added to this set when they have crashed twice within
445 * a minimum amount of time; they are removed from it when they are
446 * later restarted (hopefully due to some user action). The value is the
447 * time it was added to the list.
448 */
449 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
450
451 /**
452 * All of the processes we currently have running organized by pid.
453 * The keys are the pid running the application.
454 *
455 * <p>NOTE: This object is protected by its own lock, NOT the global
456 * activity manager lock!
457 */
458 final SparseArray<ProcessRecord> mPidsSelfLocked
459 = new SparseArray<ProcessRecord>();
460
461 /**
462 * All of the processes that have been forced to be foreground. The key
463 * is the pid of the caller who requested it (we hold a death
464 * link on it).
465 */
466 abstract class ForegroundToken implements IBinder.DeathRecipient {
467 int pid;
468 IBinder token;
469 }
470 final SparseArray<ForegroundToken> mForegroundProcesses
471 = new SparseArray<ForegroundToken>();
472
473 /**
474 * List of records for processes that someone had tried to start before the
475 * system was ready. We don't start them at that point, but ensure they
476 * are started by the time booting is complete.
477 */
478 final ArrayList<ProcessRecord> mProcessesOnHold
479 = new ArrayList<ProcessRecord>();
480
481 /**
482 * List of records for processes that we have started and are waiting
483 * for them to call back. This is really only needed when running in
484 * single processes mode, in which case we do not have a unique pid for
485 * each process.
486 */
487 final ArrayList<ProcessRecord> mStartingProcesses
488 = new ArrayList<ProcessRecord>();
489
490 /**
491 * List of persistent applications that are in the process
492 * of being started.
493 */
494 final ArrayList<ProcessRecord> mPersistentStartingProcesses
495 = new ArrayList<ProcessRecord>();
496
497 /**
498 * Processes that are being forcibly torn down.
499 */
500 final ArrayList<ProcessRecord> mRemovedProcesses
501 = new ArrayList<ProcessRecord>();
502
503 /**
504 * List of running applications, sorted by recent usage.
505 * The first entry in the list is the least recently used.
506 * It contains ApplicationRecord objects. This list does NOT include
507 * any persistent application records (since we never want to exit them).
508 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800509 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 = new ArrayList<ProcessRecord>();
511
512 /**
513 * List of processes that should gc as soon as things are idle.
514 */
515 final ArrayList<ProcessRecord> mProcessesToGc
516 = new ArrayList<ProcessRecord>();
517
518 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800519 * This is the process holding what we currently consider to be
520 * the "home" activity.
521 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700522 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800523
524 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 * Set of PendingResultRecord objects that are currently active.
526 */
527 final HashSet mPendingResultRecords = new HashSet();
528
529 /**
530 * Set of IntentSenderRecord objects that are currently active.
531 */
532 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
533 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
534
535 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700536 * Fingerprints (String.hashCode()) of stack traces that we've
537 * already logged DropBox entries for. Guarded by itself. If
538 * something (rogue user app) forces this over
539 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
540 */
541 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
542 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
543
544 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700545 * Strict Mode background batched logging state.
546 *
547 * The string buffer is guarded by itself, and its lock is also
548 * used to determine if another batched write is already
549 * in-flight.
550 */
551 private final StringBuilder mStrictModeBuffer = new StringBuilder();
552
553 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 * Intent broadcast that we have tried to start, but are
555 * waiting for its application's process to be created. We only
556 * need one (instead of a list) because we always process broadcasts
557 * one at a time, so no others can be started while waiting for this
558 * one.
559 */
560 BroadcastRecord mPendingBroadcast = null;
561
562 /**
563 * Keeps track of all IIntentReceivers that have been registered for
564 * broadcasts. Hash keys are the receiver IBinder, hash value is
565 * a ReceiverList.
566 */
567 final HashMap mRegisteredReceivers = new HashMap();
568
569 /**
570 * Resolver for broadcast intents to registered receivers.
571 * Holds BroadcastFilter (subclass of IntentFilter).
572 */
573 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
574 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
575 @Override
576 protected boolean allowFilterResult(
577 BroadcastFilter filter, List<BroadcastFilter> dest) {
578 IBinder target = filter.receiverList.receiver.asBinder();
579 for (int i=dest.size()-1; i>=0; i--) {
580 if (dest.get(i).receiverList.receiver.asBinder() == target) {
581 return false;
582 }
583 }
584 return true;
585 }
586 };
587
588 /**
589 * State of all active sticky broadcasts. Keys are the action of the
590 * sticky Intent, values are an ArrayList of all broadcasted intents with
591 * that action (which should usually be one).
592 */
593 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
594 new HashMap<String, ArrayList<Intent>>();
595
596 /**
597 * All currently running services.
598 */
599 final HashMap<ComponentName, ServiceRecord> mServices =
600 new HashMap<ComponentName, ServiceRecord>();
601
602 /**
603 * All currently running services indexed by the Intent used to start them.
604 */
605 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
606 new HashMap<Intent.FilterComparison, ServiceRecord>();
607
608 /**
609 * All currently bound service connections. Keys are the IBinder of
610 * the client's IServiceConnection.
611 */
612 final HashMap<IBinder, ConnectionRecord> mServiceConnections
613 = new HashMap<IBinder, ConnectionRecord>();
614
615 /**
616 * List of services that we have been asked to start,
617 * but haven't yet been able to. It is used to hold start requests
618 * while waiting for their corresponding application thread to get
619 * going.
620 */
621 final ArrayList<ServiceRecord> mPendingServices
622 = new ArrayList<ServiceRecord>();
623
624 /**
625 * List of services that are scheduled to restart following a crash.
626 */
627 final ArrayList<ServiceRecord> mRestartingServices
628 = new ArrayList<ServiceRecord>();
629
630 /**
631 * List of services that are in the process of being stopped.
632 */
633 final ArrayList<ServiceRecord> mStoppingServices
634 = new ArrayList<ServiceRecord>();
635
636 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700637 * Backup/restore process management
638 */
639 String mBackupAppName = null;
640 BackupRecord mBackupTarget = null;
641
642 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 * List of PendingThumbnailsRecord objects of clients who are still
644 * waiting to receive all of the thumbnails for a task.
645 */
646 final ArrayList mPendingThumbnails = new ArrayList();
647
648 /**
649 * List of HistoryRecord objects that have been finished and must
650 * still report back to a pending thumbnail receiver.
651 */
652 final ArrayList mCancelledThumbnails = new ArrayList();
653
654 /**
655 * All of the currently running global content providers. Keys are a
656 * string containing the provider name and values are a
657 * ContentProviderRecord object containing the data about it. Note
658 * that a single provider may be published under multiple names, so
659 * there may be multiple entries here for a single one in mProvidersByClass.
660 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700661 final HashMap<String, ContentProviderRecord> mProvidersByName
662 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663
664 /**
665 * All of the currently running global content providers. Keys are a
666 * string containing the provider's implementation class and values are a
667 * ContentProviderRecord object containing the data about it.
668 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700669 final HashMap<String, ContentProviderRecord> mProvidersByClass
670 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671
672 /**
673 * List of content providers who have clients waiting for them. The
674 * application is currently being launched and the provider will be
675 * removed from this list once it is published.
676 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700677 final ArrayList<ContentProviderRecord> mLaunchingProviders
678 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679
680 /**
681 * Global set of specific Uri permissions that have been granted.
682 */
683 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
684 = new SparseArray<HashMap<Uri, UriPermission>>();
685
686 /**
687 * Thread-local storage used to carry caller permissions over through
688 * indirect content-provider access.
689 * @see #ActivityManagerService.openContentUri()
690 */
691 private class Identity {
692 public int pid;
693 public int uid;
694
695 Identity(int _pid, int _uid) {
696 pid = _pid;
697 uid = _uid;
698 }
699 }
700 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
701
702 /**
703 * All information we have collected about the runtime performance of
704 * any user id that can impact battery performance.
705 */
706 final BatteryStatsService mBatteryStatsService;
707
708 /**
709 * information about component usage
710 */
711 final UsageStatsService mUsageStatsService;
712
713 /**
714 * Current configuration information. HistoryRecord objects are given
715 * a reference to this object to indicate which configuration they are
716 * currently running in, so this object must be kept immutable.
717 */
718 Configuration mConfiguration = new Configuration();
719
720 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800721 * Current sequencing integer of the configuration, for skipping old
722 * configurations.
723 */
724 int mConfigurationSeq = 0;
725
726 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700727 * Hardware-reported OpenGLES version.
728 */
729 final int GL_ES_VERSION;
730
731 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 * List of initialization arguments to pass to all processes when binding applications to them.
733 * For example, references to the commonly used services.
734 */
735 HashMap<String, IBinder> mAppBindArgs;
736
737 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700738 * Temporary to avoid allocations. Protected by main lock.
739 */
740 final StringBuilder mStringBuilder = new StringBuilder(256);
741
742 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 * Used to control how we initialize the service.
744 */
745 boolean mStartRunning = false;
746 ComponentName mTopComponent;
747 String mTopAction;
748 String mTopData;
749 boolean mSystemReady = false;
750 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700751 boolean mWaitingUpdate = false;
752 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753
754 Context mContext;
755
756 int mFactoryTest;
757
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700758 boolean mCheckedForSetup;
759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700761 * The time at which we will allow normal application switches again,
762 * after a call to {@link #stopAppSwitches()}.
763 */
764 long mAppSwitchesAllowedTime;
765
766 /**
767 * This is set to true after the first switch after mAppSwitchesAllowedTime
768 * is set; any switches after that will clear the time.
769 */
770 boolean mDidAppSwitch;
771
772 /**
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700773 * Last time (in realtime) at which we checked for wake lock usage.
774 */
775 long mLastWakeLockCheckTime;
776
777 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 * Set while we are wanting to sleep, to prevent any
779 * activities from being started/resumed.
780 */
781 boolean mSleeping = false;
782
783 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700784 * Set if we are shutting down the system, similar to sleeping.
785 */
786 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787
788 /**
789 * Task identifier that activities are currently being started
790 * in. Incremented each time a new task is created.
791 * todo: Replace this with a TokenSpace class that generates non-repeating
792 * integers that won't wrap.
793 */
794 int mCurTask = 1;
795
796 /**
797 * Current sequence id for oom_adj computation traversal.
798 */
799 int mAdjSeq = 0;
800
801 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700802 * Current sequence id for process LRU updating.
803 */
804 int mLruSeq = 0;
805
806 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
808 * is set, indicating the user wants processes started in such a way
809 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
810 * running in each process (thus no pre-initialized process, etc).
811 */
812 boolean mSimpleProcessManagement = false;
813
814 /**
815 * System monitoring: number of processes that died since the last
816 * N procs were started.
817 */
818 int[] mProcDeaths = new int[20];
819
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700820 /**
821 * This is set if we had to do a delayed dexopt of an app before launching
822 * it, to increasing the ANR timeouts in that case.
823 */
824 boolean mDidDexOpt;
825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 String mDebugApp = null;
827 boolean mWaitForDebugger = false;
828 boolean mDebugTransient = false;
829 String mOrigDebugApp = null;
830 boolean mOrigWaitForDebugger = false;
831 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700832 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700834 final RemoteCallbackList<IActivityWatcher> mWatchers
835 = new RemoteCallbackList<IActivityWatcher>();
836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 /**
838 * Callback of last caller to {@link #requestPss}.
839 */
840 Runnable mRequestPssCallback;
841
842 /**
843 * Remaining processes for which we are waiting results from the last
844 * call to {@link #requestPss}.
845 */
846 final ArrayList<ProcessRecord> mRequestPssList
847 = new ArrayList<ProcessRecord>();
848
849 /**
850 * Runtime statistics collection thread. This object's lock is used to
851 * protect all related state.
852 */
853 final Thread mProcessStatsThread;
854
855 /**
856 * Used to collect process stats when showing not responding dialog.
857 * Protected by mProcessStatsThread.
858 */
859 final ProcessStats mProcessStats = new ProcessStats(
860 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700861 final AtomicLong mLastCpuTime = new AtomicLong(0);
862 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 long mLastWriteTime = 0;
865
866 /**
867 * Set to true after the system has finished booting.
868 */
869 boolean mBooted = false;
870
871 int mProcessLimit = 0;
872
873 WindowManagerService mWindowManager;
874
875 static ActivityManagerService mSelf;
876 static ActivityThread mSystemThread;
877
878 private final class AppDeathRecipient implements IBinder.DeathRecipient {
879 final ProcessRecord mApp;
880 final int mPid;
881 final IApplicationThread mAppThread;
882
883 AppDeathRecipient(ProcessRecord app, int pid,
884 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800885 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 TAG, "New death recipient " + this
887 + " for thread " + thread.asBinder());
888 mApp = app;
889 mPid = pid;
890 mAppThread = thread;
891 }
892
893 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800894 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 TAG, "Death received in " + this
896 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 synchronized(ActivityManagerService.this) {
898 appDiedLocked(mApp, mPid, mAppThread);
899 }
900 }
901 }
902
903 static final int SHOW_ERROR_MSG = 1;
904 static final int SHOW_NOT_RESPONDING_MSG = 2;
905 static final int SHOW_FACTORY_ERROR_MSG = 3;
906 static final int UPDATE_CONFIGURATION_MSG = 4;
907 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
908 static final int WAIT_FOR_DEBUGGER_MSG = 6;
909 static final int BROADCAST_INTENT_MSG = 7;
910 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 static final int SERVICE_TIMEOUT_MSG = 12;
912 static final int UPDATE_TIME_ZONE = 13;
913 static final int SHOW_UID_ERROR_MSG = 14;
914 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700916 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700917 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800918 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700919 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
920 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700921 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700922 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923
924 AlertDialog mUidAlert;
925
926 final Handler mHandler = new Handler() {
927 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800928 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 //}
930
931 public void handleMessage(Message msg) {
932 switch (msg.what) {
933 case SHOW_ERROR_MSG: {
934 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 synchronized (ActivityManagerService.this) {
936 ProcessRecord proc = (ProcessRecord)data.get("app");
937 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800938 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 return;
940 }
941 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700942 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800943 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 d.show();
945 proc.crashDialog = d;
946 } else {
947 // The device is asleep, so just pretend that the user
948 // saw a crash dialog and hit "force quit".
949 res.set(0);
950 }
951 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700952
953 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 } break;
955 case SHOW_NOT_RESPONDING_MSG: {
956 synchronized (ActivityManagerService.this) {
957 HashMap data = (HashMap) msg.obj;
958 ProcessRecord proc = (ProcessRecord)data.get("app");
959 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800960 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 return;
962 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800963
964 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
965 null, null, 0, null, null, null,
966 false, false, MY_PID, Process.SYSTEM_UID);
967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700969 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 d.show();
971 proc.anrDialog = d;
972 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700973
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700974 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700976 case SHOW_STRICT_MODE_VIOLATION_MSG: {
977 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
978 synchronized (ActivityManagerService.this) {
979 ProcessRecord proc = (ProcessRecord) data.get("app");
980 if (proc == null) {
981 Slog.e(TAG, "App not found when showing strict mode dialog.");
982 break;
983 }
984 if (proc.crashDialog != null) {
985 Slog.e(TAG, "App already has strict mode dialog: " + proc);
986 return;
987 }
988 AppErrorResult res = (AppErrorResult) data.get("result");
989 if (!mSleeping && !mShuttingDown) {
990 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
991 d.show();
992 proc.crashDialog = d;
993 } else {
994 // The device is asleep, so just pretend that the user
995 // saw a crash dialog and hit "force quit".
996 res.set(0);
997 }
998 }
999 ensureBootCompleted();
1000 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 case SHOW_FACTORY_ERROR_MSG: {
1002 Dialog d = new FactoryErrorDialog(
1003 mContext, msg.getData().getCharSequence("msg"));
1004 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001005 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 } break;
1007 case UPDATE_CONFIGURATION_MSG: {
1008 final ContentResolver resolver = mContext.getContentResolver();
1009 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1010 } break;
1011 case GC_BACKGROUND_PROCESSES_MSG: {
1012 synchronized (ActivityManagerService.this) {
1013 performAppGcsIfAppropriateLocked();
1014 }
1015 } break;
1016 case WAIT_FOR_DEBUGGER_MSG: {
1017 synchronized (ActivityManagerService.this) {
1018 ProcessRecord app = (ProcessRecord)msg.obj;
1019 if (msg.arg1 != 0) {
1020 if (!app.waitedForDebugger) {
1021 Dialog d = new AppWaitingForDebuggerDialog(
1022 ActivityManagerService.this,
1023 mContext, app);
1024 app.waitDialog = d;
1025 app.waitedForDebugger = true;
1026 d.show();
1027 }
1028 } else {
1029 if (app.waitDialog != null) {
1030 app.waitDialog.dismiss();
1031 app.waitDialog = null;
1032 }
1033 }
1034 }
1035 } break;
1036 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001037 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 TAG, "Received BROADCAST_INTENT_MSG");
1039 processNextBroadcast(true);
1040 } break;
1041 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001042 if (mDidDexOpt) {
1043 mDidDexOpt = false;
1044 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1045 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1046 return;
1047 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001048 // Only process broadcast timeouts if the system is ready. That way
1049 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1050 // to do heavy lifting for system up
1051 if (mSystemReady) {
1052 broadcastTimeout();
1053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001056 if (mDidDexOpt) {
1057 mDidDexOpt = false;
1058 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1059 nmsg.obj = msg.obj;
1060 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1061 return;
1062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 serviceTimeout((ProcessRecord)msg.obj);
1064 } break;
1065 case UPDATE_TIME_ZONE: {
1066 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001067 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1068 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 if (r.thread != null) {
1070 try {
1071 r.thread.updateTimeZone();
1072 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001073 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 }
1075 }
1076 }
1077 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001078 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 case SHOW_UID_ERROR_MSG: {
1080 // XXX This is a temporary dialog, no need to localize.
1081 AlertDialog d = new BaseErrorDialog(mContext);
1082 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1083 d.setCancelable(false);
1084 d.setTitle("System UIDs Inconsistent");
1085 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1086 d.setButton("I'm Feeling Lucky",
1087 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1088 mUidAlert = d;
1089 d.show();
1090 } break;
1091 case IM_FEELING_LUCKY_MSG: {
1092 if (mUidAlert != null) {
1093 mUidAlert.dismiss();
1094 mUidAlert = null;
1095 }
1096 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001098 if (mDidDexOpt) {
1099 mDidDexOpt = false;
1100 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1101 nmsg.obj = msg.obj;
1102 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1103 return;
1104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 ProcessRecord app = (ProcessRecord)msg.obj;
1106 synchronized (ActivityManagerService.this) {
1107 processStartTimedOutLocked(app);
1108 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001109 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001110 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1111 synchronized (ActivityManagerService.this) {
1112 doPendingActivityLaunchesLocked(true);
1113 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001114 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001115 case KILL_APPLICATION_MSG: {
1116 synchronized (ActivityManagerService.this) {
1117 int uid = msg.arg1;
1118 boolean restart = (msg.arg2 == 1);
1119 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001120 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001121 }
1122 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001123 case FINALIZE_PENDING_INTENT_MSG: {
1124 ((PendingIntentRecord)msg.obj).completeFinalize();
1125 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001126 case POST_HEAVY_NOTIFICATION_MSG: {
1127 INotificationManager inm = NotificationManager.getService();
1128 if (inm == null) {
1129 return;
1130 }
1131
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001132 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001133 ProcessRecord process = root.app;
1134 if (process == null) {
1135 return;
1136 }
1137
1138 try {
1139 Context context = mContext.createPackageContext(process.info.packageName, 0);
1140 String text = mContext.getString(R.string.heavy_weight_notification,
1141 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1142 Notification notification = new Notification();
1143 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1144 notification.when = 0;
1145 notification.flags = Notification.FLAG_ONGOING_EVENT;
1146 notification.tickerText = text;
1147 notification.defaults = 0; // please be quiet
1148 notification.sound = null;
1149 notification.vibrate = null;
1150 notification.setLatestEventInfo(context, text,
1151 mContext.getText(R.string.heavy_weight_notification_detail),
1152 PendingIntent.getActivity(mContext, 0, root.intent,
1153 PendingIntent.FLAG_CANCEL_CURRENT));
1154
1155 try {
1156 int[] outId = new int[1];
1157 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1158 notification, outId);
1159 } catch (RuntimeException e) {
1160 Slog.w(ActivityManagerService.TAG,
1161 "Error showing notification for heavy-weight app", e);
1162 } catch (RemoteException e) {
1163 }
1164 } catch (NameNotFoundException e) {
1165 Log.w(TAG, "Unable to create context for heavy notification", e);
1166 }
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) {
2370 Log.w(TAG, "crashApplication: nothing for uid=" + uid
2371 + " 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 }
4054 return true;
4055 } catch (RemoteException e) {
4056 return false;
4057 }
4058 }
4059
4060 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4061 int modeFlags) {
4062 // Root gets to do everything.
4063 if (uid == 0 || !Process.supportsProcesses()) {
4064 return true;
4065 }
4066 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4067 if (perms == null) return false;
4068 UriPermission perm = perms.get(uri);
4069 if (perm == null) return false;
4070 return (modeFlags&perm.modeFlags) == modeFlags;
4071 }
4072
4073 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4074 // Another redirected-binder-call permissions check as in
4075 // {@link checkComponentPermission}.
4076 Identity tlsIdentity = sCallerIdentity.get();
4077 if (tlsIdentity != null) {
4078 uid = tlsIdentity.uid;
4079 pid = tlsIdentity.pid;
4080 }
4081
4082 // Our own process gets to do everything.
4083 if (pid == MY_PID) {
4084 return PackageManager.PERMISSION_GRANTED;
4085 }
4086 synchronized(this) {
4087 return checkUriPermissionLocked(uri, uid, modeFlags)
4088 ? PackageManager.PERMISSION_GRANTED
4089 : PackageManager.PERMISSION_DENIED;
4090 }
4091 }
4092
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004093 void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004094 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4096 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4097 if (modeFlags == 0) {
4098 return;
4099 }
4100
Joe Onorato8a9b2202010-02-26 18:56:32 -08004101 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004102 "Requested grant " + targetPkg + " permission to " + uri);
4103
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004104 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004105
4106 // If this is not a content: uri, we can't do anything with it.
4107 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004108 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004109 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004110 return;
4111 }
4112
4113 String name = uri.getAuthority();
4114 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004115 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 if (cpr != null) {
4117 pi = cpr.info;
4118 } else {
4119 try {
4120 pi = pm.resolveContentProvider(name,
4121 PackageManager.GET_URI_PERMISSION_PATTERNS);
4122 } catch (RemoteException ex) {
4123 }
4124 }
4125 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004126 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 return;
4128 }
4129
4130 int targetUid;
4131 try {
4132 targetUid = pm.getPackageUid(targetPkg);
4133 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004134 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004135 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004136 return;
4137 }
4138 } catch (RemoteException ex) {
4139 return;
4140 }
4141
4142 // First... does the target actually need this permission?
4143 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4144 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004145 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004146 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004147 return;
4148 }
4149
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004150 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004151 if (!pi.grantUriPermissions) {
4152 throw new SecurityException("Provider " + pi.packageName
4153 + "/" + pi.name
4154 + " does not allow granting of Uri permissions (uri "
4155 + uri + ")");
4156 }
4157 if (pi.uriPermissionPatterns != null) {
4158 final int N = pi.uriPermissionPatterns.length;
4159 boolean allowed = false;
4160 for (int i=0; i<N; i++) {
4161 if (pi.uriPermissionPatterns[i] != null
4162 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4163 allowed = true;
4164 break;
4165 }
4166 }
4167 if (!allowed) {
4168 throw new SecurityException("Provider " + pi.packageName
4169 + "/" + pi.name
4170 + " does not allow granting of permission to path of Uri "
4171 + uri);
4172 }
4173 }
4174
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004175 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004176 // this uri?
4177 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4178 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4179 throw new SecurityException("Uid " + callingUid
4180 + " does not have permission to uri " + uri);
4181 }
4182 }
4183
4184 // Okay! So here we are: the caller has the assumed permission
4185 // to the uri, and the target doesn't. Let's now give this to
4186 // the target.
4187
Joe Onorato8a9b2202010-02-26 18:56:32 -08004188 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004189 "Granting " + targetPkg + " permission to " + uri);
4190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004191 HashMap<Uri, UriPermission> targetUris
4192 = mGrantedUriPermissions.get(targetUid);
4193 if (targetUris == null) {
4194 targetUris = new HashMap<Uri, UriPermission>();
4195 mGrantedUriPermissions.put(targetUid, targetUris);
4196 }
4197
4198 UriPermission perm = targetUris.get(uri);
4199 if (perm == null) {
4200 perm = new UriPermission(targetUid, uri);
4201 targetUris.put(uri, perm);
4202
4203 }
4204 perm.modeFlags |= modeFlags;
4205 if (activity == null) {
4206 perm.globalModeFlags |= modeFlags;
4207 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4208 perm.readActivities.add(activity);
4209 if (activity.readUriPermissions == null) {
4210 activity.readUriPermissions = new HashSet<UriPermission>();
4211 }
4212 activity.readUriPermissions.add(perm);
4213 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4214 perm.writeActivities.add(activity);
4215 if (activity.writeUriPermissions == null) {
4216 activity.writeUriPermissions = new HashSet<UriPermission>();
4217 }
4218 activity.writeUriPermissions.add(perm);
4219 }
4220 }
4221
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004222 void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004223 String targetPkg, Intent intent, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 if (intent == null) {
4225 return;
4226 }
4227 Uri data = intent.getData();
4228 if (data == null) {
4229 return;
4230 }
4231 grantUriPermissionLocked(callingUid, targetPkg, data,
4232 intent.getFlags(), activity);
4233 }
4234
4235 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4236 Uri uri, int modeFlags) {
4237 synchronized(this) {
4238 final ProcessRecord r = getRecordForAppLocked(caller);
4239 if (r == null) {
4240 throw new SecurityException("Unable to find app for caller "
4241 + caller
4242 + " when granting permission to uri " + uri);
4243 }
4244 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004245 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004246 return;
4247 }
4248 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004249 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 return;
4251 }
4252
4253 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4254 null);
4255 }
4256 }
4257
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004258 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4260 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4261 HashMap<Uri, UriPermission> perms
4262 = mGrantedUriPermissions.get(perm.uid);
4263 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004264 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004265 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004266 perms.remove(perm.uri);
4267 if (perms.size() == 0) {
4268 mGrantedUriPermissions.remove(perm.uid);
4269 }
4270 }
4271 }
4272 }
4273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4275 int modeFlags) {
4276 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4277 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4278 if (modeFlags == 0) {
4279 return;
4280 }
4281
Joe Onorato8a9b2202010-02-26 18:56:32 -08004282 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004283 "Revoking all granted permissions to " + uri);
4284
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004285 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286
4287 final String authority = uri.getAuthority();
4288 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004289 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 if (cpr != null) {
4291 pi = cpr.info;
4292 } else {
4293 try {
4294 pi = pm.resolveContentProvider(authority,
4295 PackageManager.GET_URI_PERMISSION_PATTERNS);
4296 } catch (RemoteException ex) {
4297 }
4298 }
4299 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004300 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 return;
4302 }
4303
4304 // Does the caller have this permission on the URI?
4305 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4306 // Right now, if you are not the original owner of the permission,
4307 // you are not allowed to revoke it.
4308 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4309 throw new SecurityException("Uid " + callingUid
4310 + " does not have permission to uri " + uri);
4311 //}
4312 }
4313
4314 // Go through all of the permissions and remove any that match.
4315 final List<String> SEGMENTS = uri.getPathSegments();
4316 if (SEGMENTS != null) {
4317 final int NS = SEGMENTS.size();
4318 int N = mGrantedUriPermissions.size();
4319 for (int i=0; i<N; i++) {
4320 HashMap<Uri, UriPermission> perms
4321 = mGrantedUriPermissions.valueAt(i);
4322 Iterator<UriPermission> it = perms.values().iterator();
4323 toploop:
4324 while (it.hasNext()) {
4325 UriPermission perm = it.next();
4326 Uri targetUri = perm.uri;
4327 if (!authority.equals(targetUri.getAuthority())) {
4328 continue;
4329 }
4330 List<String> targetSegments = targetUri.getPathSegments();
4331 if (targetSegments == null) {
4332 continue;
4333 }
4334 if (targetSegments.size() < NS) {
4335 continue;
4336 }
4337 for (int j=0; j<NS; j++) {
4338 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4339 continue toploop;
4340 }
4341 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004342 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004343 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 perm.clearModes(modeFlags);
4345 if (perm.modeFlags == 0) {
4346 it.remove();
4347 }
4348 }
4349 if (perms.size() == 0) {
4350 mGrantedUriPermissions.remove(
4351 mGrantedUriPermissions.keyAt(i));
4352 N--;
4353 i--;
4354 }
4355 }
4356 }
4357 }
4358
4359 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4360 int modeFlags) {
4361 synchronized(this) {
4362 final ProcessRecord r = getRecordForAppLocked(caller);
4363 if (r == null) {
4364 throw new SecurityException("Unable to find app for caller "
4365 + caller
4366 + " when revoking permission to uri " + uri);
4367 }
4368 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004369 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 return;
4371 }
4372
4373 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4374 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4375 if (modeFlags == 0) {
4376 return;
4377 }
4378
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004379 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380
4381 final String authority = uri.getAuthority();
4382 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004383 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 if (cpr != null) {
4385 pi = cpr.info;
4386 } else {
4387 try {
4388 pi = pm.resolveContentProvider(authority,
4389 PackageManager.GET_URI_PERMISSION_PATTERNS);
4390 } catch (RemoteException ex) {
4391 }
4392 }
4393 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004394 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395 return;
4396 }
4397
4398 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4399 }
4400 }
4401
4402 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4403 synchronized (this) {
4404 ProcessRecord app =
4405 who != null ? getRecordForAppLocked(who) : null;
4406 if (app == null) return;
4407
4408 Message msg = Message.obtain();
4409 msg.what = WAIT_FOR_DEBUGGER_MSG;
4410 msg.obj = app;
4411 msg.arg1 = waiting ? 1 : 0;
4412 mHandler.sendMessage(msg);
4413 }
4414 }
4415
4416 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4417 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004418 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004419 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004420 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421 }
4422
4423 // =========================================================
4424 // TASK MANAGEMENT
4425 // =========================================================
4426
4427 public List getTasks(int maxNum, int flags,
4428 IThumbnailReceiver receiver) {
4429 ArrayList list = new ArrayList();
4430
4431 PendingThumbnailsRecord pending = null;
4432 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004433 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434
4435 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004436 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004437 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4438 + ", receiver=" + receiver);
4439
4440 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4441 != PackageManager.PERMISSION_GRANTED) {
4442 if (receiver != null) {
4443 // If the caller wants to wait for pending thumbnails,
4444 // it ain't gonna get them.
4445 try {
4446 receiver.finished();
4447 } catch (RemoteException ex) {
4448 }
4449 }
4450 String msg = "Permission Denial: getTasks() from pid="
4451 + Binder.getCallingPid()
4452 + ", uid=" + Binder.getCallingUid()
4453 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004454 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 throw new SecurityException(msg);
4456 }
4457
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004458 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004459 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004460 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004461 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004462 CharSequence topDescription = null;
4463 TaskRecord curTask = null;
4464 int numActivities = 0;
4465 int numRunning = 0;
4466 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004467 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004469 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004470
4471 // Initialize state for next task if needed.
4472 if (top == null ||
4473 (top.state == ActivityState.INITIALIZING
4474 && top.task == r.task)) {
4475 top = r;
4476 topDescription = r.description;
4477 curTask = r.task;
4478 numActivities = numRunning = 0;
4479 }
4480
4481 // Add 'r' into the current task.
4482 numActivities++;
4483 if (r.app != null && r.app.thread != null) {
4484 numRunning++;
4485 }
4486 if (topDescription == null) {
4487 topDescription = r.description;
4488 }
4489
Joe Onorato8a9b2202010-02-26 18:56:32 -08004490 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 TAG, r.intent.getComponent().flattenToShortString()
4492 + ": task=" + r.task);
4493
4494 // If the next one is a different task, generate a new
4495 // TaskInfo entry for what we have.
4496 if (next == null || next.task != curTask) {
4497 ActivityManager.RunningTaskInfo ci
4498 = new ActivityManager.RunningTaskInfo();
4499 ci.id = curTask.taskId;
4500 ci.baseActivity = r.intent.getComponent();
4501 ci.topActivity = top.intent.getComponent();
4502 ci.thumbnail = top.thumbnail;
4503 ci.description = topDescription;
4504 ci.numActivities = numActivities;
4505 ci.numRunning = numRunning;
4506 //System.out.println(
4507 // "#" + maxNum + ": " + " descr=" + ci.description);
4508 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004509 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 TAG, "State=" + top.state + "Idle=" + top.idle
4511 + " app=" + top.app
4512 + " thr=" + (top.app != null ? top.app.thread : null));
4513 if (top.state == ActivityState.RESUMED
4514 || top.state == ActivityState.PAUSING) {
4515 if (top.idle && top.app != null
4516 && top.app.thread != null) {
4517 topRecord = top;
4518 topThumbnail = top.app.thread;
4519 } else {
4520 top.thumbnailNeeded = true;
4521 }
4522 }
4523 if (pending == null) {
4524 pending = new PendingThumbnailsRecord(receiver);
4525 }
4526 pending.pendingRecords.add(top);
4527 }
4528 list.add(ci);
4529 maxNum--;
4530 top = null;
4531 }
4532 }
4533
4534 if (pending != null) {
4535 mPendingThumbnails.add(pending);
4536 }
4537 }
4538
Joe Onorato8a9b2202010-02-26 18:56:32 -08004539 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004540
4541 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004542 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004543 try {
4544 topThumbnail.requestThumbnail(topRecord);
4545 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004546 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004547 sendPendingThumbnail(null, topRecord, null, null, true);
4548 }
4549 }
4550
4551 if (pending == null && receiver != null) {
4552 // In this case all thumbnails were available and the client
4553 // is being asked to be told when the remaining ones come in...
4554 // which is unusually, since the top-most currently running
4555 // activity should never have a canned thumbnail! Oh well.
4556 try {
4557 receiver.finished();
4558 } catch (RemoteException ex) {
4559 }
4560 }
4561
4562 return list;
4563 }
4564
4565 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4566 int flags) {
4567 synchronized (this) {
4568 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4569 "getRecentTasks()");
4570
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004571 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004573 final int N = mRecentTasks.size();
4574 ArrayList<ActivityManager.RecentTaskInfo> res
4575 = new ArrayList<ActivityManager.RecentTaskInfo>(
4576 maxNum < N ? maxNum : N);
4577 for (int i=0; i<N && maxNum > 0; i++) {
4578 TaskRecord tr = mRecentTasks.get(i);
4579 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4580 || (tr.intent == null)
4581 || ((tr.intent.getFlags()
4582 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4583 ActivityManager.RecentTaskInfo rti
4584 = new ActivityManager.RecentTaskInfo();
4585 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4586 rti.baseIntent = new Intent(
4587 tr.intent != null ? tr.intent : tr.affinityIntent);
4588 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004589
4590 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4591 // Check whether this activity is currently available.
4592 try {
4593 if (rti.origActivity != null) {
4594 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4595 continue;
4596 }
4597 } else if (rti.baseIntent != null) {
4598 if (pm.queryIntentActivities(rti.baseIntent,
4599 null, 0) == null) {
4600 continue;
4601 }
4602 }
4603 } catch (RemoteException e) {
4604 // Will never happen.
4605 }
4606 }
4607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 res.add(rti);
4609 maxNum--;
4610 }
4611 }
4612 return res;
4613 }
4614 }
4615
4616 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4617 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004618 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 TaskRecord jt = startTask;
4620
4621 // First look backwards
4622 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004623 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 if (r.task != jt) {
4625 jt = r.task;
4626 if (affinity.equals(jt.affinity)) {
4627 return j;
4628 }
4629 }
4630 }
4631
4632 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004633 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634 jt = startTask;
4635 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004636 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 if (r.task != jt) {
4638 if (affinity.equals(jt.affinity)) {
4639 return j;
4640 }
4641 jt = r.task;
4642 }
4643 }
4644
4645 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004646 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 return N-1;
4648 }
4649
4650 return -1;
4651 }
4652
4653 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004654 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 */
4656 public void moveTaskToFront(int task) {
4657 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4658 "moveTaskToFront()");
4659
4660 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004661 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4662 Binder.getCallingUid(), "Task to front")) {
4663 return;
4664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 final long origId = Binder.clearCallingIdentity();
4666 try {
4667 int N = mRecentTasks.size();
4668 for (int i=0; i<N; i++) {
4669 TaskRecord tr = mRecentTasks.get(i);
4670 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004671 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004672 return;
4673 }
4674 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004675 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4676 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004677 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004678 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 return;
4680 }
4681 }
4682 } finally {
4683 Binder.restoreCallingIdentity(origId);
4684 }
4685 }
4686 }
4687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004688 public void moveTaskToBack(int task) {
4689 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4690 "moveTaskToBack()");
4691
4692 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004693 if (mMainStack.mResumedActivity != null
4694 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004695 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4696 Binder.getCallingUid(), "Task to back")) {
4697 return;
4698 }
4699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004701 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 Binder.restoreCallingIdentity(origId);
4703 }
4704 }
4705
4706 /**
4707 * Moves an activity, and all of the other activities within the same task, to the bottom
4708 * of the history stack. The activity's order within the task is unchanged.
4709 *
4710 * @param token A reference to the activity we wish to move
4711 * @param nonRoot If false then this only works if the activity is the root
4712 * of a task; if true it will work for any activity in a task.
4713 * @return Returns true if the move completed, false if not.
4714 */
4715 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4716 synchronized(this) {
4717 final long origId = Binder.clearCallingIdentity();
4718 int taskId = getTaskForActivityLocked(token, !nonRoot);
4719 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004720 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 }
4722 Binder.restoreCallingIdentity(origId);
4723 }
4724 return false;
4725 }
4726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 public void moveTaskBackwards(int task) {
4728 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4729 "moveTaskBackwards()");
4730
4731 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004732 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4733 Binder.getCallingUid(), "Task backwards")) {
4734 return;
4735 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004736 final long origId = Binder.clearCallingIdentity();
4737 moveTaskBackwardsLocked(task);
4738 Binder.restoreCallingIdentity(origId);
4739 }
4740 }
4741
4742 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004743 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 }
4745
4746 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4747 synchronized(this) {
4748 return getTaskForActivityLocked(token, onlyRoot);
4749 }
4750 }
4751
4752 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004753 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 TaskRecord lastTask = null;
4755 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004756 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 if (r == token) {
4758 if (!onlyRoot || lastTask != r.task) {
4759 return r.task.taskId;
4760 }
4761 return -1;
4762 }
4763 lastTask = r.task;
4764 }
4765
4766 return -1;
4767 }
4768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004769 public void finishOtherInstances(IBinder token, ComponentName className) {
4770 synchronized(this) {
4771 final long origId = Binder.clearCallingIdentity();
4772
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004773 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004774 TaskRecord lastTask = null;
4775 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004776 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 if (r.realActivity.equals(className)
4778 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004779 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 null, "others")) {
4781 i--;
4782 N--;
4783 }
4784 }
4785 lastTask = r.task;
4786 }
4787
4788 Binder.restoreCallingIdentity(origId);
4789 }
4790 }
4791
4792 // =========================================================
4793 // THUMBNAILS
4794 // =========================================================
4795
4796 public void reportThumbnail(IBinder token,
4797 Bitmap thumbnail, CharSequence description) {
4798 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4799 final long origId = Binder.clearCallingIdentity();
4800 sendPendingThumbnail(null, token, thumbnail, description, true);
4801 Binder.restoreCallingIdentity(origId);
4802 }
4803
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004804 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004805 Bitmap thumbnail, CharSequence description, boolean always) {
4806 TaskRecord task = null;
4807 ArrayList receivers = null;
4808
4809 //System.out.println("Send pending thumbnail: " + r);
4810
4811 synchronized(this) {
4812 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004813 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 if (index < 0) {
4815 return;
4816 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004817 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004818 }
4819 if (thumbnail == null) {
4820 thumbnail = r.thumbnail;
4821 description = r.description;
4822 }
4823 if (thumbnail == null && !always) {
4824 // If there is no thumbnail, and this entry is not actually
4825 // going away, then abort for now and pick up the next
4826 // thumbnail we get.
4827 return;
4828 }
4829 task = r.task;
4830
4831 int N = mPendingThumbnails.size();
4832 int i=0;
4833 while (i<N) {
4834 PendingThumbnailsRecord pr =
4835 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4836 //System.out.println("Looking in " + pr.pendingRecords);
4837 if (pr.pendingRecords.remove(r)) {
4838 if (receivers == null) {
4839 receivers = new ArrayList();
4840 }
4841 receivers.add(pr);
4842 if (pr.pendingRecords.size() == 0) {
4843 pr.finished = true;
4844 mPendingThumbnails.remove(i);
4845 N--;
4846 continue;
4847 }
4848 }
4849 i++;
4850 }
4851 }
4852
4853 if (receivers != null) {
4854 final int N = receivers.size();
4855 for (int i=0; i<N; i++) {
4856 try {
4857 PendingThumbnailsRecord pr =
4858 (PendingThumbnailsRecord)receivers.get(i);
4859 pr.receiver.newThumbnail(
4860 task != null ? task.taskId : -1, thumbnail, description);
4861 if (pr.finished) {
4862 pr.receiver.finished();
4863 }
4864 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004865 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 }
4867 }
4868 }
4869 }
4870
4871 // =========================================================
4872 // CONTENT PROVIDERS
4873 // =========================================================
4874
4875 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4876 List providers = null;
4877 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004878 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004880 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 } catch (RemoteException ex) {
4882 }
4883 if (providers != null) {
4884 final int N = providers.size();
4885 for (int i=0; i<N; i++) {
4886 ProviderInfo cpi =
4887 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004888 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004889 if (cpr == null) {
4890 cpr = new ContentProviderRecord(cpi, app.info);
4891 mProvidersByClass.put(cpi.name, cpr);
4892 }
4893 app.pubProviders.put(cpi.name, cpr);
4894 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004895 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 }
4897 }
4898 return providers;
4899 }
4900
4901 private final String checkContentProviderPermissionLocked(
4902 ProviderInfo cpi, ProcessRecord r, int mode) {
4903 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
4904 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
4905 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
4906 cpi.exported ? -1 : cpi.applicationInfo.uid)
4907 == PackageManager.PERMISSION_GRANTED
4908 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4909 return null;
4910 }
4911 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
4912 cpi.exported ? -1 : cpi.applicationInfo.uid)
4913 == PackageManager.PERMISSION_GRANTED) {
4914 return null;
4915 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004916
4917 PathPermission[] pps = cpi.pathPermissions;
4918 if (pps != null) {
4919 int i = pps.length;
4920 while (i > 0) {
4921 i--;
4922 PathPermission pp = pps[i];
4923 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
4924 cpi.exported ? -1 : cpi.applicationInfo.uid)
4925 == PackageManager.PERMISSION_GRANTED
4926 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4927 return null;
4928 }
4929 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
4930 cpi.exported ? -1 : cpi.applicationInfo.uid)
4931 == PackageManager.PERMISSION_GRANTED) {
4932 return null;
4933 }
4934 }
4935 }
4936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 String msg = "Permission Denial: opening provider " + cpi.name
4938 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
4939 + ", uid=" + callingUid + ") requires "
4940 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004941 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 return msg;
4943 }
4944
4945 private final ContentProviderHolder getContentProviderImpl(
4946 IApplicationThread caller, String name) {
4947 ContentProviderRecord cpr;
4948 ProviderInfo cpi = null;
4949
4950 synchronized(this) {
4951 ProcessRecord r = null;
4952 if (caller != null) {
4953 r = getRecordForAppLocked(caller);
4954 if (r == null) {
4955 throw new SecurityException(
4956 "Unable to find app for caller " + caller
4957 + " (pid=" + Binder.getCallingPid()
4958 + ") when getting content provider " + name);
4959 }
4960 }
4961
4962 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07004963 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 if (cpr != null) {
4965 cpi = cpr.info;
4966 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
4967 return new ContentProviderHolder(cpi,
4968 cpi.readPermission != null
4969 ? cpi.readPermission : cpi.writePermission);
4970 }
4971
4972 if (r != null && cpr.canRunHere(r)) {
4973 // This provider has been published or is in the process
4974 // of being published... but it is also allowed to run
4975 // in the caller's process, so don't make a connection
4976 // and just let the caller instantiate its own instance.
4977 if (cpr.provider != null) {
4978 // don't give caller the provider object, it needs
4979 // to make its own.
4980 cpr = new ContentProviderRecord(cpr);
4981 }
4982 return cpr;
4983 }
4984
4985 final long origId = Binder.clearCallingIdentity();
4986
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004987 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 // return it right away.
4989 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004990 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004991 "Adding provider requested by "
4992 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004993 + cpr.info.processName);
4994 Integer cnt = r.conProviders.get(cpr);
4995 if (cnt == null) {
4996 r.conProviders.put(cpr, new Integer(1));
4997 } else {
4998 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
4999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005001 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5002 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005003 // make sure to count it as being accessed and thus
5004 // back up on the LRU list. This is good because
5005 // content providers are often expensive to start.
5006 updateLruProcessLocked(cpr.app, false, true);
5007 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005008 } else {
5009 cpr.externals++;
5010 }
5011
5012 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 updateOomAdjLocked(cpr.app);
5014 }
5015
5016 Binder.restoreCallingIdentity(origId);
5017
5018 } else {
5019 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005020 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005021 resolveContentProvider(name,
5022 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 } catch (RemoteException ex) {
5024 }
5025 if (cpi == null) {
5026 return null;
5027 }
5028
5029 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
5030 return new ContentProviderHolder(cpi,
5031 cpi.readPermission != null
5032 ? cpi.readPermission : cpi.writePermission);
5033 }
5034
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005035 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5036 && !cpi.processName.equals("system")) {
5037 // If this content provider does not run in the system
5038 // process, and the system is not yet ready to run other
5039 // processes, then fail fast instead of hanging.
5040 throw new IllegalArgumentException(
5041 "Attempt to launch content provider before system ready");
5042 }
5043
Dianne Hackborn860755f2010-06-03 18:47:52 -07005044 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005045 final boolean firstClass = cpr == null;
5046 if (firstClass) {
5047 try {
5048 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005049 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005050 getApplicationInfo(
5051 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005052 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005054 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 + cpi.name);
5056 return null;
5057 }
5058 cpr = new ContentProviderRecord(cpi, ai);
5059 } catch (RemoteException ex) {
5060 // pm is in same process, this will never happen.
5061 }
5062 }
5063
5064 if (r != null && cpr.canRunHere(r)) {
5065 // If this is a multiprocess provider, then just return its
5066 // info and allow the caller to instantiate it. Only do
5067 // this if the provider is the same user as the caller's
5068 // process, or can run as root (so can be in any process).
5069 return cpr;
5070 }
5071
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005072 if (DEBUG_PROVIDER) {
5073 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005074 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005075 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 }
5077
5078 // This is single process, and our app is now connecting to it.
5079 // See if we are already in the process of launching this
5080 // provider.
5081 final int N = mLaunchingProviders.size();
5082 int i;
5083 for (i=0; i<N; i++) {
5084 if (mLaunchingProviders.get(i) == cpr) {
5085 break;
5086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005087 }
5088
5089 // If the provider is not already being launched, then get it
5090 // started.
5091 if (i >= N) {
5092 final long origId = Binder.clearCallingIdentity();
5093 ProcessRecord proc = startProcessLocked(cpi.processName,
5094 cpr.appInfo, false, 0, "content provider",
5095 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005096 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005098 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 + cpi.applicationInfo.packageName + "/"
5100 + cpi.applicationInfo.uid + " for provider "
5101 + name + ": process is bad");
5102 return null;
5103 }
5104 cpr.launchingApp = proc;
5105 mLaunchingProviders.add(cpr);
5106 Binder.restoreCallingIdentity(origId);
5107 }
5108
5109 // Make sure the provider is published (the same provider class
5110 // may be published under multiple names).
5111 if (firstClass) {
5112 mProvidersByClass.put(cpi.name, cpr);
5113 }
5114 mProvidersByName.put(name, cpr);
5115
5116 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005117 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005118 "Adding provider requested by "
5119 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005120 + cpr.info.processName);
5121 Integer cnt = r.conProviders.get(cpr);
5122 if (cnt == null) {
5123 r.conProviders.put(cpr, new Integer(1));
5124 } else {
5125 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005127 cpr.clients.add(r);
5128 } else {
5129 cpr.externals++;
5130 }
5131 }
5132 }
5133
5134 // Wait for the provider to be published...
5135 synchronized (cpr) {
5136 while (cpr.provider == null) {
5137 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005138 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 + cpi.applicationInfo.packageName + "/"
5140 + cpi.applicationInfo.uid + " for provider "
5141 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005142 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 cpi.applicationInfo.packageName,
5144 cpi.applicationInfo.uid, name);
5145 return null;
5146 }
5147 try {
5148 cpr.wait();
5149 } catch (InterruptedException ex) {
5150 }
5151 }
5152 }
5153 return cpr;
5154 }
5155
5156 public final ContentProviderHolder getContentProvider(
5157 IApplicationThread caller, String name) {
5158 if (caller == null) {
5159 String msg = "null IApplicationThread when getting content provider "
5160 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005161 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 throw new SecurityException(msg);
5163 }
5164
5165 return getContentProviderImpl(caller, name);
5166 }
5167
5168 private ContentProviderHolder getContentProviderExternal(String name) {
5169 return getContentProviderImpl(null, name);
5170 }
5171
5172 /**
5173 * Drop a content provider from a ProcessRecord's bookkeeping
5174 * @param cpr
5175 */
5176 public void removeContentProvider(IApplicationThread caller, String name) {
5177 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005178 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005179 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005180 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005181 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005182 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005183 return;
5184 }
5185 final ProcessRecord r = getRecordForAppLocked(caller);
5186 if (r == null) {
5187 throw new SecurityException(
5188 "Unable to find app for caller " + caller +
5189 " when removing content provider " + name);
5190 }
5191 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005192 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005193 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005194 + r.info.processName + " from process "
5195 + localCpr.appInfo.processName);
5196 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005198 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005199 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 return;
5201 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005202 Integer cnt = r.conProviders.get(localCpr);
5203 if (cnt == null || cnt.intValue() <= 1) {
5204 localCpr.clients.remove(r);
5205 r.conProviders.remove(localCpr);
5206 } else {
5207 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5208 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005209 }
5210 updateOomAdjLocked();
5211 }
5212 }
5213
5214 private void removeContentProviderExternal(String name) {
5215 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005216 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005217 if(cpr == null) {
5218 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005219 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 return;
5221 }
5222
5223 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005224 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 localCpr.externals--;
5226 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005227 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 }
5229 updateOomAdjLocked();
5230 }
5231 }
5232
5233 public final void publishContentProviders(IApplicationThread caller,
5234 List<ContentProviderHolder> providers) {
5235 if (providers == null) {
5236 return;
5237 }
5238
5239 synchronized(this) {
5240 final ProcessRecord r = getRecordForAppLocked(caller);
5241 if (r == null) {
5242 throw new SecurityException(
5243 "Unable to find app for caller " + caller
5244 + " (pid=" + Binder.getCallingPid()
5245 + ") when publishing content providers");
5246 }
5247
5248 final long origId = Binder.clearCallingIdentity();
5249
5250 final int N = providers.size();
5251 for (int i=0; i<N; i++) {
5252 ContentProviderHolder src = providers.get(i);
5253 if (src == null || src.info == null || src.provider == null) {
5254 continue;
5255 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005256 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 if (dst != null) {
5258 mProvidersByClass.put(dst.info.name, dst);
5259 String names[] = dst.info.authority.split(";");
5260 for (int j = 0; j < names.length; j++) {
5261 mProvidersByName.put(names[j], dst);
5262 }
5263
5264 int NL = mLaunchingProviders.size();
5265 int j;
5266 for (j=0; j<NL; j++) {
5267 if (mLaunchingProviders.get(j) == dst) {
5268 mLaunchingProviders.remove(j);
5269 j--;
5270 NL--;
5271 }
5272 }
5273 synchronized (dst) {
5274 dst.provider = src.provider;
5275 dst.app = r;
5276 dst.notifyAll();
5277 }
5278 updateOomAdjLocked(r);
5279 }
5280 }
5281
5282 Binder.restoreCallingIdentity(origId);
5283 }
5284 }
5285
5286 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005287 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005288 synchronized (mSelf) {
5289 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5290 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005291 if (providers != null) {
5292 for (int i=providers.size()-1; i>=0; i--) {
5293 ProviderInfo pi = (ProviderInfo)providers.get(i);
5294 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5295 Slog.w(TAG, "Not installing system proc provider " + pi.name
5296 + ": not system .apk");
5297 providers.remove(i);
5298 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005299 }
5300 }
5301 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005302 if (providers != null) {
5303 mSystemThread.installSystemProviders(providers);
5304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 }
5306
5307 // =========================================================
5308 // GLOBAL MANAGEMENT
5309 // =========================================================
5310
5311 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5312 ApplicationInfo info, String customProcess) {
5313 String proc = customProcess != null ? customProcess : info.processName;
5314 BatteryStatsImpl.Uid.Proc ps = null;
5315 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5316 synchronized (stats) {
5317 ps = stats.getProcessStatsLocked(info.uid, proc);
5318 }
5319 return new ProcessRecord(ps, thread, info, proc);
5320 }
5321
5322 final ProcessRecord addAppLocked(ApplicationInfo info) {
5323 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5324
5325 if (app == null) {
5326 app = newProcessRecordLocked(null, info, null);
5327 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005328 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 }
5330
5331 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5332 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5333 app.persistent = true;
5334 app.maxAdj = CORE_SERVER_ADJ;
5335 }
5336 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5337 mPersistentStartingProcesses.add(app);
5338 startProcessLocked(app, "added application", app.processName);
5339 }
5340
5341 return app;
5342 }
5343
5344 public void unhandledBack() {
5345 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5346 "unhandledBack()");
5347
5348 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005349 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005350 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005351 TAG, "Performing unhandledBack(): stack size = " + count);
5352 if (count > 1) {
5353 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005354 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5356 Binder.restoreCallingIdentity(origId);
5357 }
5358 }
5359 }
5360
5361 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5362 String name = uri.getAuthority();
5363 ContentProviderHolder cph = getContentProviderExternal(name);
5364 ParcelFileDescriptor pfd = null;
5365 if (cph != null) {
5366 // We record the binder invoker's uid in thread-local storage before
5367 // going to the content provider to open the file. Later, in the code
5368 // that handles all permissions checks, we look for this uid and use
5369 // that rather than the Activity Manager's own uid. The effect is that
5370 // we do the check against the caller's permissions even though it looks
5371 // to the content provider like the Activity Manager itself is making
5372 // the request.
5373 sCallerIdentity.set(new Identity(
5374 Binder.getCallingPid(), Binder.getCallingUid()));
5375 try {
5376 pfd = cph.provider.openFile(uri, "r");
5377 } catch (FileNotFoundException e) {
5378 // do nothing; pfd will be returned null
5379 } finally {
5380 // Ensure that whatever happens, we clean up the identity state
5381 sCallerIdentity.remove();
5382 }
5383
5384 // We've got the fd now, so we're done with the provider.
5385 removeContentProviderExternal(name);
5386 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005387 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 }
5389 return pfd;
5390 }
5391
5392 public void goingToSleep() {
5393 synchronized(this) {
5394 mSleeping = true;
5395 mWindowManager.setEventDispatching(false);
5396
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005397 if (mMainStack.mResumedActivity != null) {
5398 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005399 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005400 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005402
5403 // Initialize the wake times of all processes.
5404 checkExcessiveWakeLocksLocked(false);
5405 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5406 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5407 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 }
5409 }
5410
Dianne Hackborn55280a92009-05-07 15:53:46 -07005411 public boolean shutdown(int timeout) {
5412 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5413 != PackageManager.PERMISSION_GRANTED) {
5414 throw new SecurityException("Requires permission "
5415 + android.Manifest.permission.SHUTDOWN);
5416 }
5417
5418 boolean timedout = false;
5419
5420 synchronized(this) {
5421 mShuttingDown = true;
5422 mWindowManager.setEventDispatching(false);
5423
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005424 if (mMainStack.mResumedActivity != null) {
5425 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005426 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005427 while (mMainStack.mResumedActivity != null
5428 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005429 long delay = endTime - System.currentTimeMillis();
5430 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005431 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005432 timedout = true;
5433 break;
5434 }
5435 try {
5436 this.wait();
5437 } catch (InterruptedException e) {
5438 }
5439 }
5440 }
5441 }
5442
5443 mUsageStatsService.shutdown();
5444 mBatteryStatsService.shutdown();
5445
5446 return timedout;
5447 }
5448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 public void wakingUp() {
5450 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005451 if (mMainStack.mGoingToSleep.isHeld()) {
5452 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 }
5454 mWindowManager.setEventDispatching(true);
5455 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005456 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005457 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005458 }
5459 }
5460
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005461 public void stopAppSwitches() {
5462 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5463 != PackageManager.PERMISSION_GRANTED) {
5464 throw new SecurityException("Requires permission "
5465 + android.Manifest.permission.STOP_APP_SWITCHES);
5466 }
5467
5468 synchronized(this) {
5469 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5470 + APP_SWITCH_DELAY_TIME;
5471 mDidAppSwitch = false;
5472 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5473 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5474 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5475 }
5476 }
5477
5478 public void resumeAppSwitches() {
5479 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5480 != PackageManager.PERMISSION_GRANTED) {
5481 throw new SecurityException("Requires permission "
5482 + android.Manifest.permission.STOP_APP_SWITCHES);
5483 }
5484
5485 synchronized(this) {
5486 // Note that we don't execute any pending app switches... we will
5487 // let those wait until either the timeout, or the next start
5488 // activity request.
5489 mAppSwitchesAllowedTime = 0;
5490 }
5491 }
5492
5493 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5494 String name) {
5495 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5496 return true;
5497 }
5498
5499 final int perm = checkComponentPermission(
5500 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5501 callingUid, -1);
5502 if (perm == PackageManager.PERMISSION_GRANTED) {
5503 return true;
5504 }
5505
Joe Onorato8a9b2202010-02-26 18:56:32 -08005506 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005507 return false;
5508 }
5509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 public void setDebugApp(String packageName, boolean waitForDebugger,
5511 boolean persistent) {
5512 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5513 "setDebugApp()");
5514
5515 // Note that this is not really thread safe if there are multiple
5516 // callers into it at the same time, but that's not a situation we
5517 // care about.
5518 if (persistent) {
5519 final ContentResolver resolver = mContext.getContentResolver();
5520 Settings.System.putString(
5521 resolver, Settings.System.DEBUG_APP,
5522 packageName);
5523 Settings.System.putInt(
5524 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5525 waitForDebugger ? 1 : 0);
5526 }
5527
5528 synchronized (this) {
5529 if (!persistent) {
5530 mOrigDebugApp = mDebugApp;
5531 mOrigWaitForDebugger = mWaitForDebugger;
5532 }
5533 mDebugApp = packageName;
5534 mWaitForDebugger = waitForDebugger;
5535 mDebugTransient = !persistent;
5536 if (packageName != null) {
5537 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005538 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005539 Binder.restoreCallingIdentity(origId);
5540 }
5541 }
5542 }
5543
5544 public void setAlwaysFinish(boolean enabled) {
5545 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5546 "setAlwaysFinish()");
5547
5548 Settings.System.putInt(
5549 mContext.getContentResolver(),
5550 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5551
5552 synchronized (this) {
5553 mAlwaysFinishActivities = enabled;
5554 }
5555 }
5556
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005557 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005559 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005560 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005561 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005562 }
5563 }
5564
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005565 public boolean isUserAMonkey() {
5566 // For now the fact that there is a controller implies
5567 // we have a monkey.
5568 synchronized (this) {
5569 return mController != null;
5570 }
5571 }
5572
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005573 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005574 synchronized (this) {
5575 mWatchers.register(watcher);
5576 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005577 }
5578
5579 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005580 synchronized (this) {
5581 mWatchers.unregister(watcher);
5582 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005583 }
5584
Daniel Sandler69a48172010-06-23 16:29:36 -04005585 public void setImmersive(IBinder token, boolean immersive) {
5586 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005587 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005588 if (index < 0) {
5589 throw new IllegalArgumentException();
5590 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005591 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005592 r.immersive = immersive;
5593 }
5594 }
5595
5596 public boolean isImmersive(IBinder token) {
5597 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005598 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005599 if (index < 0) {
5600 throw new IllegalArgumentException();
5601 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005602 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005603 return r.immersive;
5604 }
5605 }
5606
5607 public boolean isTopActivityImmersive() {
5608 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005609 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005610 return (r != null) ? r.immersive : false;
5611 }
5612 }
5613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 public final void enterSafeMode() {
5615 synchronized(this) {
5616 // It only makes sense to do this before the system is ready
5617 // and started launching other packages.
5618 if (!mSystemReady) {
5619 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005620 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 } catch (RemoteException e) {
5622 }
5623
5624 View v = LayoutInflater.from(mContext).inflate(
5625 com.android.internal.R.layout.safe_mode, null);
5626 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5627 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5628 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5629 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5630 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5631 lp.format = v.getBackground().getOpacity();
5632 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5633 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5634 ((WindowManager)mContext.getSystemService(
5635 Context.WINDOW_SERVICE)).addView(v, lp);
5636 }
5637 }
5638 }
5639
5640 public void noteWakeupAlarm(IIntentSender sender) {
5641 if (!(sender instanceof PendingIntentRecord)) {
5642 return;
5643 }
5644 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5645 synchronized (stats) {
5646 if (mBatteryStatsService.isOnBattery()) {
5647 mBatteryStatsService.enforceCallingPermission();
5648 PendingIntentRecord rec = (PendingIntentRecord)sender;
5649 int MY_UID = Binder.getCallingUid();
5650 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5651 BatteryStatsImpl.Uid.Pkg pkg =
5652 stats.getPackageStatsLocked(uid, rec.key.packageName);
5653 pkg.incWakeupsLocked();
5654 }
5655 }
5656 }
5657
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005658 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005660 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005661 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005662 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005663 // XXX Note: don't acquire main activity lock here, because the window
5664 // manager calls in with its locks held.
5665
5666 boolean killed = false;
5667 synchronized (mPidsSelfLocked) {
5668 int[] types = new int[pids.length];
5669 int worstType = 0;
5670 for (int i=0; i<pids.length; i++) {
5671 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5672 if (proc != null) {
5673 int type = proc.setAdj;
5674 types[i] = type;
5675 if (type > worstType) {
5676 worstType = type;
5677 }
5678 }
5679 }
5680
5681 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5682 // then constrain it so we will kill all hidden procs.
5683 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5684 worstType = HIDDEN_APP_MIN_ADJ;
5685 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005686 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 for (int i=0; i<pids.length; i++) {
5688 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5689 if (proc == null) {
5690 continue;
5691 }
5692 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005693 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005694 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005695 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5696 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005697 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005698 proc.killedBackground = true;
5699 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 }
5701 }
5702 }
5703 return killed;
5704 }
5705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005706 public final void startRunning(String pkg, String cls, String action,
5707 String data) {
5708 synchronized(this) {
5709 if (mStartRunning) {
5710 return;
5711 }
5712 mStartRunning = true;
5713 mTopComponent = pkg != null && cls != null
5714 ? new ComponentName(pkg, cls) : null;
5715 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5716 mTopData = data;
5717 if (!mSystemReady) {
5718 return;
5719 }
5720 }
5721
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005722 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 }
5724
5725 private void retrieveSettings() {
5726 final ContentResolver resolver = mContext.getContentResolver();
5727 String debugApp = Settings.System.getString(
5728 resolver, Settings.System.DEBUG_APP);
5729 boolean waitForDebugger = Settings.System.getInt(
5730 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5731 boolean alwaysFinishActivities = Settings.System.getInt(
5732 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5733
5734 Configuration configuration = new Configuration();
5735 Settings.System.getConfiguration(resolver, configuration);
5736
5737 synchronized (this) {
5738 mDebugApp = mOrigDebugApp = debugApp;
5739 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5740 mAlwaysFinishActivities = alwaysFinishActivities;
5741 // This happens before any activities are started, so we can
5742 // change mConfiguration in-place.
5743 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005744 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005745 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005746 }
5747 }
5748
5749 public boolean testIsSystemReady() {
5750 // no need to synchronize(this) just to read & return the value
5751 return mSystemReady;
5752 }
5753
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005754 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005755 // In the simulator, startRunning will never have been called, which
5756 // normally sets a few crucial variables. Do it here instead.
5757 if (!Process.supportsProcesses()) {
5758 mStartRunning = true;
5759 mTopAction = Intent.ACTION_MAIN;
5760 }
5761
5762 synchronized(this) {
5763 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005764 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 return;
5766 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005767
5768 // Check to see if there are any update receivers to run.
5769 if (!mDidUpdate) {
5770 if (mWaitingUpdate) {
5771 return;
5772 }
5773 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5774 List<ResolveInfo> ris = null;
5775 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005776 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005777 intent, null, 0);
5778 } catch (RemoteException e) {
5779 }
5780 if (ris != null) {
5781 for (int i=ris.size()-1; i>=0; i--) {
5782 if ((ris.get(i).activityInfo.applicationInfo.flags
5783 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5784 ris.remove(i);
5785 }
5786 }
5787 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5788 for (int i=0; i<ris.size(); i++) {
5789 ActivityInfo ai = ris.get(i).activityInfo;
5790 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5791 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005792 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005793 finisher = new IIntentReceiver.Stub() {
5794 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005795 String data, Bundle extras, boolean ordered,
5796 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005797 throws RemoteException {
5798 synchronized (ActivityManagerService.this) {
5799 mDidUpdate = true;
5800 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005801 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005802 }
5803 };
5804 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005805 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005806 broadcastIntentLocked(null, null, intent, null, finisher,
5807 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005808 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005809 mWaitingUpdate = true;
5810 }
5811 }
5812 }
5813 if (mWaitingUpdate) {
5814 return;
5815 }
5816 mDidUpdate = true;
5817 }
5818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 mSystemReady = true;
5820 if (!mStartRunning) {
5821 return;
5822 }
5823 }
5824
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005825 ArrayList<ProcessRecord> procsToKill = null;
5826 synchronized(mPidsSelfLocked) {
5827 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5828 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5829 if (!isAllowedWhileBooting(proc.info)){
5830 if (procsToKill == null) {
5831 procsToKill = new ArrayList<ProcessRecord>();
5832 }
5833 procsToKill.add(proc);
5834 }
5835 }
5836 }
5837
5838 if (procsToKill != null) {
5839 synchronized(this) {
5840 for (int i=procsToKill.size()-1; i>=0; i--) {
5841 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005842 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005843 removeProcessLocked(proc, true);
5844 }
5845 }
5846 }
5847
Joe Onorato8a9b2202010-02-26 18:56:32 -08005848 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005849 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005850 SystemClock.uptimeMillis());
5851
5852 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005853 // Make sure we have no pre-ready processes sitting around.
5854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005855 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5856 ResolveInfo ri = mContext.getPackageManager()
5857 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005858 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005859 CharSequence errorMsg = null;
5860 if (ri != null) {
5861 ActivityInfo ai = ri.activityInfo;
5862 ApplicationInfo app = ai.applicationInfo;
5863 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5864 mTopAction = Intent.ACTION_FACTORY_TEST;
5865 mTopData = null;
5866 mTopComponent = new ComponentName(app.packageName,
5867 ai.name);
5868 } else {
5869 errorMsg = mContext.getResources().getText(
5870 com.android.internal.R.string.factorytest_not_system);
5871 }
5872 } else {
5873 errorMsg = mContext.getResources().getText(
5874 com.android.internal.R.string.factorytest_no_action);
5875 }
5876 if (errorMsg != null) {
5877 mTopAction = null;
5878 mTopData = null;
5879 mTopComponent = null;
5880 Message msg = Message.obtain();
5881 msg.what = SHOW_FACTORY_ERROR_MSG;
5882 msg.getData().putCharSequence("msg", errorMsg);
5883 mHandler.sendMessage(msg);
5884 }
5885 }
5886 }
5887
5888 retrieveSettings();
5889
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005890 if (goingCallback != null) goingCallback.run();
5891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005892 synchronized (this) {
5893 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5894 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005895 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005896 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 if (apps != null) {
5898 int N = apps.size();
5899 int i;
5900 for (i=0; i<N; i++) {
5901 ApplicationInfo info
5902 = (ApplicationInfo)apps.get(i);
5903 if (info != null &&
5904 !info.packageName.equals("android")) {
5905 addAppLocked(info);
5906 }
5907 }
5908 }
5909 } catch (RemoteException ex) {
5910 // pm is in same process, this will never happen.
5911 }
5912 }
5913
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005914 // Start up initial activity.
5915 mBooting = true;
5916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005918 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005919 Message msg = Message.obtain();
5920 msg.what = SHOW_UID_ERROR_MSG;
5921 mHandler.sendMessage(msg);
5922 }
5923 } catch (RemoteException e) {
5924 }
5925
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005926 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005927 }
5928 }
5929
Dan Egnorb7f03672009-12-09 16:22:32 -08005930 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005931 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005933 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005934 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 startAppProblemLocked(app);
5936 app.stopFreezingAllLocked();
5937 return handleAppCrashLocked(app);
5938 }
5939
Dan Egnorb7f03672009-12-09 16:22:32 -08005940 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005941 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005942 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005943 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005944 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
5945 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005946 startAppProblemLocked(app);
5947 app.stopFreezingAllLocked();
5948 }
5949
5950 /**
5951 * Generate a process error record, suitable for attachment to a ProcessRecord.
5952 *
5953 * @param app The ProcessRecord in which the error occurred.
5954 * @param condition Crashing, Application Not Responding, etc. Values are defined in
5955 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08005956 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 * @param shortMsg Short message describing the crash.
5958 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08005959 * @param stackTrace Full crash stack trace, may be null.
5960 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005961 * @return Returns a fully-formed AppErrorStateInfo record.
5962 */
5963 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005964 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08005966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005967 report.condition = condition;
5968 report.processName = app.processName;
5969 report.pid = app.pid;
5970 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08005971 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005972 report.shortMsg = shortMsg;
5973 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08005974 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975
5976 return report;
5977 }
5978
Dan Egnor42471dd2010-01-07 17:25:22 -08005979 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005980 synchronized (this) {
5981 app.crashing = false;
5982 app.crashingReport = null;
5983 app.notResponding = false;
5984 app.notRespondingReport = null;
5985 if (app.anrDialog == fromDialog) {
5986 app.anrDialog = null;
5987 }
5988 if (app.waitDialog == fromDialog) {
5989 app.waitDialog = null;
5990 }
5991 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005992 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07005993 Slog.i(ActivityManagerService.TAG, "Killing "
5994 + app.processName + " (pid=" + app.pid + "): user's request");
5995 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
5996 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 Process.killProcess(app.pid);
5998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005999 }
6000 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006001
Dan Egnorb7f03672009-12-09 16:22:32 -08006002 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 long now = SystemClock.uptimeMillis();
6004
6005 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6006 app.info.uid);
6007 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6008 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006009 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006010 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006011 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 app.info.processName, app.info.uid);
6013 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006014 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6015 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006016 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006017 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006018 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006019 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 }
6021 }
6022 if (!app.persistent) {
6023 // We don't want to start this process again until the user
6024 // explicitly does so... but for persistent process, we really
6025 // need to keep it running. If a persistent process is actually
6026 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006027 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006028 app.info.processName);
6029 mBadProcesses.put(app.info.processName, app.info.uid, now);
6030 app.bad = true;
6031 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6032 app.removed = true;
6033 removeProcessLocked(app, false);
6034 return false;
6035 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006036 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006037 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006038 if (r.app == app) {
6039 // If the top running activity is from this crashing
6040 // process, then terminate it to avoid getting in a loop.
6041 Slog.w(TAG, " Force finishing activity "
6042 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006043 int index = mMainStack.indexOfTokenLocked(r);
6044 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006045 Activity.RESULT_CANCELED, null, "crashed");
6046 // Also terminate an activities below it that aren't yet
6047 // stopped, to avoid a situation where one will get
6048 // re-start our crashing activity once it gets resumed again.
6049 index--;
6050 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006051 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006052 if (r.state == ActivityState.RESUMED
6053 || r.state == ActivityState.PAUSING
6054 || r.state == ActivityState.PAUSED) {
6055 if (!r.isHomeActivity) {
6056 Slog.w(TAG, " Force finishing activity "
6057 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006058 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006059 Activity.RESULT_CANCELED, null, "crashed");
6060 }
6061 }
6062 }
6063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006064 }
6065
6066 // Bump up the crash count of any services currently running in the proc.
6067 if (app.services.size() != 0) {
6068 // Any services running in the application need to be placed
6069 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006070 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006071 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006072 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006073 sr.crashCount++;
6074 }
6075 }
6076
6077 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6078 return true;
6079 }
6080
6081 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006082 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6083 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 skipCurrentReceiverLocked(app);
6085 }
6086
6087 void skipCurrentReceiverLocked(ProcessRecord app) {
6088 boolean reschedule = false;
6089 BroadcastRecord r = app.curReceiver;
6090 if (r != null) {
6091 // The current broadcast is waiting for this app's receiver
6092 // to be finished. Looks like that's not going to happen, so
6093 // let the broadcast continue.
6094 logBroadcastReceiverDiscard(r);
6095 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6096 r.resultExtras, r.resultAbort, true);
6097 reschedule = true;
6098 }
6099 r = mPendingBroadcast;
6100 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006101 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 "skip & discard pending app " + r);
6103 logBroadcastReceiverDiscard(r);
6104 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6105 r.resultExtras, r.resultAbort, true);
6106 reschedule = true;
6107 }
6108 if (reschedule) {
6109 scheduleBroadcastsLocked();
6110 }
6111 }
6112
Dan Egnor60d87622009-12-16 16:32:58 -08006113 /**
6114 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6115 * The application process will exit immediately after this call returns.
6116 * @param app object of the crashing app, null for the system server
6117 * @param crashInfo describing the exception
6118 */
6119 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6120 ProcessRecord r = findAppProcess(app);
6121
6122 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6123 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006124 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006125 crashInfo.exceptionClassName,
6126 crashInfo.exceptionMessage,
6127 crashInfo.throwFileName,
6128 crashInfo.throwLineNumber);
6129
Dan Egnor42471dd2010-01-07 17:25:22 -08006130 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006131
6132 crashApplication(r, crashInfo);
6133 }
6134
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006135 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006136 IBinder app,
6137 int violationMask,
6138 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006139 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006140
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006141 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006142 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006143 boolean logIt = true;
6144 synchronized (mAlreadyLoggedViolatedStacks) {
6145 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6146 logIt = false;
6147 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006148 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006149 // the relative pain numbers, without logging all
6150 // the stack traces repeatedly. We'd want to do
6151 // likewise in the client code, which also does
6152 // dup suppression, before the Binder call.
6153 } else {
6154 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6155 mAlreadyLoggedViolatedStacks.clear();
6156 }
6157 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6158 }
6159 }
6160 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006161 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006162 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006163 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006164
6165 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6166 AppErrorResult result = new AppErrorResult();
6167 synchronized (this) {
6168 final long origId = Binder.clearCallingIdentity();
6169
6170 Message msg = Message.obtain();
6171 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6172 HashMap<String, Object> data = new HashMap<String, Object>();
6173 data.put("result", result);
6174 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006175 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006176 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006177 msg.obj = data;
6178 mHandler.sendMessage(msg);
6179
6180 Binder.restoreCallingIdentity(origId);
6181 }
6182 int res = result.get();
6183 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
6184 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006185 }
6186
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006187 // Depending on the policy in effect, there could be a bunch of
6188 // these in quick succession so we try to batch these together to
6189 // minimize disk writes, number of dropbox entries, and maximize
6190 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006191 private void logStrictModeViolationToDropBox(
6192 ProcessRecord process,
6193 StrictMode.ViolationInfo info) {
6194 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006195 return;
6196 }
6197 final boolean isSystemApp = process == null ||
6198 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6199 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6200 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6201 final DropBoxManager dbox = (DropBoxManager)
6202 mContext.getSystemService(Context.DROPBOX_SERVICE);
6203
6204 // Exit early if the dropbox isn't configured to accept this report type.
6205 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6206
6207 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006208 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006209 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6210 synchronized (sb) {
6211 bufferWasEmpty = sb.length() == 0;
6212 appendDropBoxProcessHeaders(process, sb);
6213 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6214 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006215 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6216 if (info.violationNumThisLoop != 0) {
6217 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6218 }
6219 if (info != null && info.durationMillis != -1) {
6220 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006221 }
6222 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006223 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6224 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006225 }
6226 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006227
6228 // Only buffer up to ~64k. Various logging bits truncate
6229 // things at 128k.
6230 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006231 }
6232
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006233 // Flush immediately if the buffer's grown too large, or this
6234 // is a non-system app. Non-system apps are isolated with a
6235 // different tag & policy and not batched.
6236 //
6237 // Batching is useful during internal testing with
6238 // StrictMode settings turned up high. Without batching,
6239 // thousands of separate files could be created on boot.
6240 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006241 new Thread("Error dump: " + dropboxTag) {
6242 @Override
6243 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006244 String report;
6245 synchronized (sb) {
6246 report = sb.toString();
6247 sb.delete(0, sb.length());
6248 sb.trimToSize();
6249 }
6250 if (report.length() != 0) {
6251 dbox.addText(dropboxTag, report);
6252 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006253 }
6254 }.start();
6255 return;
6256 }
6257
6258 // System app batching:
6259 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006260 // An existing dropbox-writing thread is outstanding, so
6261 // we don't need to start it up. The existing thread will
6262 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006263 return;
6264 }
6265
6266 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6267 // (After this point, we shouldn't access AMS internal data structures.)
6268 new Thread("Error dump: " + dropboxTag) {
6269 @Override
6270 public void run() {
6271 // 5 second sleep to let stacks arrive and be batched together
6272 try {
6273 Thread.sleep(5000); // 5 seconds
6274 } catch (InterruptedException e) {}
6275
6276 String errorReport;
6277 synchronized (mStrictModeBuffer) {
6278 errorReport = mStrictModeBuffer.toString();
6279 if (errorReport.length() == 0) {
6280 return;
6281 }
6282 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6283 mStrictModeBuffer.trimToSize();
6284 }
6285 dbox.addText(dropboxTag, errorReport);
6286 }
6287 }.start();
6288 }
6289
Dan Egnor60d87622009-12-16 16:32:58 -08006290 /**
6291 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6292 * @param app object of the crashing app, null for the system server
6293 * @param tag reported by the caller
6294 * @param crashInfo describing the context of the error
6295 * @return true if the process should exit immediately (WTF is fatal)
6296 */
6297 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006298 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006299 ProcessRecord r = findAppProcess(app);
6300
6301 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6302 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006303 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006304 tag, crashInfo.exceptionMessage);
6305
Dan Egnor42471dd2010-01-07 17:25:22 -08006306 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006307
Doug Zongker43866e02010-01-07 12:09:54 -08006308 if (Settings.Secure.getInt(mContext.getContentResolver(),
6309 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006310 crashApplication(r, crashInfo);
6311 return true;
6312 } else {
6313 return false;
6314 }
6315 }
6316
6317 /**
6318 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6319 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6320 */
6321 private ProcessRecord findAppProcess(IBinder app) {
6322 if (app == null) {
6323 return null;
6324 }
6325
6326 synchronized (this) {
6327 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6328 final int NA = apps.size();
6329 for (int ia=0; ia<NA; ia++) {
6330 ProcessRecord p = apps.valueAt(ia);
6331 if (p.thread != null && p.thread.asBinder() == app) {
6332 return p;
6333 }
6334 }
6335 }
6336
Joe Onorato8a9b2202010-02-26 18:56:32 -08006337 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006338 return null;
6339 }
6340 }
6341
6342 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006343 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6344 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006345 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006346 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006347 if (process == null || process.pid == MY_PID) {
6348 sb.append("Process: system_server\n");
6349 } else {
6350 sb.append("Process: ").append(process.processName).append("\n");
6351 }
6352 if (process != null) {
6353 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006354 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006355 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6356 for (String pkg : process.pkgList) {
6357 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006358 try {
Dan Egnora455d192010-03-12 08:52:28 -08006359 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6360 if (pi != null) {
6361 sb.append(" v").append(pi.versionCode);
6362 if (pi.versionName != null) {
6363 sb.append(" (").append(pi.versionName).append(")");
6364 }
6365 }
6366 } catch (RemoteException e) {
6367 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006368 }
Dan Egnora455d192010-03-12 08:52:28 -08006369 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006370 }
Dan Egnora455d192010-03-12 08:52:28 -08006371 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006372 }
6373
6374 private static String processClass(ProcessRecord process) {
6375 if (process == null || process.pid == MY_PID) {
6376 return "system_server";
6377 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6378 return "system_app";
6379 } else {
6380 return "data_app";
6381 }
6382 }
6383
6384 /**
6385 * Write a description of an error (crash, WTF, ANR) to the drop box.
6386 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6387 * @param process which caused the error, null means the system server
6388 * @param activity which triggered the error, null if unknown
6389 * @param parent activity related to the error, null if unknown
6390 * @param subject line related to the error, null if absent
6391 * @param report in long form describing the error, null if absent
6392 * @param logFile to include in the report, null if none
6393 * @param crashInfo giving an application stack trace, null if absent
6394 */
6395 public void addErrorToDropBox(String eventType,
6396 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6397 final String report, final File logFile,
6398 final ApplicationErrorReport.CrashInfo crashInfo) {
6399 // NOTE -- this must never acquire the ActivityManagerService lock,
6400 // otherwise the watchdog may be prevented from resetting the system.
6401
6402 final String dropboxTag = processClass(process) + "_" + eventType;
6403 final DropBoxManager dbox = (DropBoxManager)
6404 mContext.getSystemService(Context.DROPBOX_SERVICE);
6405
6406 // Exit early if the dropbox isn't configured to accept this report type.
6407 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6408
6409 final StringBuilder sb = new StringBuilder(1024);
6410 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006411 if (activity != null) {
6412 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6413 }
6414 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6415 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6416 }
6417 if (parent != null && parent != activity) {
6418 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6419 }
6420 if (subject != null) {
6421 sb.append("Subject: ").append(subject).append("\n");
6422 }
6423 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6424 sb.append("\n");
6425
6426 // Do the rest in a worker thread to avoid blocking the caller on I/O
6427 // (After this point, we shouldn't access AMS internal data structures.)
6428 Thread worker = new Thread("Error dump: " + dropboxTag) {
6429 @Override
6430 public void run() {
6431 if (report != null) {
6432 sb.append(report);
6433 }
6434 if (logFile != null) {
6435 try {
6436 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6437 } catch (IOException e) {
6438 Slog.e(TAG, "Error reading " + logFile, e);
6439 }
6440 }
6441 if (crashInfo != null && crashInfo.stackTrace != null) {
6442 sb.append(crashInfo.stackTrace);
6443 }
6444
6445 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6446 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6447 if (lines > 0) {
6448 sb.append("\n");
6449
6450 // Merge several logcat streams, and take the last N lines
6451 InputStreamReader input = null;
6452 try {
6453 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6454 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6455 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6456
6457 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6458 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6459 input = new InputStreamReader(logcat.getInputStream());
6460
6461 int num;
6462 char[] buf = new char[8192];
6463 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6464 } catch (IOException e) {
6465 Slog.e(TAG, "Error running logcat", e);
6466 } finally {
6467 if (input != null) try { input.close(); } catch (IOException e) {}
6468 }
6469 }
6470
6471 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006472 }
Dan Egnora455d192010-03-12 08:52:28 -08006473 };
6474
6475 if (process == null || process.pid == MY_PID) {
6476 worker.run(); // We may be about to die -- need to run this synchronously
6477 } else {
6478 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006479 }
6480 }
6481
6482 /**
6483 * Bring up the "unexpected error" dialog box for a crashing app.
6484 * Deal with edge cases (intercepts from instrumented applications,
6485 * ActivityController, error intent receivers, that sort of thing).
6486 * @param r the application crashing
6487 * @param crashInfo describing the failure
6488 */
6489 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006490 long timeMillis = System.currentTimeMillis();
6491 String shortMsg = crashInfo.exceptionClassName;
6492 String longMsg = crashInfo.exceptionMessage;
6493 String stackTrace = crashInfo.stackTrace;
6494 if (shortMsg != null && longMsg != null) {
6495 longMsg = shortMsg + ": " + longMsg;
6496 } else if (shortMsg != null) {
6497 longMsg = shortMsg;
6498 }
6499
Dan Egnor60d87622009-12-16 16:32:58 -08006500 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006501 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006502 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 try {
6504 String name = r != null ? r.processName : null;
6505 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006506 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006507 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006508 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006509 + " at watcher's request");
6510 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006511 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006512 }
6513 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006514 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 }
6516 }
6517
6518 final long origId = Binder.clearCallingIdentity();
6519
6520 // If this process is running instrumentation, finish it.
6521 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006522 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006524 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6525 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006526 Bundle info = new Bundle();
6527 info.putString("shortMsg", shortMsg);
6528 info.putString("longMsg", longMsg);
6529 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6530 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006531 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006532 }
6533
Dan Egnor60d87622009-12-16 16:32:58 -08006534 // If we can't identify the process or it's already exceeded its crash quota,
6535 // quit right away without showing a crash dialog.
6536 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006537 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006538 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 }
6540
6541 Message msg = Message.obtain();
6542 msg.what = SHOW_ERROR_MSG;
6543 HashMap data = new HashMap();
6544 data.put("result", result);
6545 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006546 msg.obj = data;
6547 mHandler.sendMessage(msg);
6548
6549 Binder.restoreCallingIdentity(origId);
6550 }
6551
6552 int res = result.get();
6553
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006554 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006555 synchronized (this) {
6556 if (r != null) {
6557 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6558 SystemClock.uptimeMillis());
6559 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006560 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006561 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006562 }
6563 }
6564
6565 if (appErrorIntent != null) {
6566 try {
6567 mContext.startActivity(appErrorIntent);
6568 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006569 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006572 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006573
6574 Intent createAppErrorIntentLocked(ProcessRecord r,
6575 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6576 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006577 if (report == null) {
6578 return null;
6579 }
6580 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6581 result.setComponent(r.errorReportReceiver);
6582 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6583 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6584 return result;
6585 }
6586
Dan Egnorb7f03672009-12-09 16:22:32 -08006587 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6588 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006589 if (r.errorReportReceiver == null) {
6590 return null;
6591 }
6592
6593 if (!r.crashing && !r.notResponding) {
6594 return null;
6595 }
6596
Dan Egnorb7f03672009-12-09 16:22:32 -08006597 ApplicationErrorReport report = new ApplicationErrorReport();
6598 report.packageName = r.info.packageName;
6599 report.installerPackageName = r.errorReportReceiver.getPackageName();
6600 report.processName = r.processName;
6601 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006602 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006603
Dan Egnorb7f03672009-12-09 16:22:32 -08006604 if (r.crashing) {
6605 report.type = ApplicationErrorReport.TYPE_CRASH;
6606 report.crashInfo = crashInfo;
6607 } else if (r.notResponding) {
6608 report.type = ApplicationErrorReport.TYPE_ANR;
6609 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006610
Dan Egnorb7f03672009-12-09 16:22:32 -08006611 report.anrInfo.activity = r.notRespondingReport.tag;
6612 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6613 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006614 }
6615
Dan Egnorb7f03672009-12-09 16:22:32 -08006616 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006617 }
6618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6620 // assume our apps are happy - lazy create the list
6621 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6622
6623 synchronized (this) {
6624
6625 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006626 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6627 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6629 // This one's in trouble, so we'll generate a report for it
6630 // crashes are higher priority (in case there's a crash *and* an anr)
6631 ActivityManager.ProcessErrorStateInfo report = null;
6632 if (app.crashing) {
6633 report = app.crashingReport;
6634 } else if (app.notResponding) {
6635 report = app.notRespondingReport;
6636 }
6637
6638 if (report != null) {
6639 if (errList == null) {
6640 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6641 }
6642 errList.add(report);
6643 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006644 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006645 " crashing = " + app.crashing +
6646 " notResponding = " + app.notResponding);
6647 }
6648 }
6649 }
6650 }
6651
6652 return errList;
6653 }
6654
6655 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6656 // Lazy instantiation of list
6657 List<ActivityManager.RunningAppProcessInfo> runList = null;
6658 synchronized (this) {
6659 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006660 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6661 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6663 // Generate process state info for running application
6664 ActivityManager.RunningAppProcessInfo currApp =
6665 new ActivityManager.RunningAppProcessInfo(app.processName,
6666 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006667 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006668 if (mHeavyWeightProcess == app) {
6669 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006671 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006672 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006673 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6674 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6675 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006676 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6677 } else if (adj >= HOME_APP_ADJ) {
6678 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6679 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006680 } else if (adj >= SECONDARY_SERVER_ADJ) {
6681 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006682 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6683 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6684 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6685 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006686 } else if (adj >= VISIBLE_APP_ADJ) {
6687 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6688 } else {
6689 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6690 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006691 currApp.importanceReasonCode = app.adjTypeCode;
6692 if (app.adjSource instanceof ProcessRecord) {
6693 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006694 } else if (app.adjSource instanceof ActivityRecord) {
6695 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006696 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6697 }
6698 if (app.adjTarget instanceof ComponentName) {
6699 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6700 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006701 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 // + " lru=" + currApp.lru);
6703 if (runList == null) {
6704 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6705 }
6706 runList.add(currApp);
6707 }
6708 }
6709 }
6710 return runList;
6711 }
6712
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006713 public List<ApplicationInfo> getRunningExternalApplications() {
6714 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6715 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6716 if (runningApps != null && runningApps.size() > 0) {
6717 Set<String> extList = new HashSet<String>();
6718 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6719 if (app.pkgList != null) {
6720 for (String pkg : app.pkgList) {
6721 extList.add(pkg);
6722 }
6723 }
6724 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006725 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006726 for (String pkg : extList) {
6727 try {
6728 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6729 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6730 retList.add(info);
6731 }
6732 } catch (RemoteException e) {
6733 }
6734 }
6735 }
6736 return retList;
6737 }
6738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006739 @Override
6740 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006741 if (checkCallingPermission(android.Manifest.permission.DUMP)
6742 != PackageManager.PERMISSION_GRANTED) {
6743 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6744 + Binder.getCallingPid()
6745 + ", uid=" + Binder.getCallingUid()
6746 + " without permission "
6747 + android.Manifest.permission.DUMP);
6748 return;
6749 }
6750
6751 boolean dumpAll = false;
6752
6753 int opti = 0;
6754 while (opti < args.length) {
6755 String opt = args[opti];
6756 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6757 break;
6758 }
6759 opti++;
6760 if ("-a".equals(opt)) {
6761 dumpAll = true;
6762 } else if ("-h".equals(opt)) {
6763 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006764 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006765 pw.println(" cmd may be one of:");
6766 pw.println(" activities: activity stack state");
6767 pw.println(" broadcasts: broadcast state");
6768 pw.println(" intents: pending intent state");
6769 pw.println(" processes: process state");
6770 pw.println(" providers: content provider state");
6771 pw.println(" services: service state");
6772 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006773 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006774 } else {
6775 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006777 }
6778
6779 // Is the caller requesting to dump a particular piece of data?
6780 if (opti < args.length) {
6781 String cmd = args[opti];
6782 opti++;
6783 if ("activities".equals(cmd) || "a".equals(cmd)) {
6784 synchronized (this) {
6785 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006787 return;
6788 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6789 synchronized (this) {
6790 dumpBroadcastsLocked(fd, pw, args, opti, true);
6791 }
6792 return;
6793 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6794 synchronized (this) {
6795 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6796 }
6797 return;
6798 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6799 synchronized (this) {
6800 dumpProcessesLocked(fd, pw, args, opti, true);
6801 }
6802 return;
6803 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6804 synchronized (this) {
6805 dumpProvidersLocked(fd, pw, args, opti, true);
6806 }
6807 return;
6808 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006809 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006810 return;
6811 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6812 synchronized (this) {
6813 dumpServicesLocked(fd, pw, args, opti, true);
6814 }
6815 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006816 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006817 }
6818
6819 // No piece of data specified, dump everything.
6820 synchronized (this) {
6821 boolean needSep;
6822 if (dumpAll) {
6823 pw.println("Providers in Current Activity Manager State:");
6824 }
6825 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6826 if (needSep) {
6827 pw.println(" ");
6828 }
6829 if (dumpAll) {
6830 pw.println("-------------------------------------------------------------------------------");
6831 pw.println("Broadcasts in Current Activity Manager State:");
6832 }
6833 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6834 if (needSep) {
6835 pw.println(" ");
6836 }
6837 if (dumpAll) {
6838 pw.println("-------------------------------------------------------------------------------");
6839 pw.println("Services in Current Activity Manager State:");
6840 }
6841 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6842 if (needSep) {
6843 pw.println(" ");
6844 }
6845 if (dumpAll) {
6846 pw.println("-------------------------------------------------------------------------------");
6847 pw.println("PendingIntents in Current Activity Manager State:");
6848 }
6849 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6850 if (needSep) {
6851 pw.println(" ");
6852 }
6853 if (dumpAll) {
6854 pw.println("-------------------------------------------------------------------------------");
6855 pw.println("Activities in Current Activity Manager State:");
6856 }
6857 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6858 if (needSep) {
6859 pw.println(" ");
6860 }
6861 if (dumpAll) {
6862 pw.println("-------------------------------------------------------------------------------");
6863 pw.println("Processes in Current Activity Manager State:");
6864 }
6865 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6866 }
6867 }
6868
6869 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6870 int opti, boolean dumpAll, boolean needHeader) {
6871 if (needHeader) {
6872 pw.println(" Activity stack:");
6873 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006874 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006875 pw.println(" ");
6876 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006877 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6878 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006879 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006880 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006881 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006882 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006883 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006884 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006885 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006886 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006887 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006888 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006889 pw.println(" ");
6890 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006891 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006893
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006894 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006895 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
6896 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006897 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006898 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006899
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006900 if (dumpAll && mRecentTasks.size() > 0) {
6901 pw.println(" ");
6902 pw.println("Recent tasks in Current Activity Manager State:");
6903
6904 final int N = mRecentTasks.size();
6905 for (int i=0; i<N; i++) {
6906 TaskRecord tr = mRecentTasks.get(i);
6907 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
6908 pw.println(tr);
6909 mRecentTasks.get(i).dump(pw, " ");
6910 }
6911 }
6912
6913 pw.println(" ");
6914 pw.println(" mCurTask: " + mCurTask);
6915
6916 return true;
6917 }
6918
6919 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6920 int opti, boolean dumpAll) {
6921 boolean needSep = false;
6922 int numPers = 0;
6923
6924 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006925 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
6926 final int NA = procs.size();
6927 for (int ia=0; ia<NA; ia++) {
6928 if (!needSep) {
6929 pw.println(" All known processes:");
6930 needSep = true;
6931 }
6932 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006933 pw.print(r.persistent ? " *PERS*" : " *APP*");
6934 pw.print(" UID "); pw.print(procs.keyAt(ia));
6935 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006936 r.dump(pw, " ");
6937 if (r.persistent) {
6938 numPers++;
6939 }
6940 }
6941 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006942 }
6943
6944 if (mLruProcesses.size() > 0) {
6945 if (needSep) pw.println(" ");
6946 needSep = true;
6947 pw.println(" Running processes (most recent first):");
6948 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006949 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006950 needSep = true;
6951 }
6952
6953 synchronized (mPidsSelfLocked) {
6954 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006955 if (needSep) pw.println(" ");
6956 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006957 pw.println(" PID mappings:");
6958 for (int i=0; i<mPidsSelfLocked.size(); i++) {
6959 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
6960 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006961 }
6962 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006963 }
6964
6965 if (mForegroundProcesses.size() > 0) {
6966 if (needSep) pw.println(" ");
6967 needSep = true;
6968 pw.println(" Foreground Processes:");
6969 for (int i=0; i<mForegroundProcesses.size(); i++) {
6970 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
6971 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006973 }
6974
6975 if (mPersistentStartingProcesses.size() > 0) {
6976 if (needSep) pw.println(" ");
6977 needSep = true;
6978 pw.println(" Persisent processes that are starting:");
6979 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
6980 "Starting Norm", "Restarting PERS", false);
6981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006982
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006983 if (mStartingProcesses.size() > 0) {
6984 if (needSep) pw.println(" ");
6985 needSep = true;
6986 pw.println(" Processes that are starting:");
6987 dumpProcessList(pw, this, mStartingProcesses, " ",
6988 "Starting Norm", "Starting PERS", false);
6989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006990
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006991 if (mRemovedProcesses.size() > 0) {
6992 if (needSep) pw.println(" ");
6993 needSep = true;
6994 pw.println(" Processes that are being removed:");
6995 dumpProcessList(pw, this, mRemovedProcesses, " ",
6996 "Removed Norm", "Removed PERS", false);
6997 }
6998
6999 if (mProcessesOnHold.size() > 0) {
7000 if (needSep) pw.println(" ");
7001 needSep = true;
7002 pw.println(" Processes that are on old until the system is ready:");
7003 dumpProcessList(pw, this, mProcessesOnHold, " ",
7004 "OnHold Norm", "OnHold PERS", false);
7005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007007 if (mProcessesToGc.size() > 0) {
7008 if (needSep) pw.println(" ");
7009 needSep = true;
7010 pw.println(" Processes that are waiting to GC:");
7011 long now = SystemClock.uptimeMillis();
7012 for (int i=0; i<mProcessesToGc.size(); i++) {
7013 ProcessRecord proc = mProcessesToGc.get(i);
7014 pw.print(" Process "); pw.println(proc);
7015 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7016 pw.print(", last gced=");
7017 pw.print(now-proc.lastRequestedGc);
7018 pw.print(" ms ago, last lowMem=");
7019 pw.print(now-proc.lastLowMemory);
7020 pw.println(" ms ago");
7021
7022 }
7023 }
7024
7025 if (mProcessCrashTimes.getMap().size() > 0) {
7026 if (needSep) pw.println(" ");
7027 needSep = true;
7028 pw.println(" Time since processes crashed:");
7029 long now = SystemClock.uptimeMillis();
7030 for (Map.Entry<String, SparseArray<Long>> procs
7031 : mProcessCrashTimes.getMap().entrySet()) {
7032 SparseArray<Long> uids = procs.getValue();
7033 final int N = uids.size();
7034 for (int i=0; i<N; i++) {
7035 pw.print(" Process "); pw.print(procs.getKey());
7036 pw.print(" uid "); pw.print(uids.keyAt(i));
7037 pw.print(": last crashed ");
7038 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007039 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007040 }
7041 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007043
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007044 if (mBadProcesses.getMap().size() > 0) {
7045 if (needSep) pw.println(" ");
7046 needSep = true;
7047 pw.println(" Bad processes:");
7048 for (Map.Entry<String, SparseArray<Long>> procs
7049 : mBadProcesses.getMap().entrySet()) {
7050 SparseArray<Long> uids = procs.getValue();
7051 final int N = uids.size();
7052 for (int i=0; i<N; i++) {
7053 pw.print(" Bad process "); pw.print(procs.getKey());
7054 pw.print(" uid "); pw.print(uids.keyAt(i));
7055 pw.print(": crashed at time ");
7056 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007057 }
7058 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007061 pw.println(" ");
7062 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007063 if (mHeavyWeightProcess != null) {
7064 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7065 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007066 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007067 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007068 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7069 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7070 || mOrigWaitForDebugger) {
7071 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7072 + " mDebugTransient=" + mDebugTransient
7073 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7074 }
7075 if (mAlwaysFinishActivities || mController != null) {
7076 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7077 + " mController=" + mController);
7078 }
7079 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007080 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007081 pw.println(" mStartRunning=" + mStartRunning
7082 + " mSystemReady=" + mSystemReady
7083 + " mBooting=" + mBooting
7084 + " mBooted=" + mBooted
7085 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007086 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7087 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007088 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007090
7091 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 }
7093
7094 /**
7095 * There are three ways to call this:
7096 * - no service specified: dump all the services
7097 * - a flattened component name that matched an existing service was specified as the
7098 * first arg: dump that one service
7099 * - the first arg isn't the flattened component name of an existing service:
7100 * dump all services whose component contains the first arg as a substring
7101 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007102 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7103 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007104 String[] newArgs;
7105 String componentNameString;
7106 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007107 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007108 componentNameString = null;
7109 newArgs = EMPTY_STRING_ARRAY;
7110 r = null;
7111 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007112 componentNameString = args[opti];
7113 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007115 synchronized (this) {
7116 r = componentName != null ? mServices.get(componentName) : null;
7117 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007118 newArgs = new String[args.length - opti];
7119 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007120 }
7121
7122 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007123 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007124 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007125 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7126 synchronized (this) {
7127 for (ServiceRecord r1 : mServices.values()) {
7128 if (componentNameString == null
7129 || r1.name.flattenToString().contains(componentNameString)) {
7130 services.add(r1);
7131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007132 }
7133 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007134 for (int i=0; i<services.size(); i++) {
7135 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 }
7138 }
7139
7140 /**
7141 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7142 * there is a thread associated with the service.
7143 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007144 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7145 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007146 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007147 if (dumpAll) {
7148 synchronized (this) {
7149 pw.print(" * "); pw.println(r);
7150 r.dump(pw, " ");
7151 }
7152 pw.println("");
7153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007154 if (r.app != null && r.app.thread != null) {
7155 try {
7156 // flush anything that is already in the PrintWriter since the thread is going
7157 // to write to the file descriptor directly
7158 pw.flush();
7159 r.app.thread.dumpService(fd, r, args);
7160 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007161 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007162 } catch (RemoteException e) {
7163 pw.println("got a RemoteException while dumping the service");
7164 }
7165 }
7166 }
7167
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007168 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7169 int opti, boolean dumpAll) {
7170 boolean needSep = false;
7171
7172 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007173 if (mRegisteredReceivers.size() > 0) {
7174 pw.println(" ");
7175 pw.println(" Registered Receivers:");
7176 Iterator it = mRegisteredReceivers.values().iterator();
7177 while (it.hasNext()) {
7178 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007179 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180 r.dump(pw, " ");
7181 }
7182 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007184 pw.println(" ");
7185 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007186 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007187 needSep = true;
7188 }
7189
7190 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7191 || mPendingBroadcast != null) {
7192 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007193 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007194 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007195 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007196 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7197 pw.println(" Broadcast #" + i + ":");
7198 mParallelBroadcasts.get(i).dump(pw, " ");
7199 }
7200 if (mOrderedBroadcasts.size() > 0) {
7201 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007202 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007203 }
7204 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7205 pw.println(" Serialized Broadcast #" + i + ":");
7206 mOrderedBroadcasts.get(i).dump(pw, " ");
7207 }
7208 pw.println(" ");
7209 pw.println(" Pending broadcast:");
7210 if (mPendingBroadcast != null) {
7211 mPendingBroadcast.dump(pw, " ");
7212 } else {
7213 pw.println(" (null)");
7214 }
7215 needSep = true;
7216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007218 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007220 pw.println(" Historical broadcasts:");
7221 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7222 BroadcastRecord r = mBroadcastHistory[i];
7223 if (r == null) {
7224 break;
7225 }
7226 pw.println(" Historical Broadcast #" + i + ":");
7227 r.dump(pw, " ");
7228 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007229 needSep = true;
7230 }
7231
7232 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007233 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007234 pw.println(" Sticky broadcasts:");
7235 StringBuilder sb = new StringBuilder(128);
7236 for (Map.Entry<String, ArrayList<Intent>> ent
7237 : mStickyBroadcasts.entrySet()) {
7238 pw.print(" * Sticky action "); pw.print(ent.getKey());
7239 pw.println(":");
7240 ArrayList<Intent> intents = ent.getValue();
7241 final int N = intents.size();
7242 for (int i=0; i<N; i++) {
7243 sb.setLength(0);
7244 sb.append(" Intent: ");
7245 intents.get(i).toShortString(sb, true, false);
7246 pw.println(sb.toString());
7247 Bundle bundle = intents.get(i).getExtras();
7248 if (bundle != null) {
7249 pw.print(" ");
7250 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 }
7252 }
7253 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007254 needSep = true;
7255 }
7256
7257 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007258 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007259 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007260 pw.println(" mHandler:");
7261 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007262 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007263 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007264
7265 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 }
7267
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007268 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7269 int opti, boolean dumpAll) {
7270 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007272 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 if (mServices.size() > 0) {
7274 pw.println(" Active services:");
7275 Iterator<ServiceRecord> it = mServices.values().iterator();
7276 while (it.hasNext()) {
7277 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007278 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007279 r.dump(pw, " ");
7280 }
7281 needSep = true;
7282 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007284
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007285 if (mPendingServices.size() > 0) {
7286 if (needSep) pw.println(" ");
7287 pw.println(" Pending services:");
7288 for (int i=0; i<mPendingServices.size(); i++) {
7289 ServiceRecord r = mPendingServices.get(i);
7290 pw.print(" * Pending "); pw.println(r);
7291 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007292 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007293 needSep = true;
7294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007296 if (mRestartingServices.size() > 0) {
7297 if (needSep) pw.println(" ");
7298 pw.println(" Restarting services:");
7299 for (int i=0; i<mRestartingServices.size(); i++) {
7300 ServiceRecord r = mRestartingServices.get(i);
7301 pw.print(" * Restarting "); pw.println(r);
7302 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007303 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007304 needSep = true;
7305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007307 if (mStoppingServices.size() > 0) {
7308 if (needSep) pw.println(" ");
7309 pw.println(" Stopping services:");
7310 for (int i=0; i<mStoppingServices.size(); i++) {
7311 ServiceRecord r = mStoppingServices.get(i);
7312 pw.print(" * Stopping "); pw.println(r);
7313 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007315 needSep = true;
7316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007318 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319 if (mServiceConnections.size() > 0) {
7320 if (needSep) pw.println(" ");
7321 pw.println(" Connection bindings to services:");
7322 Iterator<ConnectionRecord> it
7323 = mServiceConnections.values().iterator();
7324 while (it.hasNext()) {
7325 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007326 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007327 r.dump(pw, " ");
7328 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007329 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007330 }
7331 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007332
7333 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007334 }
7335
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007336 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7337 int opti, boolean dumpAll) {
7338 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007340 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341 if (mProvidersByClass.size() > 0) {
7342 if (needSep) pw.println(" ");
7343 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007344 Iterator<Map.Entry<String, ContentProviderRecord>> it
7345 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007347 Map.Entry<String, ContentProviderRecord> e = it.next();
7348 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007349 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 r.dump(pw, " ");
7351 }
7352 needSep = true;
7353 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007354
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007355 if (mProvidersByName.size() > 0) {
7356 pw.println(" ");
7357 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007358 Iterator<Map.Entry<String, ContentProviderRecord>> it
7359 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007360 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007361 Map.Entry<String, ContentProviderRecord> e = it.next();
7362 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007363 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7364 pw.println(r);
7365 }
7366 needSep = true;
7367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007369
7370 if (mLaunchingProviders.size() > 0) {
7371 if (needSep) pw.println(" ");
7372 pw.println(" Launching content providers:");
7373 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7374 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7375 pw.println(mLaunchingProviders.get(i));
7376 }
7377 needSep = true;
7378 }
7379
7380 if (mGrantedUriPermissions.size() > 0) {
7381 pw.println();
7382 pw.println("Granted Uri Permissions:");
7383 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7384 int uid = mGrantedUriPermissions.keyAt(i);
7385 HashMap<Uri, UriPermission> perms
7386 = mGrantedUriPermissions.valueAt(i);
7387 pw.print(" * UID "); pw.print(uid);
7388 pw.println(" holds:");
7389 for (UriPermission perm : perms.values()) {
7390 pw.print(" "); pw.println(perm);
7391 perm.dump(pw, " ");
7392 }
7393 }
7394 needSep = true;
7395 }
7396
7397 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 }
7399
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007400 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7401 int opti, boolean dumpAll) {
7402 boolean needSep = false;
7403
7404 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007405 if (this.mIntentSenderRecords.size() > 0) {
7406 Iterator<WeakReference<PendingIntentRecord>> it
7407 = mIntentSenderRecords.values().iterator();
7408 while (it.hasNext()) {
7409 WeakReference<PendingIntentRecord> ref = it.next();
7410 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007411 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007412 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007413 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 rec.dump(pw, " ");
7415 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007416 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 }
7418 }
7419 }
7420 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007421
7422 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 }
7424
7425 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007426 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 TaskRecord lastTask = null;
7428 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007429 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007430 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 if (lastTask != r.task) {
7432 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007433 pw.print(prefix);
7434 pw.print(full ? "* " : " ");
7435 pw.println(lastTask);
7436 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007437 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007439 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007440 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7441 pw.print(" #"); pw.print(i); pw.print(": ");
7442 pw.println(r);
7443 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007444 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 }
7447 }
7448
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007449 private static String buildOomTag(String prefix, String space, int val, int base) {
7450 if (val == base) {
7451 if (space == null) return prefix;
7452 return prefix + " ";
7453 }
7454 return prefix + "+" + Integer.toString(val-base);
7455 }
7456
7457 private static final int dumpProcessList(PrintWriter pw,
7458 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007459 String prefix, String normalLabel, String persistentLabel,
7460 boolean inclOomAdj) {
7461 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007462 final int N = list.size()-1;
7463 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007464 ProcessRecord r = (ProcessRecord)list.get(i);
7465 if (false) {
7466 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7467 + " #" + i + ":");
7468 r.dump(pw, prefix + " ");
7469 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007470 String oomAdj;
7471 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007472 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007473 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007474 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7475 } else if (r.setAdj >= HOME_APP_ADJ) {
7476 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7477 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7478 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7479 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7480 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007481 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7482 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7483 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7484 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007485 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7486 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7487 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7488 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007489 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007490 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007491 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007492 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007493 } else {
7494 oomAdj = Integer.toString(r.setAdj);
7495 }
7496 String schedGroup;
7497 switch (r.setSchedGroup) {
7498 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7499 schedGroup = "B";
7500 break;
7501 case Process.THREAD_GROUP_DEFAULT:
7502 schedGroup = "F";
7503 break;
7504 default:
7505 schedGroup = Integer.toString(r.setSchedGroup);
7506 break;
7507 }
7508 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007509 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007510 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007511 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007512 pw.print(prefix);
7513 pw.print(" ");
7514 if (r.adjTarget instanceof ComponentName) {
7515 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7516 } else if (r.adjTarget != null) {
7517 pw.print(r.adjTarget.toString());
7518 } else {
7519 pw.print("{null}");
7520 }
7521 pw.print("<=");
7522 if (r.adjSource instanceof ProcessRecord) {
7523 pw.print("Proc{");
7524 pw.print(((ProcessRecord)r.adjSource).toShortString());
7525 pw.println("}");
7526 } else if (r.adjSource != null) {
7527 pw.println(r.adjSource.toString());
7528 } else {
7529 pw.println("{null}");
7530 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007532 } else {
7533 pw.println(String.format("%s%s #%2d: %s",
7534 prefix, (r.persistent ? persistentLabel : normalLabel),
7535 i, r.toString()));
7536 }
7537 if (r.persistent) {
7538 numPers++;
7539 }
7540 }
7541 return numPers;
7542 }
7543
Dianne Hackborn472ad872010-04-07 17:31:48 -07007544 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007546 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007547 long uptime = SystemClock.uptimeMillis();
7548 long realtime = SystemClock.elapsedRealtime();
7549
7550 if (isCheckinRequest) {
7551 // short checkin version
7552 pw.println(uptime + "," + realtime);
7553 pw.flush();
7554 } else {
7555 pw.println("Applications Memory Usage (kB):");
7556 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7557 }
7558 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7559 ProcessRecord r = (ProcessRecord)list.get(i);
7560 if (r.thread != null) {
7561 if (!isCheckinRequest) {
7562 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7563 pw.flush();
7564 }
7565 try {
7566 r.thread.asBinder().dump(fd, args);
7567 } catch (RemoteException e) {
7568 if (!isCheckinRequest) {
7569 pw.println("Got RemoteException!");
7570 pw.flush();
7571 }
7572 }
7573 }
7574 }
7575 }
7576
7577 /**
7578 * Searches array of arguments for the specified string
7579 * @param args array of argument strings
7580 * @param value value to search for
7581 * @return true if the value is contained in the array
7582 */
7583 private static boolean scanArgs(String[] args, String value) {
7584 if (args != null) {
7585 for (String arg : args) {
7586 if (value.equals(arg)) {
7587 return true;
7588 }
7589 }
7590 }
7591 return false;
7592 }
7593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594 private final void killServicesLocked(ProcessRecord app,
7595 boolean allowRestart) {
7596 // Report disconnected services.
7597 if (false) {
7598 // XXX we are letting the client link to the service for
7599 // death notifications.
7600 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007601 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007602 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007603 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604 if (r.connections.size() > 0) {
7605 Iterator<ConnectionRecord> jt
7606 = r.connections.values().iterator();
7607 while (jt.hasNext()) {
7608 ConnectionRecord c = jt.next();
7609 if (c.binding.client != app) {
7610 try {
7611 //c.conn.connected(r.className, null);
7612 } catch (Exception e) {
7613 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007614 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 + r.shortName
7616 + " from app " + app.processName, e);
7617 }
7618 }
7619 }
7620 }
7621 }
7622 }
7623 }
7624
7625 // Clean up any connections this application has to other services.
7626 if (app.connections.size() > 0) {
7627 Iterator<ConnectionRecord> it = app.connections.iterator();
7628 while (it.hasNext()) {
7629 ConnectionRecord r = it.next();
7630 removeConnectionLocked(r, app, null);
7631 }
7632 }
7633 app.connections.clear();
7634
7635 if (app.services.size() != 0) {
7636 // Any services running in the application need to be placed
7637 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007638 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007639 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007640 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 synchronized (sr.stats.getBatteryStats()) {
7642 sr.stats.stopLaunchedLocked();
7643 }
7644 sr.app = null;
7645 sr.executeNesting = 0;
7646 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007647
7648 boolean hasClients = sr.bindings.size() > 0;
7649 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 Iterator<IntentBindRecord> bindings
7651 = sr.bindings.values().iterator();
7652 while (bindings.hasNext()) {
7653 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007654 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007655 + ": shouldUnbind=" + b.hasBound);
7656 b.binder = null;
7657 b.requested = b.received = b.hasBound = false;
7658 }
7659 }
7660
7661 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007662 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007663 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007664 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 sr.crashCount, sr.shortName, app.pid);
7666 bringDownServiceLocked(sr, true);
7667 } else if (!allowRestart) {
7668 bringDownServiceLocked(sr, true);
7669 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007670 boolean canceled = scheduleServiceRestartLocked(sr, true);
7671
7672 // Should the service remain running? Note that in the
7673 // extreme case of so many attempts to deliver a command
7674 // that it failed, that we also will stop it here.
7675 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7676 if (sr.pendingStarts.size() == 0) {
7677 sr.startRequested = false;
7678 if (!hasClients) {
7679 // Whoops, no reason to restart!
7680 bringDownServiceLocked(sr, true);
7681 }
7682 }
7683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 }
7685 }
7686
7687 if (!allowRestart) {
7688 app.services.clear();
7689 }
7690 }
7691
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007692 // Make sure we have no more records on the stopping list.
7693 int i = mStoppingServices.size();
7694 while (i > 0) {
7695 i--;
7696 ServiceRecord sr = mStoppingServices.get(i);
7697 if (sr.app == app) {
7698 mStoppingServices.remove(i);
7699 }
7700 }
7701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702 app.executingServices.clear();
7703 }
7704
7705 private final void removeDyingProviderLocked(ProcessRecord proc,
7706 ContentProviderRecord cpr) {
7707 synchronized (cpr) {
7708 cpr.launchingApp = null;
7709 cpr.notifyAll();
7710 }
7711
7712 mProvidersByClass.remove(cpr.info.name);
7713 String names[] = cpr.info.authority.split(";");
7714 for (int j = 0; j < names.length; j++) {
7715 mProvidersByName.remove(names[j]);
7716 }
7717
7718 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7719 while (cit.hasNext()) {
7720 ProcessRecord capp = cit.next();
7721 if (!capp.persistent && capp.thread != null
7722 && capp.pid != 0
7723 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007724 Slog.i(TAG, "Kill " + capp.processName
7725 + " (pid " + capp.pid + "): provider " + cpr.info.name
7726 + " in dying process " + proc.processName);
7727 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7728 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 Process.killProcess(capp.pid);
7730 }
7731 }
7732
7733 mLaunchingProviders.remove(cpr);
7734 }
7735
7736 /**
7737 * Main code for cleaning up a process when it has gone away. This is
7738 * called both as a result of the process dying, or directly when stopping
7739 * a process when running in single process mode.
7740 */
7741 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7742 boolean restarting, int index) {
7743 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007744 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007745 }
7746
Dianne Hackborn36124872009-10-08 16:22:03 -07007747 mProcessesToGc.remove(app);
7748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 // Dismiss any open dialogs.
7750 if (app.crashDialog != null) {
7751 app.crashDialog.dismiss();
7752 app.crashDialog = null;
7753 }
7754 if (app.anrDialog != null) {
7755 app.anrDialog.dismiss();
7756 app.anrDialog = null;
7757 }
7758 if (app.waitDialog != null) {
7759 app.waitDialog.dismiss();
7760 app.waitDialog = null;
7761 }
7762
7763 app.crashing = false;
7764 app.notResponding = false;
7765
7766 app.resetPackageList();
7767 app.thread = null;
7768 app.forcingToForeground = null;
7769 app.foregroundServices = false;
7770
7771 killServicesLocked(app, true);
7772
7773 boolean restart = false;
7774
7775 int NL = mLaunchingProviders.size();
7776
7777 // Remove published content providers.
7778 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007779 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007780 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007781 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 cpr.provider = null;
7783 cpr.app = null;
7784
7785 // See if someone is waiting for this provider... in which
7786 // case we don't remove it, but just let it restart.
7787 int i = 0;
7788 if (!app.bad) {
7789 for (; i<NL; i++) {
7790 if (mLaunchingProviders.get(i) == cpr) {
7791 restart = true;
7792 break;
7793 }
7794 }
7795 } else {
7796 i = NL;
7797 }
7798
7799 if (i >= NL) {
7800 removeDyingProviderLocked(app, cpr);
7801 NL = mLaunchingProviders.size();
7802 }
7803 }
7804 app.pubProviders.clear();
7805 }
7806
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007807 // Take care of any launching providers waiting for this process.
7808 if (checkAppInLaunchingProvidersLocked(app, false)) {
7809 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007812 // Unregister from connected content providers.
7813 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007814 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007815 while (it.hasNext()) {
7816 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7817 cpr.clients.remove(app);
7818 }
7819 app.conProviders.clear();
7820 }
7821
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007822 // At this point there may be remaining entries in mLaunchingProviders
7823 // where we were the only one waiting, so they are no longer of use.
7824 // Look for these and clean up if found.
7825 // XXX Commented out for now. Trying to figure out a way to reproduce
7826 // the actual situation to identify what is actually going on.
7827 if (false) {
7828 for (int i=0; i<NL; i++) {
7829 ContentProviderRecord cpr = (ContentProviderRecord)
7830 mLaunchingProviders.get(i);
7831 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7832 synchronized (cpr) {
7833 cpr.launchingApp = null;
7834 cpr.notifyAll();
7835 }
7836 }
7837 }
7838 }
7839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 skipCurrentReceiverLocked(app);
7841
7842 // Unregister any receivers.
7843 if (app.receivers.size() > 0) {
7844 Iterator<ReceiverList> it = app.receivers.iterator();
7845 while (it.hasNext()) {
7846 removeReceiverLocked(it.next());
7847 }
7848 app.receivers.clear();
7849 }
7850
Christopher Tate181fafa2009-05-14 11:12:14 -07007851 // If the app is undergoing backup, tell the backup manager about it
7852 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007853 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007854 try {
7855 IBackupManager bm = IBackupManager.Stub.asInterface(
7856 ServiceManager.getService(Context.BACKUP_SERVICE));
7857 bm.agentDisconnected(app.info.packageName);
7858 } catch (RemoteException e) {
7859 // can't happen; backup manager is local
7860 }
7861 }
7862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 // If the caller is restarting this app, then leave it in its
7864 // current lists and let the caller take care of it.
7865 if (restarting) {
7866 return;
7867 }
7868
7869 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007870 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007871 "Removing non-persistent process during cleanup: " + app);
7872 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007873 if (mHeavyWeightProcess == app) {
7874 mHeavyWeightProcess = null;
7875 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007877 } else if (!app.removed) {
7878 // This app is persistent, so we need to keep its record around.
7879 // If it is not already on the pending app list, add it there
7880 // and start a new process for it.
7881 app.thread = null;
7882 app.forcingToForeground = null;
7883 app.foregroundServices = false;
7884 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7885 mPersistentStartingProcesses.add(app);
7886 restart = true;
7887 }
7888 }
7889 mProcessesOnHold.remove(app);
7890
The Android Open Source Project4df24232009-03-05 14:34:35 -08007891 if (app == mHomeProcess) {
7892 mHomeProcess = null;
7893 }
7894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 if (restart) {
7896 // We have components that still need to be running in the
7897 // process, so re-launch it.
7898 mProcessNames.put(app.processName, app.info.uid, app);
7899 startProcessLocked(app, "restart", app.processName);
7900 } else if (app.pid > 0 && app.pid != MY_PID) {
7901 // Goodbye!
7902 synchronized (mPidsSelfLocked) {
7903 mPidsSelfLocked.remove(app.pid);
7904 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
7905 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007906 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007907 }
7908 }
7909
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007910 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
7911 // Look through the content providers we are waiting to have launched,
7912 // and if any run in this process then either schedule a restart of
7913 // the process or kill the client waiting for it if this process has
7914 // gone bad.
7915 int NL = mLaunchingProviders.size();
7916 boolean restart = false;
7917 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007918 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007919 if (cpr.launchingApp == app) {
7920 if (!alwaysBad && !app.bad) {
7921 restart = true;
7922 } else {
7923 removeDyingProviderLocked(app, cpr);
7924 NL = mLaunchingProviders.size();
7925 }
7926 }
7927 }
7928 return restart;
7929 }
7930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007931 // =========================================================
7932 // SERVICES
7933 // =========================================================
7934
7935 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
7936 ActivityManager.RunningServiceInfo info =
7937 new ActivityManager.RunningServiceInfo();
7938 info.service = r.name;
7939 if (r.app != null) {
7940 info.pid = r.app.pid;
7941 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007942 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007943 info.process = r.processName;
7944 info.foreground = r.isForeground;
7945 info.activeSince = r.createTime;
7946 info.started = r.startRequested;
7947 info.clientCount = r.connections.size();
7948 info.crashCount = r.crashCount;
7949 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007950 if (r.isForeground) {
7951 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
7952 }
7953 if (r.startRequested) {
7954 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
7955 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007956 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007957 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
7958 }
7959 if (r.app != null && r.app.persistent) {
7960 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
7961 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007962 for (ConnectionRecord conn : r.connections.values()) {
7963 if (conn.clientLabel != 0) {
7964 info.clientPackage = conn.binding.client.info.packageName;
7965 info.clientLabel = conn.clientLabel;
7966 break;
7967 }
7968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007969 return info;
7970 }
7971
7972 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
7973 int flags) {
7974 synchronized (this) {
7975 ArrayList<ActivityManager.RunningServiceInfo> res
7976 = new ArrayList<ActivityManager.RunningServiceInfo>();
7977
7978 if (mServices.size() > 0) {
7979 Iterator<ServiceRecord> it = mServices.values().iterator();
7980 while (it.hasNext() && res.size() < maxNum) {
7981 res.add(makeRunningServiceInfoLocked(it.next()));
7982 }
7983 }
7984
7985 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
7986 ServiceRecord r = mRestartingServices.get(i);
7987 ActivityManager.RunningServiceInfo info =
7988 makeRunningServiceInfoLocked(r);
7989 info.restarting = r.nextRestartTime;
7990 res.add(info);
7991 }
7992
7993 return res;
7994 }
7995 }
7996
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007997 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
7998 synchronized (this) {
7999 ServiceRecord r = mServices.get(name);
8000 if (r != null) {
8001 for (ConnectionRecord conn : r.connections.values()) {
8002 if (conn.clientIntent != null) {
8003 return conn.clientIntent;
8004 }
8005 }
8006 }
8007 }
8008 return null;
8009 }
8010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008011 private final ServiceRecord findServiceLocked(ComponentName name,
8012 IBinder token) {
8013 ServiceRecord r = mServices.get(name);
8014 return r == token ? r : null;
8015 }
8016
8017 private final class ServiceLookupResult {
8018 final ServiceRecord record;
8019 final String permission;
8020
8021 ServiceLookupResult(ServiceRecord _record, String _permission) {
8022 record = _record;
8023 permission = _permission;
8024 }
8025 };
8026
8027 private ServiceLookupResult findServiceLocked(Intent service,
8028 String resolvedType) {
8029 ServiceRecord r = null;
8030 if (service.getComponent() != null) {
8031 r = mServices.get(service.getComponent());
8032 }
8033 if (r == null) {
8034 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8035 r = mServicesByIntent.get(filter);
8036 }
8037
8038 if (r == null) {
8039 try {
8040 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008041 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008042 service, resolvedType, 0);
8043 ServiceInfo sInfo =
8044 rInfo != null ? rInfo.serviceInfo : null;
8045 if (sInfo == null) {
8046 return null;
8047 }
8048
8049 ComponentName name = new ComponentName(
8050 sInfo.applicationInfo.packageName, sInfo.name);
8051 r = mServices.get(name);
8052 } catch (RemoteException ex) {
8053 // pm is in same process, this will never happen.
8054 }
8055 }
8056 if (r != null) {
8057 int callingPid = Binder.getCallingPid();
8058 int callingUid = Binder.getCallingUid();
8059 if (checkComponentPermission(r.permission,
8060 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8061 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008062 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 + " from pid=" + callingPid
8064 + ", uid=" + callingUid
8065 + " requires " + r.permission);
8066 return new ServiceLookupResult(null, r.permission);
8067 }
8068 return new ServiceLookupResult(r, null);
8069 }
8070 return null;
8071 }
8072
8073 private class ServiceRestarter implements Runnable {
8074 private ServiceRecord mService;
8075
8076 void setService(ServiceRecord service) {
8077 mService = service;
8078 }
8079
8080 public void run() {
8081 synchronized(ActivityManagerService.this) {
8082 performServiceRestartLocked(mService);
8083 }
8084 }
8085 }
8086
8087 private ServiceLookupResult retrieveServiceLocked(Intent service,
8088 String resolvedType, int callingPid, int callingUid) {
8089 ServiceRecord r = null;
8090 if (service.getComponent() != null) {
8091 r = mServices.get(service.getComponent());
8092 }
8093 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8094 r = mServicesByIntent.get(filter);
8095 if (r == null) {
8096 try {
8097 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008098 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008099 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008100 ServiceInfo sInfo =
8101 rInfo != null ? rInfo.serviceInfo : null;
8102 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008103 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008104 ": not found");
8105 return null;
8106 }
8107
8108 ComponentName name = new ComponentName(
8109 sInfo.applicationInfo.packageName, sInfo.name);
8110 r = mServices.get(name);
8111 if (r == null) {
8112 filter = new Intent.FilterComparison(service.cloneFilter());
8113 ServiceRestarter res = new ServiceRestarter();
8114 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8115 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8116 synchronized (stats) {
8117 ss = stats.getServiceStatsLocked(
8118 sInfo.applicationInfo.uid, sInfo.packageName,
8119 sInfo.name);
8120 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008121 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008122 res.setService(r);
8123 mServices.put(name, r);
8124 mServicesByIntent.put(filter, r);
8125
8126 // Make sure this component isn't in the pending list.
8127 int N = mPendingServices.size();
8128 for (int i=0; i<N; i++) {
8129 ServiceRecord pr = mPendingServices.get(i);
8130 if (pr.name.equals(name)) {
8131 mPendingServices.remove(i);
8132 i--;
8133 N--;
8134 }
8135 }
8136 }
8137 } catch (RemoteException ex) {
8138 // pm is in same process, this will never happen.
8139 }
8140 }
8141 if (r != null) {
8142 if (checkComponentPermission(r.permission,
8143 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8144 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008145 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008146 + " from pid=" + Binder.getCallingPid()
8147 + ", uid=" + Binder.getCallingUid()
8148 + " requires " + r.permission);
8149 return new ServiceLookupResult(null, r.permission);
8150 }
8151 return new ServiceLookupResult(r, null);
8152 }
8153 return null;
8154 }
8155
8156 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8157 long now = SystemClock.uptimeMillis();
8158 if (r.executeNesting == 0 && r.app != null) {
8159 if (r.app.executingServices.size() == 0) {
8160 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8161 msg.obj = r.app;
8162 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8163 }
8164 r.app.executingServices.add(r);
8165 }
8166 r.executeNesting++;
8167 r.executingStart = now;
8168 }
8169
8170 private final void sendServiceArgsLocked(ServiceRecord r,
8171 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008172 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 if (N == 0) {
8174 return;
8175 }
8176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008177 int i = 0;
8178 while (i < N) {
8179 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008180 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008181 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008182 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -07008183 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008184 // If somehow we got a dummy start at the front, then
8185 // just drop it here.
8186 i++;
8187 continue;
8188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189 bumpServiceExecutingLocked(r);
8190 if (!oomAdjusted) {
8191 oomAdjusted = true;
8192 updateOomAdjLocked(r.app);
8193 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008194 int flags = 0;
8195 if (si.deliveryCount > 0) {
8196 flags |= Service.START_FLAG_RETRY;
8197 }
8198 if (si.doneExecutingCount > 0) {
8199 flags |= Service.START_FLAG_REDELIVERY;
8200 }
8201 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
8202 si.deliveredTime = SystemClock.uptimeMillis();
8203 r.deliveredStarts.add(si);
8204 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008205 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008206 } catch (RemoteException e) {
8207 // Remote process gone... we'll let the normal cleanup take
8208 // care of this.
8209 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008210 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008211 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008212 break;
8213 }
8214 }
8215 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008216 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 } else {
8218 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008220 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008221 }
8222 }
8223 }
8224
8225 private final boolean requestServiceBindingLocked(ServiceRecord r,
8226 IntentBindRecord i, boolean rebind) {
8227 if (r.app == null || r.app.thread == null) {
8228 // If service is not currently running, can't yet bind.
8229 return false;
8230 }
8231 if ((!i.requested || rebind) && i.apps.size() > 0) {
8232 try {
8233 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008234 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008235 + ": shouldUnbind=" + i.hasBound);
8236 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8237 if (!rebind) {
8238 i.requested = true;
8239 }
8240 i.hasBound = true;
8241 i.doRebind = false;
8242 } catch (RemoteException e) {
8243 return false;
8244 }
8245 }
8246 return true;
8247 }
8248
8249 private final void requestServiceBindingsLocked(ServiceRecord r) {
8250 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8251 while (bindings.hasNext()) {
8252 IntentBindRecord i = bindings.next();
8253 if (!requestServiceBindingLocked(r, i, false)) {
8254 break;
8255 }
8256 }
8257 }
8258
8259 private final void realStartServiceLocked(ServiceRecord r,
8260 ProcessRecord app) throws RemoteException {
8261 if (app.thread == null) {
8262 throw new RemoteException();
8263 }
8264
8265 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008266 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008267
8268 app.services.add(r);
8269 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008270 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271
8272 boolean created = false;
8273 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008274 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008275 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008276 mStringBuilder.setLength(0);
8277 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008278 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008279 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008280 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008281 synchronized (r.stats.getBatteryStats()) {
8282 r.stats.startLaunchedLocked();
8283 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008284 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008285 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008286 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008287 created = true;
8288 } finally {
8289 if (!created) {
8290 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008291 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008292 }
8293 }
8294
8295 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008296
8297 // If the service is in the started state, and there are no
8298 // pending arguments, then fake up one so its onStartCommand() will
8299 // be called.
8300 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8301 r.lastStartId++;
8302 if (r.lastStartId < 1) {
8303 r.lastStartId = 1;
8304 }
8305 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
8306 }
8307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008308 sendServiceArgsLocked(r, true);
8309 }
8310
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008311 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8312 boolean allowCancel) {
8313 boolean canceled = false;
8314
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008315 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008316 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008317 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008318
8319 // Any delivered but not yet finished starts should be put back
8320 // on the pending list.
8321 final int N = r.deliveredStarts.size();
8322 if (N > 0) {
8323 for (int i=N-1; i>=0; i--) {
8324 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
8325 if (si.intent == null) {
8326 // We'll generate this again if needed.
8327 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8328 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8329 r.pendingStarts.add(0, si);
8330 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8331 dur *= 2;
8332 if (minDuration < dur) minDuration = dur;
8333 if (resetTime < dur) resetTime = dur;
8334 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008335 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008336 + r.name);
8337 canceled = true;
8338 }
8339 }
8340 r.deliveredStarts.clear();
8341 }
8342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008343 r.totalRestartCount++;
8344 if (r.restartDelay == 0) {
8345 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008346 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 } else {
8348 // If it has been a "reasonably long time" since the service
8349 // was started, then reset our restart duration back to
8350 // the beginning, so we don't infinitely increase the duration
8351 // on a service that just occasionally gets killed (which is
8352 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008353 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008354 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008355 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008356 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008357 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008358 if (r.restartDelay < minDuration) {
8359 r.restartDelay = minDuration;
8360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008361 }
8362 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008363
8364 r.nextRestartTime = now + r.restartDelay;
8365
8366 // Make sure that we don't end up restarting a bunch of services
8367 // all at the same time.
8368 boolean repeat;
8369 do {
8370 repeat = false;
8371 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8372 ServiceRecord r2 = mRestartingServices.get(i);
8373 if (r2 != r && r.nextRestartTime
8374 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8375 && r.nextRestartTime
8376 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8377 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8378 r.restartDelay = r.nextRestartTime - now;
8379 repeat = true;
8380 break;
8381 }
8382 }
8383 } while (repeat);
8384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 if (!mRestartingServices.contains(r)) {
8386 mRestartingServices.add(r);
8387 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008388
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008389 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008391 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008392 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008394 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008395 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008396 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008397 r.shortName, r.restartDelay);
8398
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008399 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008400 }
8401
8402 final void performServiceRestartLocked(ServiceRecord r) {
8403 if (!mRestartingServices.contains(r)) {
8404 return;
8405 }
8406 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8407 }
8408
8409 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8410 if (r.restartDelay == 0) {
8411 return false;
8412 }
8413 r.resetRestartCounter();
8414 mRestartingServices.remove(r);
8415 mHandler.removeCallbacks(r.restarter);
8416 return true;
8417 }
8418
8419 private final boolean bringUpServiceLocked(ServiceRecord r,
8420 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008421 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008422 //r.dump(" ");
8423
Dianne Hackborn36124872009-10-08 16:22:03 -07008424 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 sendServiceArgsLocked(r, false);
8426 return true;
8427 }
8428
8429 if (!whileRestarting && r.restartDelay > 0) {
8430 // If waiting for a restart, then do nothing.
8431 return true;
8432 }
8433
Joe Onorato8a9b2202010-02-26 18:56:32 -08008434 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008435 + " " + r.intent);
8436
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008437 // We are now bringing the service up, so no longer in the
8438 // restarting state.
8439 mRestartingServices.remove(r);
8440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008441 final String appName = r.processName;
8442 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8443 if (app != null && app.thread != null) {
8444 try {
8445 realStartServiceLocked(r, app);
8446 return true;
8447 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008448 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008449 }
8450
8451 // If a dead object exception was thrown -- fall through to
8452 // restart the application.
8453 }
8454
Dianne Hackborn36124872009-10-08 16:22:03 -07008455 // Not running -- get it started, and enqueue this service record
8456 // to be executed when the app comes up.
8457 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8458 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008459 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008460 + r.appInfo.packageName + "/"
8461 + r.appInfo.uid + " for service "
8462 + r.intent.getIntent() + ": process is bad");
8463 bringDownServiceLocked(r, true);
8464 return false;
8465 }
8466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008467 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008468 mPendingServices.add(r);
8469 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 return true;
8472 }
8473
8474 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008475 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008476 //r.dump(" ");
8477
8478 // Does it still need to run?
8479 if (!force && r.startRequested) {
8480 return;
8481 }
8482 if (r.connections.size() > 0) {
8483 if (!force) {
8484 // XXX should probably keep a count of the number of auto-create
8485 // connections directly in the service.
8486 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8487 while (it.hasNext()) {
8488 ConnectionRecord cr = it.next();
8489 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
8490 return;
8491 }
8492 }
8493 }
8494
8495 // Report to all of the connections that the service is no longer
8496 // available.
8497 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8498 while (it.hasNext()) {
8499 ConnectionRecord c = it.next();
8500 try {
8501 // todo: shouldn't be a synchronous call!
8502 c.conn.connected(r.name, null);
8503 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008504 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 " to connection " + c.conn.asBinder() +
8506 " (in " + c.binding.client.processName + ")", e);
8507 }
8508 }
8509 }
8510
8511 // Tell the service that it has been unbound.
8512 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8513 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8514 while (it.hasNext()) {
8515 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008516 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 + ": hasBound=" + ibr.hasBound);
8518 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8519 try {
8520 bumpServiceExecutingLocked(r);
8521 updateOomAdjLocked(r.app);
8522 ibr.hasBound = false;
8523 r.app.thread.scheduleUnbindService(r,
8524 ibr.intent.getIntent());
8525 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008526 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008527 + r.shortName, e);
8528 serviceDoneExecutingLocked(r, true);
8529 }
8530 }
8531 }
8532 }
8533
Joe Onorato8a9b2202010-02-26 18:56:32 -08008534 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008535 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008536 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 System.identityHashCode(r), r.shortName,
8538 (r.app != null) ? r.app.pid : -1);
8539
8540 mServices.remove(r.name);
8541 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008542 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 r.totalRestartCount = 0;
8544 unscheduleServiceRestartLocked(r);
8545
8546 // Also make sure it is not on the pending list.
8547 int N = mPendingServices.size();
8548 for (int i=0; i<N; i++) {
8549 if (mPendingServices.get(i) == r) {
8550 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008551 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008552 TAG, "Removed pending service: " + r.shortName);
8553 i--;
8554 N--;
8555 }
8556 }
8557
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008558 r.cancelNotification();
8559 r.isForeground = false;
8560 r.foregroundId = 0;
8561 r.foregroundNoti = null;
8562
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008563 // Clear start entries.
8564 r.deliveredStarts.clear();
8565 r.pendingStarts.clear();
8566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008567 if (r.app != null) {
8568 synchronized (r.stats.getBatteryStats()) {
8569 r.stats.stopLaunchedLocked();
8570 }
8571 r.app.services.remove(r);
8572 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008573 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008574 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008575 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008576 bumpServiceExecutingLocked(r);
8577 mStoppingServices.add(r);
8578 updateOomAdjLocked(r.app);
8579 r.app.thread.scheduleStopService(r);
8580 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008581 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008582 + r.shortName, e);
8583 serviceDoneExecutingLocked(r, true);
8584 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008585 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008587 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008588 TAG, "Removed service that has no process: " + r.shortName);
8589 }
8590 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008591 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008592 TAG, "Removed service that is not running: " + r.shortName);
8593 }
8594 }
8595
8596 ComponentName startServiceLocked(IApplicationThread caller,
8597 Intent service, String resolvedType,
8598 int callingPid, int callingUid) {
8599 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008600 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008601 + " type=" + resolvedType + " args=" + service.getExtras());
8602
8603 if (caller != null) {
8604 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8605 if (callerApp == null) {
8606 throw new SecurityException(
8607 "Unable to find app for caller " + caller
8608 + " (pid=" + Binder.getCallingPid()
8609 + ") when starting service " + service);
8610 }
8611 }
8612
8613 ServiceLookupResult res =
8614 retrieveServiceLocked(service, resolvedType,
8615 callingPid, callingUid);
8616 if (res == null) {
8617 return null;
8618 }
8619 if (res.record == null) {
8620 return new ComponentName("!", res.permission != null
8621 ? res.permission : "private to package");
8622 }
8623 ServiceRecord r = res.record;
8624 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008625 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008626 + r.shortName);
8627 }
8628 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008629 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008630 r.lastStartId++;
8631 if (r.lastStartId < 1) {
8632 r.lastStartId = 1;
8633 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008634 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008635 r.lastActivity = SystemClock.uptimeMillis();
8636 synchronized (r.stats.getBatteryStats()) {
8637 r.stats.startRunningLocked();
8638 }
8639 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8640 return new ComponentName("!", "Service process is bad");
8641 }
8642 return r.name;
8643 }
8644 }
8645
8646 public ComponentName startService(IApplicationThread caller, Intent service,
8647 String resolvedType) {
8648 // Refuse possible leaked file descriptors
8649 if (service != null && service.hasFileDescriptors() == true) {
8650 throw new IllegalArgumentException("File descriptors passed in Intent");
8651 }
8652
8653 synchronized(this) {
8654 final int callingPid = Binder.getCallingPid();
8655 final int callingUid = Binder.getCallingUid();
8656 final long origId = Binder.clearCallingIdentity();
8657 ComponentName res = startServiceLocked(caller, service,
8658 resolvedType, callingPid, callingUid);
8659 Binder.restoreCallingIdentity(origId);
8660 return res;
8661 }
8662 }
8663
8664 ComponentName startServiceInPackage(int uid,
8665 Intent service, String resolvedType) {
8666 synchronized(this) {
8667 final long origId = Binder.clearCallingIdentity();
8668 ComponentName res = startServiceLocked(null, service,
8669 resolvedType, -1, uid);
8670 Binder.restoreCallingIdentity(origId);
8671 return res;
8672 }
8673 }
8674
8675 public int stopService(IApplicationThread caller, Intent service,
8676 String resolvedType) {
8677 // Refuse possible leaked file descriptors
8678 if (service != null && service.hasFileDescriptors() == true) {
8679 throw new IllegalArgumentException("File descriptors passed in Intent");
8680 }
8681
8682 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008683 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008684 + " type=" + resolvedType);
8685
8686 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8687 if (caller != null && callerApp == null) {
8688 throw new SecurityException(
8689 "Unable to find app for caller " + caller
8690 + " (pid=" + Binder.getCallingPid()
8691 + ") when stopping service " + service);
8692 }
8693
8694 // If this service is active, make sure it is stopped.
8695 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8696 if (r != null) {
8697 if (r.record != null) {
8698 synchronized (r.record.stats.getBatteryStats()) {
8699 r.record.stats.stopRunningLocked();
8700 }
8701 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008702 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008703 final long origId = Binder.clearCallingIdentity();
8704 bringDownServiceLocked(r.record, false);
8705 Binder.restoreCallingIdentity(origId);
8706 return 1;
8707 }
8708 return -1;
8709 }
8710 }
8711
8712 return 0;
8713 }
8714
8715 public IBinder peekService(Intent service, String resolvedType) {
8716 // Refuse possible leaked file descriptors
8717 if (service != null && service.hasFileDescriptors() == true) {
8718 throw new IllegalArgumentException("File descriptors passed in Intent");
8719 }
8720
8721 IBinder ret = null;
8722
8723 synchronized(this) {
8724 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8725
8726 if (r != null) {
8727 // r.record is null if findServiceLocked() failed the caller permission check
8728 if (r.record == null) {
8729 throw new SecurityException(
8730 "Permission Denial: Accessing service " + r.record.name
8731 + " from pid=" + Binder.getCallingPid()
8732 + ", uid=" + Binder.getCallingUid()
8733 + " requires " + r.permission);
8734 }
8735 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8736 if (ib != null) {
8737 ret = ib.binder;
8738 }
8739 }
8740 }
8741
8742 return ret;
8743 }
8744
8745 public boolean stopServiceToken(ComponentName className, IBinder token,
8746 int startId) {
8747 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008748 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 + " " + token + " startId=" + startId);
8750 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008751 if (r != null) {
8752 if (startId >= 0) {
8753 // Asked to only stop if done with all work. Note that
8754 // to avoid leaks, we will take this as dropping all
8755 // start items up to and including this one.
8756 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8757 if (si != null) {
8758 while (r.deliveredStarts.size() > 0) {
8759 if (r.deliveredStarts.remove(0) == si) {
8760 break;
8761 }
8762 }
8763 }
8764
8765 if (r.lastStartId != startId) {
8766 return false;
8767 }
8768
8769 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008770 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008771 + " is last, but have " + r.deliveredStarts.size()
8772 + " remaining args");
8773 }
8774 }
8775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008776 synchronized (r.stats.getBatteryStats()) {
8777 r.stats.stopRunningLocked();
8778 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008779 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008780 }
8781 final long origId = Binder.clearCallingIdentity();
8782 bringDownServiceLocked(r, false);
8783 Binder.restoreCallingIdentity(origId);
8784 return true;
8785 }
8786 }
8787 return false;
8788 }
8789
8790 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008791 int id, Notification notification, boolean removeNotification) {
8792 final long origId = Binder.clearCallingIdentity();
8793 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 synchronized(this) {
8795 ServiceRecord r = findServiceLocked(className, token);
8796 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008797 if (id != 0) {
8798 if (notification == null) {
8799 throw new IllegalArgumentException("null notification");
8800 }
8801 if (r.foregroundId != id) {
8802 r.cancelNotification();
8803 r.foregroundId = id;
8804 }
8805 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8806 r.foregroundNoti = notification;
8807 r.isForeground = true;
8808 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 if (r.app != null) {
8810 updateServiceForegroundLocked(r.app, true);
8811 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008812 } else {
8813 if (r.isForeground) {
8814 r.isForeground = false;
8815 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008816 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008817 updateServiceForegroundLocked(r.app, true);
8818 }
8819 }
8820 if (removeNotification) {
8821 r.cancelNotification();
8822 r.foregroundId = 0;
8823 r.foregroundNoti = null;
8824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008825 }
8826 }
8827 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008828 } finally {
8829 Binder.restoreCallingIdentity(origId);
8830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008831 }
8832
8833 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8834 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008835 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008836 if (sr.isForeground) {
8837 anyForeground = true;
8838 break;
8839 }
8840 }
8841 if (anyForeground != proc.foregroundServices) {
8842 proc.foregroundServices = anyForeground;
8843 if (oomAdj) {
8844 updateOomAdjLocked();
8845 }
8846 }
8847 }
8848
8849 public int bindService(IApplicationThread caller, IBinder token,
8850 Intent service, String resolvedType,
8851 IServiceConnection connection, int flags) {
8852 // Refuse possible leaked file descriptors
8853 if (service != null && service.hasFileDescriptors() == true) {
8854 throw new IllegalArgumentException("File descriptors passed in Intent");
8855 }
8856
8857 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008858 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008859 + " type=" + resolvedType + " conn=" + connection.asBinder()
8860 + " flags=0x" + Integer.toHexString(flags));
8861 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8862 if (callerApp == null) {
8863 throw new SecurityException(
8864 "Unable to find app for caller " + caller
8865 + " (pid=" + Binder.getCallingPid()
8866 + ") when binding service " + service);
8867 }
8868
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008869 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008870 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008871 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008872 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008873 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008874 return 0;
8875 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008876 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008877 }
8878
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008879 int clientLabel = 0;
8880 PendingIntent clientIntent = null;
8881
8882 if (callerApp.info.uid == Process.SYSTEM_UID) {
8883 // Hacky kind of thing -- allow system stuff to tell us
8884 // what they are, so we can report this elsewhere for
8885 // others to know why certain services are running.
8886 try {
8887 clientIntent = (PendingIntent)service.getParcelableExtra(
8888 Intent.EXTRA_CLIENT_INTENT);
8889 } catch (RuntimeException e) {
8890 }
8891 if (clientIntent != null) {
8892 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
8893 if (clientLabel != 0) {
8894 // There are no useful extras in the intent, trash them.
8895 // System code calling with this stuff just needs to know
8896 // this will happen.
8897 service = service.cloneFilter();
8898 }
8899 }
8900 }
8901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008902 ServiceLookupResult res =
8903 retrieveServiceLocked(service, resolvedType,
8904 Binder.getCallingPid(), Binder.getCallingUid());
8905 if (res == null) {
8906 return 0;
8907 }
8908 if (res.record == null) {
8909 return -1;
8910 }
8911 ServiceRecord s = res.record;
8912
8913 final long origId = Binder.clearCallingIdentity();
8914
8915 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008916 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 + s.shortName);
8918 }
8919
8920 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
8921 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008922 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008923
8924 IBinder binder = connection.asBinder();
8925 s.connections.put(binder, c);
8926 b.connections.add(c);
8927 if (activity != null) {
8928 if (activity.connections == null) {
8929 activity.connections = new HashSet<ConnectionRecord>();
8930 }
8931 activity.connections.add(c);
8932 }
8933 b.client.connections.add(c);
8934 mServiceConnections.put(binder, c);
8935
8936 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
8937 s.lastActivity = SystemClock.uptimeMillis();
8938 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
8939 return 0;
8940 }
8941 }
8942
8943 if (s.app != null) {
8944 // This could have made the service more important.
8945 updateOomAdjLocked(s.app);
8946 }
8947
Joe Onorato8a9b2202010-02-26 18:56:32 -08008948 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008949 + ": received=" + b.intent.received
8950 + " apps=" + b.intent.apps.size()
8951 + " doRebind=" + b.intent.doRebind);
8952
8953 if (s.app != null && b.intent.received) {
8954 // Service is already running, so we can immediately
8955 // publish the connection.
8956 try {
8957 c.conn.connected(s.name, b.intent.binder);
8958 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008959 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008960 + " to connection " + c.conn.asBinder()
8961 + " (in " + c.binding.client.processName + ")", e);
8962 }
8963
8964 // If this is the first app connected back to this binding,
8965 // and the service had previously asked to be told when
8966 // rebound, then do so.
8967 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
8968 requestServiceBindingLocked(s, b.intent, true);
8969 }
8970 } else if (!b.intent.requested) {
8971 requestServiceBindingLocked(s, b.intent, false);
8972 }
8973
8974 Binder.restoreCallingIdentity(origId);
8975 }
8976
8977 return 1;
8978 }
8979
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008980 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008981 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 IBinder binder = c.conn.asBinder();
8983 AppBindRecord b = c.binding;
8984 ServiceRecord s = b.service;
8985 s.connections.remove(binder);
8986 b.connections.remove(c);
8987 if (c.activity != null && c.activity != skipAct) {
8988 if (c.activity.connections != null) {
8989 c.activity.connections.remove(c);
8990 }
8991 }
8992 if (b.client != skipApp) {
8993 b.client.connections.remove(c);
8994 }
8995 mServiceConnections.remove(binder);
8996
8997 if (b.connections.size() == 0) {
8998 b.intent.apps.remove(b.client);
8999 }
9000
Joe Onorato8a9b2202010-02-26 18:56:32 -08009001 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009002 + ": shouldUnbind=" + b.intent.hasBound);
9003 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9004 && b.intent.hasBound) {
9005 try {
9006 bumpServiceExecutingLocked(s);
9007 updateOomAdjLocked(s.app);
9008 b.intent.hasBound = false;
9009 // Assume the client doesn't want to know about a rebind;
9010 // we will deal with that later if it asks for one.
9011 b.intent.doRebind = false;
9012 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9013 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009014 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009015 serviceDoneExecutingLocked(s, true);
9016 }
9017 }
9018
9019 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9020 bringDownServiceLocked(s, false);
9021 }
9022 }
9023
9024 public boolean unbindService(IServiceConnection connection) {
9025 synchronized (this) {
9026 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009027 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009028 ConnectionRecord r = mServiceConnections.get(binder);
9029 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009030 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 + connection.asBinder());
9032 return false;
9033 }
9034
9035 final long origId = Binder.clearCallingIdentity();
9036
9037 removeConnectionLocked(r, null, null);
9038
9039 if (r.binding.service.app != null) {
9040 // This could have made the service less important.
9041 updateOomAdjLocked(r.binding.service.app);
9042 }
9043
9044 Binder.restoreCallingIdentity(origId);
9045 }
9046
9047 return true;
9048 }
9049
9050 public void publishService(IBinder token, Intent intent, IBinder service) {
9051 // Refuse possible leaked file descriptors
9052 if (intent != null && intent.hasFileDescriptors() == true) {
9053 throw new IllegalArgumentException("File descriptors passed in Intent");
9054 }
9055
9056 synchronized(this) {
9057 if (!(token instanceof ServiceRecord)) {
9058 throw new IllegalArgumentException("Invalid service token");
9059 }
9060 ServiceRecord r = (ServiceRecord)token;
9061
9062 final long origId = Binder.clearCallingIdentity();
9063
Joe Onorato8a9b2202010-02-26 18:56:32 -08009064 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009065 + " " + intent + ": " + service);
9066 if (r != null) {
9067 Intent.FilterComparison filter
9068 = new Intent.FilterComparison(intent);
9069 IntentBindRecord b = r.bindings.get(filter);
9070 if (b != null && !b.received) {
9071 b.binder = service;
9072 b.requested = true;
9073 b.received = true;
9074 if (r.connections.size() > 0) {
9075 Iterator<ConnectionRecord> it
9076 = r.connections.values().iterator();
9077 while (it.hasNext()) {
9078 ConnectionRecord c = it.next();
9079 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009080 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009082 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009083 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009084 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085 TAG, "Published intent: " + intent);
9086 continue;
9087 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009088 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009089 try {
9090 c.conn.connected(r.name, service);
9091 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009092 Slog.w(TAG, "Failure sending service " + r.name +
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 }
9098 }
9099
9100 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9101
9102 Binder.restoreCallingIdentity(origId);
9103 }
9104 }
9105 }
9106
9107 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9108 // Refuse possible leaked file descriptors
9109 if (intent != null && intent.hasFileDescriptors() == true) {
9110 throw new IllegalArgumentException("File descriptors passed in Intent");
9111 }
9112
9113 synchronized(this) {
9114 if (!(token instanceof ServiceRecord)) {
9115 throw new IllegalArgumentException("Invalid service token");
9116 }
9117 ServiceRecord r = (ServiceRecord)token;
9118
9119 final long origId = Binder.clearCallingIdentity();
9120
9121 if (r != null) {
9122 Intent.FilterComparison filter
9123 = new Intent.FilterComparison(intent);
9124 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009125 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009126 + " at " + b + ": apps="
9127 + (b != null ? b.apps.size() : 0));
9128 if (b != null) {
9129 if (b.apps.size() > 0) {
9130 // Applications have already bound since the last
9131 // unbind, so just rebind right here.
9132 requestServiceBindingLocked(r, b, true);
9133 } else {
9134 // Note to tell the service the next time there is
9135 // a new client.
9136 b.doRebind = true;
9137 }
9138 }
9139
9140 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9141
9142 Binder.restoreCallingIdentity(origId);
9143 }
9144 }
9145 }
9146
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009147 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009148 synchronized(this) {
9149 if (!(token instanceof ServiceRecord)) {
9150 throw new IllegalArgumentException("Invalid service token");
9151 }
9152 ServiceRecord r = (ServiceRecord)token;
9153 boolean inStopping = mStoppingServices.contains(token);
9154 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009155 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009156 + ": nesting=" + r.executeNesting
9157 + ", inStopping=" + inStopping);
9158 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009159 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160 + " with incorrect token: given " + token
9161 + ", expected " + r);
9162 return;
9163 }
9164
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009165 if (type == 1) {
9166 // This is a call from a service start... take care of
9167 // book-keeping.
9168 r.callStart = true;
9169 switch (res) {
9170 case Service.START_STICKY_COMPATIBILITY:
9171 case Service.START_STICKY: {
9172 // We are done with the associated start arguments.
9173 r.findDeliveredStart(startId, true);
9174 // Don't stop if killed.
9175 r.stopIfKilled = false;
9176 break;
9177 }
9178 case Service.START_NOT_STICKY: {
9179 // We are done with the associated start arguments.
9180 r.findDeliveredStart(startId, true);
9181 if (r.lastStartId == startId) {
9182 // There is no more work, and this service
9183 // doesn't want to hang around if killed.
9184 r.stopIfKilled = true;
9185 }
9186 break;
9187 }
9188 case Service.START_REDELIVER_INTENT: {
9189 // We'll keep this item until they explicitly
9190 // call stop for it, but keep track of the fact
9191 // that it was delivered.
9192 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9193 if (si != null) {
9194 si.deliveryCount = 0;
9195 si.doneExecutingCount++;
9196 // Don't stop if killed.
9197 r.stopIfKilled = true;
9198 }
9199 break;
9200 }
9201 default:
9202 throw new IllegalArgumentException(
9203 "Unknown service start result: " + res);
9204 }
9205 if (res == Service.START_STICKY_COMPATIBILITY) {
9206 r.callStart = false;
9207 }
9208 }
9209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009210 final long origId = Binder.clearCallingIdentity();
9211 serviceDoneExecutingLocked(r, inStopping);
9212 Binder.restoreCallingIdentity(origId);
9213 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009214 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 + " with token " + token);
9216 }
9217 }
9218 }
9219
9220 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9221 r.executeNesting--;
9222 if (r.executeNesting <= 0 && r.app != null) {
9223 r.app.executingServices.remove(r);
9224 if (r.app.executingServices.size() == 0) {
9225 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9226 }
9227 if (inStopping) {
9228 mStoppingServices.remove(r);
9229 }
9230 updateOomAdjLocked(r.app);
9231 }
9232 }
9233
9234 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009235 String anrMessage = null;
9236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009237 synchronized(this) {
9238 if (proc.executingServices.size() == 0 || proc.thread == null) {
9239 return;
9240 }
9241 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9242 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9243 ServiceRecord timeout = null;
9244 long nextTime = 0;
9245 while (it.hasNext()) {
9246 ServiceRecord sr = it.next();
9247 if (sr.executingStart < maxTime) {
9248 timeout = sr;
9249 break;
9250 }
9251 if (sr.executingStart > nextTime) {
9252 nextTime = sr.executingStart;
9253 }
9254 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009255 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009256 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009257 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009258 } else {
9259 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9260 msg.obj = proc;
9261 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9262 }
9263 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009264
9265 if (anrMessage != null) {
9266 appNotResponding(proc, null, null, anrMessage);
9267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009268 }
9269
9270 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009271 // BACKUP AND RESTORE
9272 // =========================================================
9273
9274 // Cause the target app to be launched if necessary and its backup agent
9275 // instantiated. The backup agent will invoke backupAgentCreated() on the
9276 // activity manager to announce its creation.
9277 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009278 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009279 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9280
9281 synchronized(this) {
9282 // !!! TODO: currently no check here that we're already bound
9283 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9284 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9285 synchronized (stats) {
9286 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9287 }
9288
9289 BackupRecord r = new BackupRecord(ss, app, backupMode);
9290 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9291 // startProcessLocked() returns existing proc's record if it's already running
9292 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009293 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009294 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009295 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009296 return false;
9297 }
9298
9299 r.app = proc;
9300 mBackupTarget = r;
9301 mBackupAppName = app.packageName;
9302
Christopher Tate6fa95972009-06-05 18:43:55 -07009303 // Try not to kill the process during backup
9304 updateOomAdjLocked(proc);
9305
Christopher Tate181fafa2009-05-14 11:12:14 -07009306 // If the process is already attached, schedule the creation of the backup agent now.
9307 // If it is not yet live, this will be done when it attaches to the framework.
9308 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009309 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009310 try {
9311 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9312 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009313 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009314 }
9315 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009316 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009317 }
9318 // Invariants: at this point, the target app process exists and the application
9319 // is either already running or in the process of coming up. mBackupTarget and
9320 // mBackupAppName describe the app, so that when it binds back to the AM we
9321 // know that it's scheduled for a backup-agent operation.
9322 }
9323
9324 return true;
9325 }
9326
9327 // A backup agent has just come up
9328 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009329 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009330 + " = " + agent);
9331
9332 synchronized(this) {
9333 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009334 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009335 return;
9336 }
9337
Christopher Tate043dadc2009-06-02 16:11:00 -07009338 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009339 try {
9340 IBackupManager bm = IBackupManager.Stub.asInterface(
9341 ServiceManager.getService(Context.BACKUP_SERVICE));
9342 bm.agentConnected(agentPackageName, agent);
9343 } catch (RemoteException e) {
9344 // can't happen; the backup manager service is local
9345 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009346 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009347 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009348 } finally {
9349 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009350 }
9351 }
9352 }
9353
9354 // done with this agent
9355 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009356 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009357 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009358 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009359 return;
9360 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009361
9362 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009363 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009364 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009365 return;
9366 }
9367
Christopher Tate181fafa2009-05-14 11:12:14 -07009368 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009369 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009370 return;
9371 }
9372
Christopher Tate6fa95972009-06-05 18:43:55 -07009373 ProcessRecord proc = mBackupTarget.app;
9374 mBackupTarget = null;
9375 mBackupAppName = null;
9376
9377 // Not backing this app up any more; reset its OOM adjustment
9378 updateOomAdjLocked(proc);
9379
Christopher Tatec7b31e32009-06-10 15:49:30 -07009380 // If the app crashed during backup, 'thread' will be null here
9381 if (proc.thread != null) {
9382 try {
9383 proc.thread.scheduleDestroyBackupAgent(appInfo);
9384 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009385 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009386 e.printStackTrace();
9387 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009388 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009389 }
9390 }
9391 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009392 // BROADCASTS
9393 // =========================================================
9394
Josh Bartel7f208742010-02-25 11:01:44 -06009395 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009396 List cur) {
9397 final ContentResolver resolver = mContext.getContentResolver();
9398 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9399 if (list == null) {
9400 return cur;
9401 }
9402 int N = list.size();
9403 for (int i=0; i<N; i++) {
9404 Intent intent = list.get(i);
9405 if (filter.match(resolver, intent, true, TAG) >= 0) {
9406 if (cur == null) {
9407 cur = new ArrayList<Intent>();
9408 }
9409 cur.add(intent);
9410 }
9411 }
9412 return cur;
9413 }
9414
9415 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009416 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009417 + mBroadcastsScheduled);
9418
9419 if (mBroadcastsScheduled) {
9420 return;
9421 }
9422 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9423 mBroadcastsScheduled = true;
9424 }
9425
9426 public Intent registerReceiver(IApplicationThread caller,
9427 IIntentReceiver receiver, IntentFilter filter, String permission) {
9428 synchronized(this) {
9429 ProcessRecord callerApp = null;
9430 if (caller != null) {
9431 callerApp = getRecordForAppLocked(caller);
9432 if (callerApp == null) {
9433 throw new SecurityException(
9434 "Unable to find app for caller " + caller
9435 + " (pid=" + Binder.getCallingPid()
9436 + ") when registering receiver " + receiver);
9437 }
9438 }
9439
9440 List allSticky = null;
9441
9442 // Look for any matching sticky broadcasts...
9443 Iterator actions = filter.actionsIterator();
9444 if (actions != null) {
9445 while (actions.hasNext()) {
9446 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009447 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009448 }
9449 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009450 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009451 }
9452
9453 // The first sticky in the list is returned directly back to
9454 // the client.
9455 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9456
Joe Onorato8a9b2202010-02-26 18:56:32 -08009457 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009458 + ": " + sticky);
9459
9460 if (receiver == null) {
9461 return sticky;
9462 }
9463
9464 ReceiverList rl
9465 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9466 if (rl == null) {
9467 rl = new ReceiverList(this, callerApp,
9468 Binder.getCallingPid(),
9469 Binder.getCallingUid(), receiver);
9470 if (rl.app != null) {
9471 rl.app.receivers.add(rl);
9472 } else {
9473 try {
9474 receiver.asBinder().linkToDeath(rl, 0);
9475 } catch (RemoteException e) {
9476 return sticky;
9477 }
9478 rl.linkedToDeath = true;
9479 }
9480 mRegisteredReceivers.put(receiver.asBinder(), rl);
9481 }
9482 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9483 rl.add(bf);
9484 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009485 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009486 }
9487 mReceiverResolver.addFilter(bf);
9488
9489 // Enqueue broadcasts for all existing stickies that match
9490 // this filter.
9491 if (allSticky != null) {
9492 ArrayList receivers = new ArrayList();
9493 receivers.add(bf);
9494
9495 int N = allSticky.size();
9496 for (int i=0; i<N; i++) {
9497 Intent intent = (Intent)allSticky.get(i);
9498 BroadcastRecord r = new BroadcastRecord(intent, null,
9499 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009500 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009501 if (mParallelBroadcasts.size() == 0) {
9502 scheduleBroadcastsLocked();
9503 }
9504 mParallelBroadcasts.add(r);
9505 }
9506 }
9507
9508 return sticky;
9509 }
9510 }
9511
9512 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009513 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009514
9515 boolean doNext = false;
9516
9517 synchronized(this) {
9518 ReceiverList rl
9519 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9520 if (rl != null) {
9521 if (rl.curBroadcast != null) {
9522 BroadcastRecord r = rl.curBroadcast;
9523 doNext = finishReceiverLocked(
9524 receiver.asBinder(), r.resultCode, r.resultData,
9525 r.resultExtras, r.resultAbort, true);
9526 }
9527
9528 if (rl.app != null) {
9529 rl.app.receivers.remove(rl);
9530 }
9531 removeReceiverLocked(rl);
9532 if (rl.linkedToDeath) {
9533 rl.linkedToDeath = false;
9534 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9535 }
9536 }
9537 }
9538
9539 if (!doNext) {
9540 return;
9541 }
9542
9543 final long origId = Binder.clearCallingIdentity();
9544 processNextBroadcast(false);
9545 trimApplications();
9546 Binder.restoreCallingIdentity(origId);
9547 }
9548
9549 void removeReceiverLocked(ReceiverList rl) {
9550 mRegisteredReceivers.remove(rl.receiver.asBinder());
9551 int N = rl.size();
9552 for (int i=0; i<N; i++) {
9553 mReceiverResolver.removeFilter(rl.get(i));
9554 }
9555 }
9556
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009557 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9558 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9559 ProcessRecord r = mLruProcesses.get(i);
9560 if (r.thread != null) {
9561 try {
9562 r.thread.dispatchPackageBroadcast(cmd, packages);
9563 } catch (RemoteException ex) {
9564 }
9565 }
9566 }
9567 }
9568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009569 private final int broadcastIntentLocked(ProcessRecord callerApp,
9570 String callerPackage, Intent intent, String resolvedType,
9571 IIntentReceiver resultTo, int resultCode, String resultData,
9572 Bundle map, String requiredPermission,
9573 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9574 intent = new Intent(intent);
9575
Joe Onorato8a9b2202010-02-26 18:56:32 -08009576 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009577 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9578 + " ordered=" + ordered);
9579 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009580 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009581 }
9582
9583 // Handle special intents: if this broadcast is from the package
9584 // manager about a package being removed, we need to remove all of
9585 // its activities from the history stack.
9586 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9587 intent.getAction());
9588 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9589 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009590 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009591 || uidRemoved) {
9592 if (checkComponentPermission(
9593 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9594 callingPid, callingUid, -1)
9595 == PackageManager.PERMISSION_GRANTED) {
9596 if (uidRemoved) {
9597 final Bundle intentExtras = intent.getExtras();
9598 final int uid = intentExtras != null
9599 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9600 if (uid >= 0) {
9601 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9602 synchronized (bs) {
9603 bs.removeUidStatsLocked(uid);
9604 }
9605 }
9606 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009607 // If resources are unvailble just force stop all
9608 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009609 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009610 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9611 if (list != null && (list.length > 0)) {
9612 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009613 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009614 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009615 sendPackageBroadcastLocked(
9616 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009617 }
9618 } else {
9619 Uri data = intent.getData();
9620 String ssp;
9621 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9622 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9623 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009624 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009625 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009626 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9627 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9628 new String[] {ssp});
9629 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009630 }
9631 }
9632 }
9633 } else {
9634 String msg = "Permission Denial: " + intent.getAction()
9635 + " broadcast from " + callerPackage + " (pid=" + callingPid
9636 + ", uid=" + callingUid + ")"
9637 + " requires "
9638 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009639 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009640 throw new SecurityException(msg);
9641 }
9642 }
9643
9644 /*
9645 * If this is the time zone changed action, queue up a message that will reset the timezone
9646 * of all currently running processes. This message will get queued up before the broadcast
9647 * happens.
9648 */
9649 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9650 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9651 }
9652
Dianne Hackborn854060af2009-07-09 18:14:31 -07009653 /*
9654 * Prevent non-system code (defined here to be non-persistent
9655 * processes) from sending protected broadcasts.
9656 */
9657 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9658 || callingUid == Process.SHELL_UID || callingUid == 0) {
9659 // Always okay.
9660 } else if (callerApp == null || !callerApp.persistent) {
9661 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009662 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009663 intent.getAction())) {
9664 String msg = "Permission Denial: not allowed to send broadcast "
9665 + intent.getAction() + " from pid="
9666 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009667 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009668 throw new SecurityException(msg);
9669 }
9670 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009671 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009672 return BROADCAST_SUCCESS;
9673 }
9674 }
9675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676 // Add to the sticky list if requested.
9677 if (sticky) {
9678 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9679 callingPid, callingUid)
9680 != PackageManager.PERMISSION_GRANTED) {
9681 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9682 + callingPid + ", uid=" + callingUid
9683 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009684 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009685 throw new SecurityException(msg);
9686 }
9687 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009688 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 + " and enforce permission " + requiredPermission);
9690 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9691 }
9692 if (intent.getComponent() != null) {
9693 throw new SecurityException(
9694 "Sticky broadcasts can't target a specific component");
9695 }
9696 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9697 if (list == null) {
9698 list = new ArrayList<Intent>();
9699 mStickyBroadcasts.put(intent.getAction(), list);
9700 }
9701 int N = list.size();
9702 int i;
9703 for (i=0; i<N; i++) {
9704 if (intent.filterEquals(list.get(i))) {
9705 // This sticky already exists, replace it.
9706 list.set(i, new Intent(intent));
9707 break;
9708 }
9709 }
9710 if (i >= N) {
9711 list.add(new Intent(intent));
9712 }
9713 }
9714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009715 // Figure out who all will receive this broadcast.
9716 List receivers = null;
9717 List<BroadcastFilter> registeredReceivers = null;
9718 try {
9719 if (intent.getComponent() != null) {
9720 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009721 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009722 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009723 if (ai != null) {
9724 receivers = new ArrayList();
9725 ResolveInfo ri = new ResolveInfo();
9726 ri.activityInfo = ai;
9727 receivers.add(ri);
9728 }
9729 } else {
9730 // Need to resolve the intent to interested receivers...
9731 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9732 == 0) {
9733 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009734 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009735 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009736 }
Mihai Preda074edef2009-05-18 17:13:31 +02009737 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009738 }
9739 } catch (RemoteException ex) {
9740 // pm is in same process, this will never happen.
9741 }
9742
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009743 final boolean replacePending =
9744 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9745
Joe Onorato8a9b2202010-02-26 18:56:32 -08009746 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009747 + " replacePending=" + replacePending);
9748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009749 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9750 if (!ordered && NR > 0) {
9751 // If we are not serializing this broadcast, then send the
9752 // registered receivers separately so they don't wait for the
9753 // components to be launched.
9754 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9755 callerPackage, callingPid, callingUid, requiredPermission,
9756 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009757 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009758 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 TAG, "Enqueueing parallel broadcast " + r
9760 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009761 boolean replaced = false;
9762 if (replacePending) {
9763 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9764 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009765 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009766 "***** DROPPING PARALLEL: " + intent);
9767 mParallelBroadcasts.set(i, r);
9768 replaced = true;
9769 break;
9770 }
9771 }
9772 }
9773 if (!replaced) {
9774 mParallelBroadcasts.add(r);
9775 scheduleBroadcastsLocked();
9776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009777 registeredReceivers = null;
9778 NR = 0;
9779 }
9780
9781 // Merge into one list.
9782 int ir = 0;
9783 if (receivers != null) {
9784 // A special case for PACKAGE_ADDED: do not allow the package
9785 // being added to see this broadcast. This prevents them from
9786 // using this as a back door to get run as soon as they are
9787 // installed. Maybe in the future we want to have a special install
9788 // broadcast or such for apps, but we'd like to deliberately make
9789 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009790 String skipPackages[] = null;
9791 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9792 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9793 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9794 Uri data = intent.getData();
9795 if (data != null) {
9796 String pkgName = data.getSchemeSpecificPart();
9797 if (pkgName != null) {
9798 skipPackages = new String[] { pkgName };
9799 }
9800 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009801 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009802 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009803 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009804 if (skipPackages != null && (skipPackages.length > 0)) {
9805 for (String skipPackage : skipPackages) {
9806 if (skipPackage != null) {
9807 int NT = receivers.size();
9808 for (int it=0; it<NT; it++) {
9809 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9810 if (curt.activityInfo.packageName.equals(skipPackage)) {
9811 receivers.remove(it);
9812 it--;
9813 NT--;
9814 }
9815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009816 }
9817 }
9818 }
9819
9820 int NT = receivers != null ? receivers.size() : 0;
9821 int it = 0;
9822 ResolveInfo curt = null;
9823 BroadcastFilter curr = null;
9824 while (it < NT && ir < NR) {
9825 if (curt == null) {
9826 curt = (ResolveInfo)receivers.get(it);
9827 }
9828 if (curr == null) {
9829 curr = registeredReceivers.get(ir);
9830 }
9831 if (curr.getPriority() >= curt.priority) {
9832 // Insert this broadcast record into the final list.
9833 receivers.add(it, curr);
9834 ir++;
9835 curr = null;
9836 it++;
9837 NT++;
9838 } else {
9839 // Skip to the next ResolveInfo in the final list.
9840 it++;
9841 curt = null;
9842 }
9843 }
9844 }
9845 while (ir < NR) {
9846 if (receivers == null) {
9847 receivers = new ArrayList();
9848 }
9849 receivers.add(registeredReceivers.get(ir));
9850 ir++;
9851 }
9852
9853 if ((receivers != null && receivers.size() > 0)
9854 || resultTo != null) {
9855 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9856 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009857 receivers, resultTo, resultCode, resultData, map, ordered,
9858 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009859 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860 TAG, "Enqueueing ordered broadcast " + r
9861 + ": prev had " + mOrderedBroadcasts.size());
9862 if (DEBUG_BROADCAST) {
9863 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009864 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009866 boolean replaced = false;
9867 if (replacePending) {
9868 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9869 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009870 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009871 "***** DROPPING ORDERED: " + intent);
9872 mOrderedBroadcasts.set(i, r);
9873 replaced = true;
9874 break;
9875 }
9876 }
9877 }
9878 if (!replaced) {
9879 mOrderedBroadcasts.add(r);
9880 scheduleBroadcastsLocked();
9881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009882 }
9883
9884 return BROADCAST_SUCCESS;
9885 }
9886
9887 public final int broadcastIntent(IApplicationThread caller,
9888 Intent intent, String resolvedType, IIntentReceiver resultTo,
9889 int resultCode, String resultData, Bundle map,
9890 String requiredPermission, boolean serialized, boolean sticky) {
9891 // Refuse possible leaked file descriptors
9892 if (intent != null && intent.hasFileDescriptors() == true) {
9893 throw new IllegalArgumentException("File descriptors passed in Intent");
9894 }
9895
9896 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009897 int flags = intent.getFlags();
9898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009899 if (!mSystemReady) {
9900 // if the caller really truly claims to know what they're doing, go
9901 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009902 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
9903 intent = new Intent(intent);
9904 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
9905 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -08009906 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009907 + " before boot completion");
9908 throw new IllegalStateException("Cannot broadcast before boot completed");
9909 }
9910 }
9911
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009912 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
9913 throw new IllegalArgumentException(
9914 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
9915 }
9916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009917 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9918 final int callingPid = Binder.getCallingPid();
9919 final int callingUid = Binder.getCallingUid();
9920 final long origId = Binder.clearCallingIdentity();
9921 int res = broadcastIntentLocked(callerApp,
9922 callerApp != null ? callerApp.info.packageName : null,
9923 intent, resolvedType, resultTo,
9924 resultCode, resultData, map, requiredPermission, serialized,
9925 sticky, callingPid, callingUid);
9926 Binder.restoreCallingIdentity(origId);
9927 return res;
9928 }
9929 }
9930
9931 int broadcastIntentInPackage(String packageName, int uid,
9932 Intent intent, String resolvedType, IIntentReceiver resultTo,
9933 int resultCode, String resultData, Bundle map,
9934 String requiredPermission, boolean serialized, boolean sticky) {
9935 synchronized(this) {
9936 final long origId = Binder.clearCallingIdentity();
9937 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
9938 resultTo, resultCode, resultData, map, requiredPermission,
9939 serialized, sticky, -1, uid);
9940 Binder.restoreCallingIdentity(origId);
9941 return res;
9942 }
9943 }
9944
9945 public final void unbroadcastIntent(IApplicationThread caller,
9946 Intent intent) {
9947 // Refuse possible leaked file descriptors
9948 if (intent != null && intent.hasFileDescriptors() == true) {
9949 throw new IllegalArgumentException("File descriptors passed in Intent");
9950 }
9951
9952 synchronized(this) {
9953 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
9954 != PackageManager.PERMISSION_GRANTED) {
9955 String msg = "Permission Denial: unbroadcastIntent() from pid="
9956 + Binder.getCallingPid()
9957 + ", uid=" + Binder.getCallingUid()
9958 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009959 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009960 throw new SecurityException(msg);
9961 }
9962 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9963 if (list != null) {
9964 int N = list.size();
9965 int i;
9966 for (i=0; i<N; i++) {
9967 if (intent.filterEquals(list.get(i))) {
9968 list.remove(i);
9969 break;
9970 }
9971 }
9972 }
9973 }
9974 }
9975
9976 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
9977 String resultData, Bundle resultExtras, boolean resultAbort,
9978 boolean explicit) {
9979 if (mOrderedBroadcasts.size() == 0) {
9980 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009981 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009982 }
9983 return false;
9984 }
9985 BroadcastRecord r = mOrderedBroadcasts.get(0);
9986 if (r.receiver == null) {
9987 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009988 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009989 }
9990 return false;
9991 }
9992 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009993 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009994 return false;
9995 }
9996 int state = r.state;
9997 r.state = r.IDLE;
9998 if (state == r.IDLE) {
9999 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010000 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 }
10002 }
10003 r.receiver = null;
10004 r.intent.setComponent(null);
10005 if (r.curApp != null) {
10006 r.curApp.curReceiver = null;
10007 }
10008 if (r.curFilter != null) {
10009 r.curFilter.receiverList.curBroadcast = null;
10010 }
10011 r.curFilter = null;
10012 r.curApp = null;
10013 r.curComponent = null;
10014 r.curReceiver = null;
10015 mPendingBroadcast = null;
10016
10017 r.resultCode = resultCode;
10018 r.resultData = resultData;
10019 r.resultExtras = resultExtras;
10020 r.resultAbort = resultAbort;
10021
10022 // We will process the next receiver right now if this is finishing
10023 // an app receiver (which is always asynchronous) or after we have
10024 // come back from calling a receiver.
10025 return state == BroadcastRecord.APP_RECEIVE
10026 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10027 }
10028
10029 public void finishReceiver(IBinder who, int resultCode, String resultData,
10030 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010031 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032
10033 // Refuse possible leaked file descriptors
10034 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10035 throw new IllegalArgumentException("File descriptors passed in Bundle");
10036 }
10037
10038 boolean doNext;
10039
10040 final long origId = Binder.clearCallingIdentity();
10041
10042 synchronized(this) {
10043 doNext = finishReceiverLocked(
10044 who, resultCode, resultData, resultExtras, resultAbort, true);
10045 }
10046
10047 if (doNext) {
10048 processNextBroadcast(false);
10049 }
10050 trimApplications();
10051
10052 Binder.restoreCallingIdentity(origId);
10053 }
10054
10055 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10056 if (r.nextReceiver > 0) {
10057 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10058 if (curReceiver instanceof BroadcastFilter) {
10059 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010060 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010061 System.identityHashCode(r),
10062 r.intent.getAction(),
10063 r.nextReceiver - 1,
10064 System.identityHashCode(bf));
10065 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010066 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067 System.identityHashCode(r),
10068 r.intent.getAction(),
10069 r.nextReceiver - 1,
10070 ((ResolveInfo)curReceiver).toString());
10071 }
10072 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010073 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010074 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010075 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010076 System.identityHashCode(r),
10077 r.intent.getAction(),
10078 r.nextReceiver,
10079 "NONE");
10080 }
10081 }
10082
10083 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010084 ProcessRecord app = null;
10085 String anrMessage = null;
10086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010087 synchronized (this) {
10088 if (mOrderedBroadcasts.size() == 0) {
10089 return;
10090 }
10091 long now = SystemClock.uptimeMillis();
10092 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010093 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010094 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010095 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010096 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010097 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010098 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099 return;
10100 }
10101
Joe Onorato8a9b2202010-02-26 18:56:32 -080010102 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010103 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010104 r.anrCount++;
10105
10106 // Current receiver has passed its expiration date.
10107 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010108 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010109 return;
10110 }
10111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010113 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 logBroadcastReceiverDiscard(r);
10115 if (curReceiver instanceof BroadcastFilter) {
10116 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10117 if (bf.receiverList.pid != 0
10118 && bf.receiverList.pid != MY_PID) {
10119 synchronized (this.mPidsSelfLocked) {
10120 app = this.mPidsSelfLocked.get(
10121 bf.receiverList.pid);
10122 }
10123 }
10124 } else {
10125 app = r.curApp;
10126 }
10127
10128 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010129 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130 }
10131
10132 if (mPendingBroadcast == r) {
10133 mPendingBroadcast = null;
10134 }
10135
10136 // Move on to the next receiver.
10137 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10138 r.resultExtras, r.resultAbort, true);
10139 scheduleBroadcastsLocked();
10140 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010141
10142 if (anrMessage != null) {
10143 appNotResponding(app, null, null, anrMessage);
10144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010145 }
10146
10147 private final void processCurBroadcastLocked(BroadcastRecord r,
10148 ProcessRecord app) throws RemoteException {
10149 if (app.thread == null) {
10150 throw new RemoteException();
10151 }
10152 r.receiver = app.thread.asBinder();
10153 r.curApp = app;
10154 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010155 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010156
10157 // Tell the application to launch this receiver.
10158 r.intent.setComponent(r.curComponent);
10159
10160 boolean started = false;
10161 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010162 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010163 "Delivering to component " + r.curComponent
10164 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010165 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010166 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10167 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10168 started = true;
10169 } finally {
10170 if (!started) {
10171 r.receiver = null;
10172 r.curApp = null;
10173 app.curReceiver = null;
10174 }
10175 }
10176
10177 }
10178
10179 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010180 Intent intent, int resultCode, String data, Bundle extras,
10181 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 if (app != null && app.thread != null) {
10183 // If we have an app thread, do the call through that so it is
10184 // correctly ordered with other one-way calls.
10185 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010186 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010187 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010188 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010189 }
10190 }
10191
10192 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10193 BroadcastFilter filter, boolean ordered) {
10194 boolean skip = false;
10195 if (filter.requiredPermission != null) {
10196 int perm = checkComponentPermission(filter.requiredPermission,
10197 r.callingPid, r.callingUid, -1);
10198 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010199 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010200 + r.intent.toString()
10201 + " from " + r.callerPackage + " (pid="
10202 + r.callingPid + ", uid=" + r.callingUid + ")"
10203 + " requires " + filter.requiredPermission
10204 + " due to registered receiver " + filter);
10205 skip = true;
10206 }
10207 }
10208 if (r.requiredPermission != null) {
10209 int perm = checkComponentPermission(r.requiredPermission,
10210 filter.receiverList.pid, filter.receiverList.uid, -1);
10211 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010212 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 + r.intent.toString()
10214 + " to " + filter.receiverList.app
10215 + " (pid=" + filter.receiverList.pid
10216 + ", uid=" + filter.receiverList.uid + ")"
10217 + " requires " + r.requiredPermission
10218 + " due to sender " + r.callerPackage
10219 + " (uid " + r.callingUid + ")");
10220 skip = true;
10221 }
10222 }
10223
10224 if (!skip) {
10225 // If this is not being sent as an ordered broadcast, then we
10226 // don't want to touch the fields that keep track of the current
10227 // state of ordered broadcasts.
10228 if (ordered) {
10229 r.receiver = filter.receiverList.receiver.asBinder();
10230 r.curFilter = filter;
10231 filter.receiverList.curBroadcast = r;
10232 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010233 if (filter.receiverList.app != null) {
10234 // Bump hosting application to no longer be in background
10235 // scheduling class. Note that we can't do that if there
10236 // isn't an app... but we can only be in that case for
10237 // things that directly call the IActivityManager API, which
10238 // are already core system stuff so don't matter for this.
10239 r.curApp = filter.receiverList.app;
10240 filter.receiverList.app.curReceiver = r;
10241 updateOomAdjLocked();
10242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010243 }
10244 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010245 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010246 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010247 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010248 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 }
10250 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10251 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010252 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010253 if (ordered) {
10254 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10255 }
10256 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010257 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010258 if (ordered) {
10259 r.receiver = null;
10260 r.curFilter = null;
10261 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010262 if (filter.receiverList.app != null) {
10263 filter.receiverList.app.curReceiver = null;
10264 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010265 }
10266 }
10267 }
10268 }
10269
Dianne Hackborn12527f92009-11-11 17:39:50 -080010270 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10271 if (r.callingUid < 0) {
10272 // This was from a registerReceiver() call; ignore it.
10273 return;
10274 }
10275 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10276 MAX_BROADCAST_HISTORY-1);
10277 r.finishTime = SystemClock.uptimeMillis();
10278 mBroadcastHistory[0] = r;
10279 }
10280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 private final void processNextBroadcast(boolean fromMsg) {
10282 synchronized(this) {
10283 BroadcastRecord r;
10284
Joe Onorato8a9b2202010-02-26 18:56:32 -080010285 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010286 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010287 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010288
10289 updateCpuStats();
10290
10291 if (fromMsg) {
10292 mBroadcastsScheduled = false;
10293 }
10294
10295 // First, deliver any non-serialized broadcasts right away.
10296 while (mParallelBroadcasts.size() > 0) {
10297 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010298 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010300 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010301 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 for (int i=0; i<N; i++) {
10303 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010304 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010305 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010306 + target + ": " + r);
10307 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10308 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010309 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010310 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010311 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010312 }
10313
10314 // Now take care of the next serialized one...
10315
10316 // If we are waiting for a process to come up to handle the next
10317 // broadcast, then do nothing at this point. Just in case, we
10318 // check that the process we're waiting for still exists.
10319 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010320 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010321 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010322 + mPendingBroadcast.curApp);
10323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010324
10325 boolean isDead;
10326 synchronized (mPidsSelfLocked) {
10327 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10328 }
10329 if (!isDead) {
10330 // It's still alive, so keep waiting
10331 return;
10332 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010333 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010334 + " died before responding to broadcast");
10335 mPendingBroadcast = null;
10336 }
10337 }
10338
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010339 boolean looped = false;
10340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010341 do {
10342 if (mOrderedBroadcasts.size() == 0) {
10343 // No more broadcasts pending, so all done!
10344 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010345 if (looped) {
10346 // If we had finished the last ordered broadcast, then
10347 // make sure all processes have correct oom and sched
10348 // adjustments.
10349 updateOomAdjLocked();
10350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010351 return;
10352 }
10353 r = mOrderedBroadcasts.get(0);
10354 boolean forceReceive = false;
10355
10356 // Ensure that even if something goes awry with the timeout
10357 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010358 // and continue to make progress.
10359 //
10360 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10361 // receivers don't get executed with with timeouts. They're intended for
10362 // one time heavy lifting after system upgrades and can take
10363 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010364 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010365 if (mSystemReady && r.dispatchTime > 0) {
10366 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 if ((numReceivers > 0) &&
10368 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010369 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 + " now=" + now
10371 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010372 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 + " intent=" + r.intent
10374 + " numReceivers=" + numReceivers
10375 + " nextReceiver=" + r.nextReceiver
10376 + " state=" + r.state);
10377 broadcastTimeout(); // forcibly finish this broadcast
10378 forceReceive = true;
10379 r.state = BroadcastRecord.IDLE;
10380 }
10381 }
10382
10383 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010384 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010385 "processNextBroadcast() called when not idle (state="
10386 + r.state + ")");
10387 return;
10388 }
10389
10390 if (r.receivers == null || r.nextReceiver >= numReceivers
10391 || r.resultAbort || forceReceive) {
10392 // No more receivers for this broadcast! Send the final
10393 // result if requested...
10394 if (r.resultTo != null) {
10395 try {
10396 if (DEBUG_BROADCAST) {
10397 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010398 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010399 + " seq=" + seq + " app=" + r.callerApp);
10400 }
10401 performReceive(r.callerApp, r.resultTo,
10402 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010403 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010404 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010405 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010406 }
10407 }
10408
Joe Onorato8a9b2202010-02-26 18:56:32 -080010409 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010410 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10411
Joe Onorato8a9b2202010-02-26 18:56:32 -080010412 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010413 + r);
10414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010415 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010416 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010417 mOrderedBroadcasts.remove(0);
10418 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010419 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010420 continue;
10421 }
10422 } while (r == null);
10423
10424 // Get the next receiver...
10425 int recIdx = r.nextReceiver++;
10426
10427 // Keep track of when this receiver started, and make sure there
10428 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010429 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010431 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010432
Joe Onorato8a9b2202010-02-26 18:56:32 -080010433 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010434 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010435 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010436 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010437 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010438 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010439 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010440 }
10441
10442 Object nextReceiver = r.receivers.get(recIdx);
10443 if (nextReceiver instanceof BroadcastFilter) {
10444 // Simple case: this is a registered receiver who gets
10445 // a direct call.
10446 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010447 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010448 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010449 + filter + ": " + r);
10450 deliverToRegisteredReceiver(r, filter, r.ordered);
10451 if (r.receiver == null || !r.ordered) {
10452 // The receiver has already finished, so schedule to
10453 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010454 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10455 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 r.state = BroadcastRecord.IDLE;
10457 scheduleBroadcastsLocked();
10458 }
10459 return;
10460 }
10461
10462 // Hard case: need to instantiate the receiver, possibly
10463 // starting its application process to host it.
10464
10465 ResolveInfo info =
10466 (ResolveInfo)nextReceiver;
10467
10468 boolean skip = false;
10469 int perm = checkComponentPermission(info.activityInfo.permission,
10470 r.callingPid, r.callingUid,
10471 info.activityInfo.exported
10472 ? -1 : info.activityInfo.applicationInfo.uid);
10473 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010474 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010475 + r.intent.toString()
10476 + " from " + r.callerPackage + " (pid=" + r.callingPid
10477 + ", uid=" + r.callingUid + ")"
10478 + " requires " + info.activityInfo.permission
10479 + " due to receiver " + info.activityInfo.packageName
10480 + "/" + info.activityInfo.name);
10481 skip = true;
10482 }
10483 if (r.callingUid != Process.SYSTEM_UID &&
10484 r.requiredPermission != null) {
10485 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010486 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010487 checkPermission(r.requiredPermission,
10488 info.activityInfo.applicationInfo.packageName);
10489 } catch (RemoteException e) {
10490 perm = PackageManager.PERMISSION_DENIED;
10491 }
10492 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010493 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010494 + r.intent + " to "
10495 + info.activityInfo.applicationInfo.packageName
10496 + " requires " + r.requiredPermission
10497 + " due to sender " + r.callerPackage
10498 + " (uid " + r.callingUid + ")");
10499 skip = true;
10500 }
10501 }
10502 if (r.curApp != null && r.curApp.crashing) {
10503 // If the target process is crashing, just skip it.
10504 skip = true;
10505 }
10506
10507 if (skip) {
10508 r.receiver = null;
10509 r.curFilter = null;
10510 r.state = BroadcastRecord.IDLE;
10511 scheduleBroadcastsLocked();
10512 return;
10513 }
10514
10515 r.state = BroadcastRecord.APP_RECEIVE;
10516 String targetProcess = info.activityInfo.processName;
10517 r.curComponent = new ComponentName(
10518 info.activityInfo.applicationInfo.packageName,
10519 info.activityInfo.name);
10520 r.curReceiver = info.activityInfo;
10521
10522 // Is this receiver's application already running?
10523 ProcessRecord app = getProcessRecordLocked(targetProcess,
10524 info.activityInfo.applicationInfo.uid);
10525 if (app != null && app.thread != null) {
10526 try {
10527 processCurBroadcastLocked(r, app);
10528 return;
10529 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010530 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 + r.curComponent, e);
10532 }
10533
10534 // If a dead object exception was thrown -- fall through to
10535 // restart the application.
10536 }
10537
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010538 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 if ((r.curApp=startProcessLocked(targetProcess,
10540 info.activityInfo.applicationInfo, true,
10541 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010542 "broadcast", r.curComponent,
10543 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10544 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010545 // Ah, this recipient is unavailable. Finish it if necessary,
10546 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010547 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 + info.activityInfo.applicationInfo.packageName + "/"
10549 + info.activityInfo.applicationInfo.uid + " for broadcast "
10550 + r.intent + ": process is bad");
10551 logBroadcastReceiverDiscard(r);
10552 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10553 r.resultExtras, r.resultAbort, true);
10554 scheduleBroadcastsLocked();
10555 r.state = BroadcastRecord.IDLE;
10556 return;
10557 }
10558
10559 mPendingBroadcast = r;
10560 }
10561 }
10562
10563 // =========================================================
10564 // INSTRUMENTATION
10565 // =========================================================
10566
10567 public boolean startInstrumentation(ComponentName className,
10568 String profileFile, int flags, Bundle arguments,
10569 IInstrumentationWatcher watcher) {
10570 // Refuse possible leaked file descriptors
10571 if (arguments != null && arguments.hasFileDescriptors()) {
10572 throw new IllegalArgumentException("File descriptors passed in Bundle");
10573 }
10574
10575 synchronized(this) {
10576 InstrumentationInfo ii = null;
10577 ApplicationInfo ai = null;
10578 try {
10579 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010580 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010582 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 } catch (PackageManager.NameNotFoundException e) {
10584 }
10585 if (ii == null) {
10586 reportStartInstrumentationFailure(watcher, className,
10587 "Unable to find instrumentation info for: " + className);
10588 return false;
10589 }
10590 if (ai == null) {
10591 reportStartInstrumentationFailure(watcher, className,
10592 "Unable to find instrumentation target package: " + ii.targetPackage);
10593 return false;
10594 }
10595
10596 int match = mContext.getPackageManager().checkSignatures(
10597 ii.targetPackage, ii.packageName);
10598 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10599 String msg = "Permission Denial: starting instrumentation "
10600 + className + " from pid="
10601 + Binder.getCallingPid()
10602 + ", uid=" + Binder.getCallingPid()
10603 + " not allowed because package " + ii.packageName
10604 + " does not have a signature matching the target "
10605 + ii.targetPackage;
10606 reportStartInstrumentationFailure(watcher, className, msg);
10607 throw new SecurityException(msg);
10608 }
10609
10610 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010611 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010612 ProcessRecord app = addAppLocked(ai);
10613 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010614 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 app.instrumentationProfileFile = profileFile;
10616 app.instrumentationArguments = arguments;
10617 app.instrumentationWatcher = watcher;
10618 app.instrumentationResultClass = className;
10619 Binder.restoreCallingIdentity(origId);
10620 }
10621
10622 return true;
10623 }
10624
10625 /**
10626 * Report errors that occur while attempting to start Instrumentation. Always writes the
10627 * error to the logs, but if somebody is watching, send the report there too. This enables
10628 * the "am" command to report errors with more information.
10629 *
10630 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10631 * @param cn The component name of the instrumentation.
10632 * @param report The error report.
10633 */
10634 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10635 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010636 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010637 try {
10638 if (watcher != null) {
10639 Bundle results = new Bundle();
10640 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10641 results.putString("Error", report);
10642 watcher.instrumentationStatus(cn, -1, results);
10643 }
10644 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010645 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010646 }
10647 }
10648
10649 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10650 if (app.instrumentationWatcher != null) {
10651 try {
10652 // NOTE: IInstrumentationWatcher *must* be oneway here
10653 app.instrumentationWatcher.instrumentationFinished(
10654 app.instrumentationClass,
10655 resultCode,
10656 results);
10657 } catch (RemoteException e) {
10658 }
10659 }
10660 app.instrumentationWatcher = null;
10661 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010662 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010663 app.instrumentationProfileFile = null;
10664 app.instrumentationArguments = null;
10665
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010666 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 }
10668
10669 public void finishInstrumentation(IApplicationThread target,
10670 int resultCode, Bundle results) {
10671 // Refuse possible leaked file descriptors
10672 if (results != null && results.hasFileDescriptors()) {
10673 throw new IllegalArgumentException("File descriptors passed in Intent");
10674 }
10675
10676 synchronized(this) {
10677 ProcessRecord app = getRecordForAppLocked(target);
10678 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010679 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010680 return;
10681 }
10682 final long origId = Binder.clearCallingIdentity();
10683 finishInstrumentationLocked(app, resultCode, results);
10684 Binder.restoreCallingIdentity(origId);
10685 }
10686 }
10687
10688 // =========================================================
10689 // CONFIGURATION
10690 // =========================================================
10691
10692 public ConfigurationInfo getDeviceConfigurationInfo() {
10693 ConfigurationInfo config = new ConfigurationInfo();
10694 synchronized (this) {
10695 config.reqTouchScreen = mConfiguration.touchscreen;
10696 config.reqKeyboardType = mConfiguration.keyboard;
10697 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010698 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10699 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010700 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10701 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010702 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10703 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010704 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10705 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010706 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 }
10708 return config;
10709 }
10710
10711 public Configuration getConfiguration() {
10712 Configuration ci;
10713 synchronized(this) {
10714 ci = new Configuration(mConfiguration);
10715 }
10716 return ci;
10717 }
10718
10719 public void updateConfiguration(Configuration values) {
10720 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10721 "updateConfiguration()");
10722
10723 synchronized(this) {
10724 if (values == null && mWindowManager != null) {
10725 // sentinel: fetch the current configuration from the window manager
10726 values = mWindowManager.computeNewConfiguration();
10727 }
10728
10729 final long origId = Binder.clearCallingIdentity();
10730 updateConfigurationLocked(values, null);
10731 Binder.restoreCallingIdentity(origId);
10732 }
10733 }
10734
10735 /**
10736 * Do either or both things: (1) change the current configuration, and (2)
10737 * make sure the given activity is running with the (now) current
10738 * configuration. Returns true if the activity has been left running, or
10739 * false if <var>starting</var> is being destroyed to match the new
10740 * configuration.
10741 */
10742 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010743 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010744 int changes = 0;
10745
10746 boolean kept = true;
10747
10748 if (values != null) {
10749 Configuration newConfig = new Configuration(mConfiguration);
10750 changes = newConfig.updateFrom(values);
10751 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010752 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010753 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754 }
10755
Doug Zongker2bec3d42009-12-04 12:52:44 -080010756 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010757
10758 if (values.locale != null) {
10759 saveLocaleLocked(values.locale,
10760 !values.locale.equals(mConfiguration.locale),
10761 values.userSetLocale);
10762 }
10763
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010764 mConfigurationSeq++;
10765 if (mConfigurationSeq <= 0) {
10766 mConfigurationSeq = 1;
10767 }
10768 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010770 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010771
10772 AttributeCache ac = AttributeCache.instance();
10773 if (ac != null) {
10774 ac.updateConfiguration(mConfiguration);
10775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010776
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010777 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10778 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10779 msg.obj = new Configuration(mConfiguration);
10780 mHandler.sendMessage(msg);
10781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010783 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10784 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785 try {
10786 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010787 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010788 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 app.thread.scheduleConfigurationChanged(mConfiguration);
10790 }
10791 } catch (Exception e) {
10792 }
10793 }
10794 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010795 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10796 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10798 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010799 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10800 broadcastIntentLocked(null, null,
10801 new Intent(Intent.ACTION_LOCALE_CHANGED),
10802 null, null, 0, null, null,
10803 null, false, false, MY_PID, Process.SYSTEM_UID);
10804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 }
10806 }
10807
10808 if (changes != 0 && starting == null) {
10809 // If the configuration changed, and the caller is not already
10810 // in the process of starting an activity, then find the top
10811 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010812 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010813 }
10814
10815 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010816 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 if (kept) {
10818 // If this didn't result in the starting activity being
10819 // destroyed, then we need to make sure at this point that all
10820 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010821 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010823 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010824 }
10825 }
10826
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010827 if (values != null && mWindowManager != null) {
10828 mWindowManager.setNewConfiguration(mConfiguration);
10829 }
10830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 return kept;
10832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833
10834 /**
10835 * Save the locale. You must be inside a synchronized (this) block.
10836 */
10837 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10838 if(isDiff) {
10839 SystemProperties.set("user.language", l.getLanguage());
10840 SystemProperties.set("user.region", l.getCountry());
10841 }
10842
10843 if(isPersist) {
10844 SystemProperties.set("persist.sys.language", l.getLanguage());
10845 SystemProperties.set("persist.sys.country", l.getCountry());
10846 SystemProperties.set("persist.sys.localevar", l.getVariant());
10847 }
10848 }
10849
10850 // =========================================================
10851 // LIFETIME MANAGEMENT
10852 // =========================================================
10853
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010854 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
10855 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010856 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010857 // This adjustment has already been computed. If we are calling
10858 // from the top, we may have already computed our adjustment with
10859 // an earlier hidden adjustment that isn't really for us... if
10860 // so, use the new hidden adjustment.
10861 if (!recursed && app.hidden) {
10862 app.curAdj = hiddenAdj;
10863 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 return app.curAdj;
10865 }
10866
10867 if (app.thread == null) {
10868 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010869 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010870 return (app.curAdj=EMPTY_APP_ADJ);
10871 }
10872
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010873 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
10874 // The max adjustment doesn't allow this app to be anything
10875 // below foreground, so it is not worth doing work for it.
10876 app.adjType = "fixed";
10877 app.adjSeq = mAdjSeq;
10878 app.curRawAdj = app.maxAdj;
10879 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
10880 return (app.curAdj=app.maxAdj);
10881 }
10882
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010883 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010884 app.adjSource = null;
10885 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010886 app.empty = false;
10887 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010888
The Android Open Source Project4df24232009-03-05 14:34:35 -080010889 // Determine the importance of the process, starting with most
10890 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010892 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010894 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010895 // The last app on the list is the foreground app.
10896 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010897 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010898 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010899 } else if (app.instrumentationClass != null) {
10900 // Don't want to kill running instrumentation.
10901 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010902 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010903 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010904 } else if (app.persistentActivities > 0) {
10905 // Special persistent activities... shouldn't be used these days.
10906 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010907 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010908 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010909 } else if (app.curReceiver != null ||
10910 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
10911 // An app that is currently receiving a broadcast also
10912 // counts as being in the foreground.
10913 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010914 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010915 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010916 } else if (app.executingServices.size() > 0) {
10917 // An app that is currently executing a service callback also
10918 // counts as being in the foreground.
10919 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010920 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010921 app.adjType = "exec-service";
10922 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010924 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010925 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010926 app.adjType = "foreground-service";
10927 } else if (app.forcingToForeground != null) {
10928 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010929 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010930 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010931 app.adjType = "force-foreground";
10932 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010933 } else if (app == mHeavyWeightProcess) {
10934 // We don't want to kill the current heavy-weight process.
10935 adj = HEAVY_WEIGHT_APP_ADJ;
10936 schedGroup = Process.THREAD_GROUP_DEFAULT;
10937 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080010938 } else if (app == mHomeProcess) {
10939 // This process is hosting what we currently consider to be the
10940 // home app, so we don't want to let it go into the background.
10941 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010942 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010943 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 } else if ((N=app.activities.size()) != 0) {
10945 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010946 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010947 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010948 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010949 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010950 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010952 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010953 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010954 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010955 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010956 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010957 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010958 break;
10959 }
10960 }
10961 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010962 // A very not-needed process. If this is lower in the lru list,
10963 // we will push it in to the empty bucket.
10964 app.hidden = true;
10965 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010966 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010967 adj = hiddenAdj;
10968 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 }
10970
Joe Onorato8a9b2202010-02-26 18:56:32 -080010971 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010972
The Android Open Source Project4df24232009-03-05 14:34:35 -080010973 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010974 // there are applications dependent on our services or providers, but
10975 // this gives us a baseline and makes sure we don't get into an
10976 // infinite recursion.
10977 app.adjSeq = mAdjSeq;
10978 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979
Christopher Tate6fa95972009-06-05 18:43:55 -070010980 if (mBackupTarget != null && app == mBackupTarget.app) {
10981 // If possible we want to avoid killing apps while they're being backed up
10982 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010983 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070010984 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010985 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010986 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070010987 }
10988 }
10989
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010990 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
10991 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992 final long now = SystemClock.uptimeMillis();
10993 // This process is more important if the top activity is
10994 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010995 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010997 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998 if (s.startRequested) {
10999 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11000 // This service has seen some activity within
11001 // recent memory, so we will keep its process ahead
11002 // of the background processes.
11003 if (adj > SECONDARY_SERVER_ADJ) {
11004 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011005 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011006 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 }
11008 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011009 // If we have let the service slide into the background
11010 // state, still have some text describing what it is doing
11011 // even though the service no longer has an impact.
11012 if (adj > SECONDARY_SERVER_ADJ) {
11013 app.adjType = "started-bg-services";
11014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011015 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011016 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11017 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 Iterator<ConnectionRecord> kt
11019 = s.connections.values().iterator();
11020 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11021 // XXX should compute this based on the max of
11022 // all connected clients.
11023 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011024 if (cr.binding.client == app) {
11025 // Binding to ourself is not interesting.
11026 continue;
11027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011028 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11029 ProcessRecord client = cr.binding.client;
11030 int myHiddenAdj = hiddenAdj;
11031 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011032 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 myHiddenAdj = client.hiddenAdj;
11034 } else {
11035 myHiddenAdj = VISIBLE_APP_ADJ;
11036 }
11037 }
11038 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011039 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011041 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011043 if (!client.hidden) {
11044 app.hidden = false;
11045 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011046 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011047 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11048 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011049 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011050 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011051 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011052 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11053 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11054 schedGroup = Process.THREAD_GROUP_DEFAULT;
11055 }
11056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011058 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011060 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011061 //}
11062 if (a != null && adj > FOREGROUND_APP_ADJ &&
11063 (a.state == ActivityState.RESUMED
11064 || a.state == ActivityState.PAUSING)) {
11065 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011066 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011067 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011068 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011069 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11070 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011071 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011072 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011073 }
11074 }
11075 }
11076 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011077
11078 // Finally, f this process has active services running in it, we
11079 // would like to avoid killing it unless it would prevent the current
11080 // application from running. By default we put the process in
11081 // with the rest of the background processes; as we scan through
11082 // its services we may bump it up from there.
11083 if (adj > hiddenAdj) {
11084 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011085 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011086 app.adjType = "bg-services";
11087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011088 }
11089
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011090 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11091 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011092 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011093 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11094 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011095 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011096 if (cpr.clients.size() != 0) {
11097 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11098 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11099 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011100 if (client == app) {
11101 // Being our own client is not interesting.
11102 continue;
11103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 int myHiddenAdj = hiddenAdj;
11105 if (myHiddenAdj > client.hiddenAdj) {
11106 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11107 myHiddenAdj = client.hiddenAdj;
11108 } else {
11109 myHiddenAdj = FOREGROUND_APP_ADJ;
11110 }
11111 }
11112 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011113 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 if (adj > clientAdj) {
11115 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011116 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011117 if (!client.hidden) {
11118 app.hidden = false;
11119 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011120 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011121 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11122 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011123 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011124 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011125 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011126 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11127 schedGroup = Process.THREAD_GROUP_DEFAULT;
11128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129 }
11130 }
11131 // If the provider has external (non-framework) process
11132 // dependencies, ensure that its adjustment is at least
11133 // FOREGROUND_APP_ADJ.
11134 if (cpr.externals != 0) {
11135 if (adj > FOREGROUND_APP_ADJ) {
11136 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011137 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011138 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011139 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011140 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141 }
11142 }
11143 }
11144 }
11145
11146 app.curRawAdj = adj;
11147
Joe Onorato8a9b2202010-02-26 18:56:32 -080011148 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11150 if (adj > app.maxAdj) {
11151 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011152 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011153 schedGroup = Process.THREAD_GROUP_DEFAULT;
11154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011155 }
11156
11157 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011158 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011160 return adj;
11161 }
11162
11163 /**
11164 * Ask a given process to GC right now.
11165 */
11166 final void performAppGcLocked(ProcessRecord app) {
11167 try {
11168 app.lastRequestedGc = SystemClock.uptimeMillis();
11169 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011170 if (app.reportLowMemory) {
11171 app.reportLowMemory = false;
11172 app.thread.scheduleLowMemory();
11173 } else {
11174 app.thread.processInBackground();
11175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011176 }
11177 } catch (Exception e) {
11178 // whatever.
11179 }
11180 }
11181
11182 /**
11183 * Returns true if things are idle enough to perform GCs.
11184 */
Josh Bartel7f208742010-02-25 11:01:44 -060011185 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 return mParallelBroadcasts.size() == 0
11187 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011188 && (mSleeping || (mMainStack.mResumedActivity != null &&
11189 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011190 }
11191
11192 /**
11193 * Perform GCs on all processes that are waiting for it, but only
11194 * if things are idle.
11195 */
11196 final void performAppGcsLocked() {
11197 final int N = mProcessesToGc.size();
11198 if (N <= 0) {
11199 return;
11200 }
Josh Bartel7f208742010-02-25 11:01:44 -060011201 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 while (mProcessesToGc.size() > 0) {
11203 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011204 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011205 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11206 <= SystemClock.uptimeMillis()) {
11207 // To avoid spamming the system, we will GC processes one
11208 // at a time, waiting a few seconds between each.
11209 performAppGcLocked(proc);
11210 scheduleAppGcsLocked();
11211 return;
11212 } else {
11213 // It hasn't been long enough since we last GCed this
11214 // process... put it in the list to wait for its time.
11215 addProcessToGcListLocked(proc);
11216 break;
11217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011218 }
11219 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011220
11221 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011222 }
11223 }
11224
11225 /**
11226 * If all looks good, perform GCs on all processes waiting for them.
11227 */
11228 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011229 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 performAppGcsLocked();
11231 return;
11232 }
11233 // Still not idle, wait some more.
11234 scheduleAppGcsLocked();
11235 }
11236
11237 /**
11238 * Schedule the execution of all pending app GCs.
11239 */
11240 final void scheduleAppGcsLocked() {
11241 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011242
11243 if (mProcessesToGc.size() > 0) {
11244 // Schedule a GC for the time to the next process.
11245 ProcessRecord proc = mProcessesToGc.get(0);
11246 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11247
11248 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11249 long now = SystemClock.uptimeMillis();
11250 if (when < (now+GC_TIMEOUT)) {
11251 when = now + GC_TIMEOUT;
11252 }
11253 mHandler.sendMessageAtTime(msg, when);
11254 }
11255 }
11256
11257 /**
11258 * Add a process to the array of processes waiting to be GCed. Keeps the
11259 * list in sorted order by the last GC time. The process can't already be
11260 * on the list.
11261 */
11262 final void addProcessToGcListLocked(ProcessRecord proc) {
11263 boolean added = false;
11264 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11265 if (mProcessesToGc.get(i).lastRequestedGc <
11266 proc.lastRequestedGc) {
11267 added = true;
11268 mProcessesToGc.add(i+1, proc);
11269 break;
11270 }
11271 }
11272 if (!added) {
11273 mProcessesToGc.add(0, proc);
11274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011275 }
11276
11277 /**
11278 * Set up to ask a process to GC itself. This will either do it
11279 * immediately, or put it on the list of processes to gc the next
11280 * time things are idle.
11281 */
11282 final void scheduleAppGcLocked(ProcessRecord app) {
11283 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011284 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 return;
11286 }
11287 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011288 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 scheduleAppGcsLocked();
11290 }
11291 }
11292
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011293 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11294 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11295 if (mLastWakeLockCheckTime == 0) {
11296 doKills = false;
11297 }
11298 if (stats.isScreenOn()) {
11299 doKills = false;
11300 }
11301 final long curRealtime = SystemClock.elapsedRealtime();
11302 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11303 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011304 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011305 doKills = false;
11306 }
11307 int i = mLruProcesses.size();
11308 while (i > 0) {
11309 i--;
11310 ProcessRecord app = mLruProcesses.get(i);
11311 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11312 long wtime;
11313 synchronized (stats) {
11314 wtime = stats.getProcessWakeTime(app.info.uid,
11315 app.pid, curRealtime);
11316 }
11317 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011318 if (false) {
11319 StringBuilder sb = new StringBuilder(128);
11320 sb.append("Wake for ");
11321 app.toShortString(sb);
11322 sb.append(": over ");
11323 TimeUtils.formatDuration(timeSince, sb);
11324 sb.append(" used ");
11325 TimeUtils.formatDuration(timeUsed, sb);
11326 sb.append(" (");
11327 sb.append((timeUsed*100)/timeSince);
11328 sb.append("%)");
11329 Slog.i(TAG, sb.toString());
11330 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011331 // If a process has held a wake lock for more
11332 // than 50% of the time during this period,
11333 // that sounds pad. Kill!
11334 if (doKills && timeSince > 0
11335 && ((timeUsed*100)/timeSince) >= 50) {
11336 Slog.i(TAG, "Excessive wake lock in " + app.processName
11337 + " (pid " + app.pid + "): held " + timeUsed
11338 + " during " + timeSince);
11339 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11340 app.processName, app.setAdj, "excessive wake lock");
11341 Process.killProcessQuiet(app.pid);
11342 } else {
11343 app.lastWakeTime = wtime;
11344 }
11345 }
11346 }
11347 }
11348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011349 private final boolean updateOomAdjLocked(
11350 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11351 app.hiddenAdj = hiddenAdj;
11352
11353 if (app.thread == null) {
11354 return true;
11355 }
11356
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011357 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011358
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011359 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 if (app.curRawAdj != app.setRawAdj) {
11361 if (app.curRawAdj > FOREGROUND_APP_ADJ
11362 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11363 // If this app is transitioning from foreground to
11364 // non-foreground, have it do a gc.
11365 scheduleAppGcLocked(app);
11366 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11367 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11368 // Likewise do a gc when an app is moving in to the
11369 // background (such as a service stopping).
11370 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011371 // And note its current wake lock time.
11372 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11373 synchronized (stats) {
11374 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11375 app.pid, SystemClock.elapsedRealtime());
11376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011377 }
11378 app.setRawAdj = app.curRawAdj;
11379 }
11380 if (adj != app.setAdj) {
11381 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011382 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011383 TAG, "Set app " + app.processName +
11384 " oom adj to " + adj);
11385 app.setAdj = adj;
11386 } else {
11387 return false;
11388 }
11389 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011390 if (app.setSchedGroup != app.curSchedGroup) {
11391 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011392 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011393 "Setting process group of " + app.processName
11394 + " to " + app.curSchedGroup);
11395 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011396 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011397 try {
11398 Process.setProcessGroup(app.pid, app.curSchedGroup);
11399 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011400 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011401 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011402 e.printStackTrace();
11403 } finally {
11404 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011405 }
11406 }
11407 if (false) {
11408 if (app.thread != null) {
11409 try {
11410 app.thread.setSchedulingGroup(app.curSchedGroup);
11411 } catch (RemoteException e) {
11412 }
11413 }
11414 }
11415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011416 }
11417
11418 return true;
11419 }
11420
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011421 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011422 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011423 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011424 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011425 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011426 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011427 }
11428 }
11429 return resumedActivity;
11430 }
11431
11432 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011433 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11435 int curAdj = app.curAdj;
11436 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11437 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11438
11439 mAdjSeq++;
11440
11441 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11442 if (res) {
11443 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11444 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11445 if (nowHidden != wasHidden) {
11446 // Changed to/from hidden state, so apps after it in the LRU
11447 // list may also be changed.
11448 updateOomAdjLocked();
11449 }
11450 }
11451 return res;
11452 }
11453
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011454 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011455 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011456 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011457 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11458
11459 if (false) {
11460 RuntimeException e = new RuntimeException();
11461 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011462 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011463 }
11464
11465 mAdjSeq++;
11466
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011467 // Let's determine how many processes we have running vs.
11468 // how many slots we have for background processes; we may want
11469 // to put multiple processes in a slot of there are enough of
11470 // them.
11471 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11472 int factor = (mLruProcesses.size()-4)/numSlots;
11473 if (factor < 1) factor = 1;
11474 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011475 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 // First try updating the OOM adjustment for each of the
11478 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011479 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011480 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11481 while (i > 0) {
11482 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011483 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011484 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011486 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011487 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011488 step++;
11489 if (step >= factor) {
11490 step = 0;
11491 curHiddenAdj++;
11492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011493 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011494 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011495 if (!app.killedBackground) {
11496 numHidden++;
11497 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011498 Slog.i(TAG, "No longer want " + app.processName
11499 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011500 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11501 app.processName, app.setAdj, "too many background");
11502 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011503 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011504 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011505 }
11506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011507 } else {
11508 didOomAdj = false;
11509 }
11510 }
11511
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011512 // If we return false, we will fall back on killing processes to
11513 // have a fixed limit. Do this if a limit has been requested; else
11514 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011515 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11516 }
11517
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011518 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011519 synchronized (this) {
11520 int i;
11521
11522 // First remove any unused application processes whose package
11523 // has been removed.
11524 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11525 final ProcessRecord app = mRemovedProcesses.get(i);
11526 if (app.activities.size() == 0
11527 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011528 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011529 TAG, "Exiting empty application process "
11530 + app.processName + " ("
11531 + (app.thread != null ? app.thread.asBinder() : null)
11532 + ")\n");
11533 if (app.pid > 0 && app.pid != MY_PID) {
11534 Process.killProcess(app.pid);
11535 } else {
11536 try {
11537 app.thread.scheduleExit();
11538 } catch (Exception e) {
11539 // Ignore exceptions.
11540 }
11541 }
11542 cleanUpApplicationRecordLocked(app, false, -1);
11543 mRemovedProcesses.remove(i);
11544
11545 if (app.persistent) {
11546 if (app.persistent) {
11547 addAppLocked(app.info);
11548 }
11549 }
11550 }
11551 }
11552
11553 // Now try updating the OOM adjustment for each of the
11554 // application processes based on their current state.
11555 // If the setOomAdj() API is not supported, then go with our
11556 // back-up plan...
11557 if (!updateOomAdjLocked()) {
11558
11559 // Count how many processes are running services.
11560 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011561 for (i=mLruProcesses.size()-1; i>=0; i--) {
11562 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563
11564 if (app.persistent || app.services.size() != 0
11565 || app.curReceiver != null
11566 || app.persistentActivities > 0) {
11567 // Don't count processes holding services against our
11568 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011569 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 TAG, "Not trimming app " + app + " with services: "
11571 + app.services);
11572 numServiceProcs++;
11573 }
11574 }
11575
11576 int curMaxProcs = mProcessLimit;
11577 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11578 if (mAlwaysFinishActivities) {
11579 curMaxProcs = 1;
11580 }
11581 curMaxProcs += numServiceProcs;
11582
11583 // Quit as many processes as we can to get down to the desired
11584 // process count. First remove any processes that no longer
11585 // have activites running in them.
11586 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011587 i<mLruProcesses.size()
11588 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011589 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011590 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011591 // Quit an application only if it is not currently
11592 // running any activities.
11593 if (!app.persistent && app.activities.size() == 0
11594 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011595 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011596 TAG, "Exiting empty application process "
11597 + app.processName + " ("
11598 + (app.thread != null ? app.thread.asBinder() : null)
11599 + ")\n");
11600 if (app.pid > 0 && app.pid != MY_PID) {
11601 Process.killProcess(app.pid);
11602 } else {
11603 try {
11604 app.thread.scheduleExit();
11605 } catch (Exception e) {
11606 // Ignore exceptions.
11607 }
11608 }
11609 // todo: For now we assume the application is not buggy
11610 // or evil, and will quit as a result of our request.
11611 // Eventually we need to drive this off of the death
11612 // notification, and kill the process if it takes too long.
11613 cleanUpApplicationRecordLocked(app, false, i);
11614 i--;
11615 }
11616 }
11617
11618 // If we still have too many processes, now from the least
11619 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011620 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011621 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011622 " of " + curMaxProcs + " processes");
11623 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011624 i<mLruProcesses.size()
11625 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011626 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011627 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 // Quit the application only if we have a state saved for
11629 // all of its activities.
11630 boolean canQuit = !app.persistent && app.curReceiver == null
11631 && app.services.size() == 0
11632 && app.persistentActivities == 0;
11633 int NUMA = app.activities.size();
11634 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011635 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 TAG, "Looking to quit " + app.processName);
11637 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011638 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011639 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011640 TAG, " " + r.intent.getComponent().flattenToShortString()
11641 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11642 canQuit = (r.haveState || !r.stateNotNeeded)
11643 && !r.visible && r.stopped;
11644 }
11645 if (canQuit) {
11646 // Finish all of the activities, and then the app itself.
11647 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011648 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011649 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011650 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011651 }
11652 r.resultTo = null;
11653 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011654 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011655 + app.processName + " ("
11656 + (app.thread != null ? app.thread.asBinder() : null)
11657 + ")\n");
11658 if (app.pid > 0 && app.pid != MY_PID) {
11659 Process.killProcess(app.pid);
11660 } else {
11661 try {
11662 app.thread.scheduleExit();
11663 } catch (Exception e) {
11664 // Ignore exceptions.
11665 }
11666 }
11667 // todo: For now we assume the application is not buggy
11668 // or evil, and will quit as a result of our request.
11669 // Eventually we need to drive this off of the death
11670 // notification, and kill the process if it takes too long.
11671 cleanUpApplicationRecordLocked(app, false, i);
11672 i--;
11673 //dump();
11674 }
11675 }
11676
11677 }
11678
11679 int curMaxActivities = MAX_ACTIVITIES;
11680 if (mAlwaysFinishActivities) {
11681 curMaxActivities = 1;
11682 }
11683
11684 // Finally, if there are too many activities now running, try to
11685 // finish as many as we can to get back down to the limit.
11686 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011687 i<mMainStack.mLRUActivities.size()
11688 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011690 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011691 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011692
11693 // We can finish this one if we have its icicle saved and
11694 // it is not persistent.
11695 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11696 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011697 final int origSize = mMainStack.mLRUActivities.size();
11698 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011699
11700 // This will remove it from the LRU list, so keep
11701 // our index at the same value. Note that this check to
11702 // see if the size changes is just paranoia -- if
11703 // something unexpected happens, we don't want to end up
11704 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011705 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 i--;
11707 }
11708 }
11709 }
11710 }
11711 }
11712
11713 /** This method sends the specified signal to each of the persistent apps */
11714 public void signalPersistentProcesses(int sig) throws RemoteException {
11715 if (sig != Process.SIGNAL_USR1) {
11716 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11717 }
11718
11719 synchronized (this) {
11720 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11721 != PackageManager.PERMISSION_GRANTED) {
11722 throw new SecurityException("Requires permission "
11723 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11724 }
11725
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011726 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11727 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011728 if (r.thread != null && r.persistent) {
11729 Process.sendSignal(r.pid, sig);
11730 }
11731 }
11732 }
11733 }
11734
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011735 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011736 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011737
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011738 try {
11739 synchronized (this) {
11740 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11741 // its own permission.
11742 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11743 != PackageManager.PERMISSION_GRANTED) {
11744 throw new SecurityException("Requires permission "
11745 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011746 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011747
11748 if (start && fd == null) {
11749 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011750 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011751
11752 ProcessRecord proc = null;
11753 try {
11754 int pid = Integer.parseInt(process);
11755 synchronized (mPidsSelfLocked) {
11756 proc = mPidsSelfLocked.get(pid);
11757 }
11758 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011759 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011760
11761 if (proc == null) {
11762 HashMap<String, SparseArray<ProcessRecord>> all
11763 = mProcessNames.getMap();
11764 SparseArray<ProcessRecord> procs = all.get(process);
11765 if (procs != null && procs.size() > 0) {
11766 proc = procs.valueAt(0);
11767 }
11768 }
11769
11770 if (proc == null || proc.thread == null) {
11771 throw new IllegalArgumentException("Unknown process: " + process);
11772 }
11773
11774 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11775 if (isSecure) {
11776 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11777 throw new SecurityException("Process not debuggable: " + proc);
11778 }
11779 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011780
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011781 proc.thread.profilerControl(start, path, fd);
11782 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011783 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011784 }
11785 } catch (RemoteException e) {
11786 throw new IllegalStateException("Process disappeared");
11787 } finally {
11788 if (fd != null) {
11789 try {
11790 fd.close();
11791 } catch (IOException e) {
11792 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011793 }
11794 }
11795 }
11796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11798 public void monitor() {
11799 synchronized (this) { }
11800 }
11801}