blob: c3160744a5c88ad08fee2208bbe1af5fdb76f0f2 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
58import android.content.Intent;
59import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070060import android.content.IIntentReceiver;
61import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070062import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.content.pm.ActivityInfo;
64import android.content.pm.ApplicationInfo;
65import android.content.pm.ConfigurationInfo;
66import android.content.pm.IPackageDataObserver;
67import android.content.pm.IPackageManager;
68import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080069import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070071import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.ProviderInfo;
73import android.content.pm.ResolveInfo;
74import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070075import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.res.Configuration;
77import android.graphics.Bitmap;
78import android.net.Uri;
79import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080080import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070082import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.FileUtils;
87import android.os.Handler;
88import android.os.IBinder;
89import android.os.IPermissionController;
90import android.os.Looper;
91import android.os.Message;
92import android.os.Parcel;
93import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070095import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.RemoteException;
97import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070098import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.SystemClock;
100import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.Config;
103import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800104import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800105import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.util.PrintWriterPrinter;
107import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700108import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.view.Gravity;
110import android.view.LayoutInflater;
111import android.view.View;
112import android.view.WindowManager;
113import android.view.WindowManagerPolicy;
114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.File;
116import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200118import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800119import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.PrintWriter;
121import java.lang.IllegalStateException;
122import java.lang.ref.WeakReference;
123import java.util.ArrayList;
124import java.util.HashMap;
125import java.util.HashSet;
126import java.util.Iterator;
127import java.util.List;
128import java.util.Locale;
129import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700130import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700131import java.util.concurrent.atomic.AtomicBoolean;
132import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133
134public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
135 static final String TAG = "ActivityManager";
136 static final boolean DEBUG = false;
137 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
138 static final boolean DEBUG_SWITCH = localLOGV || false;
139 static final boolean DEBUG_TASKS = localLOGV || false;
140 static final boolean DEBUG_PAUSE = localLOGV || false;
141 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
142 static final boolean DEBUG_TRANSITION = localLOGV || false;
143 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700144 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean DEBUG_SERVICE = localLOGV || false;
146 static final boolean DEBUG_VISBILITY = localLOGV || false;
147 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700148 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800149 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700151 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700152 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700153 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean VALIDATE_TOKENS = false;
155 static final boolean SHOW_ACTIVITY_START_TIME = true;
156
157 // Control over CPU and battery monitoring.
158 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
159 static final boolean MONITOR_CPU_USAGE = true;
160 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
161 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
162 static final boolean MONITOR_THREAD_CPU_USAGE = false;
163
Dianne Hackborn1655be42009-05-08 14:29:01 -0700164 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700165 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 private static final String SYSTEM_SECURE = "ro.secure";
168
169 // This is the maximum number of application processes we would like
170 // to have running. Due to the asynchronous nature of things, we can
171 // temporarily go beyond this limit.
172 static final int MAX_PROCESSES = 2;
173
174 // Set to false to leave processes running indefinitely, relying on
175 // the kernel killing them as resources are required.
176 static final boolean ENFORCE_PROCESS_LIMIT = false;
177
178 // This is the maximum number of activities that we would like to have
179 // running at a given time.
180 static final int MAX_ACTIVITIES = 20;
181
182 // Maximum number of recent tasks that we can remember.
183 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700184
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700185 // Amount of time after a call to stopAppSwitches() during which we will
186 // prevent further untrusted switches from happening.
187 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188
189 // How long we wait for a launched process to attach to the activity manager
190 // before we decide it's never going to come up for real.
191 static final int PROC_START_TIMEOUT = 10*1000;
192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 // How long to wait after going idle before forcing apps to GC.
194 static final int GC_TIMEOUT = 5*1000;
195
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700196 // The minimum amount of time between successive GC requests for a process.
197 static final int GC_MIN_INTERVAL = 60*1000;
198
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700199 // The rate at which we check for apps using excessive wake locks -- 15 mins.
200 static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 // How long we allow a receiver to run before giving up on it.
203 static final int BROADCAST_TIMEOUT = 10*1000;
204
205 // How long we wait for a service to finish executing.
206 static final int SERVICE_TIMEOUT = 20*1000;
207
208 // How long a service needs to be running until restarting its process
209 // is no longer considered to be a relaunch of the service.
210 static final int SERVICE_RESTART_DURATION = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // How long a service needs to be running until it will start back at
213 // SERVICE_RESTART_DURATION after being killed.
214 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
215
216 // Multiplying factor to increase restart duration time by, for each time
217 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
218 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
219
220 // The minimum amount of time between restarting services that we allow.
221 // That is, when multiple services are restarting, we won't allow each
222 // to restart less than this amount of time from the last one.
223 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // Maximum amount of time for there to be no activity on a service before
226 // we consider it non-essential and allow its process to go on the
227 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700228 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
230 // How long we wait until we timeout on key dispatching.
231 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
232
233 // The minimum time we allow between crashes, for us to consider this
234 // application to be bad and stop and its services and reject broadcasts.
235 static final int MIN_CRASH_INTERVAL = 60*1000;
236
237 // How long we wait until we timeout on key dispatching during instrumentation.
238 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
239
240 // OOM adjustments for processes in various states:
241
242 // This is a process without anything currently running in it. Definitely
243 // the first to go! Value set in system/rootdir/init.rc on startup.
244 // This value is initalized in the constructor, careful when refering to
245 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800246 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // This is a process only hosting activities that are not visible,
249 // so it can be killed without any disruption. Value set in
250 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800251 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 static int HIDDEN_APP_MIN_ADJ;
253
The Android Open Source Project4df24232009-03-05 14:34:35 -0800254 // This is a process holding the home application -- we want to try
255 // avoiding killing it, even if it would normally be in the background,
256 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800257 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800258
Christopher Tate6fa95972009-06-05 18:43:55 -0700259 // This is a process currently hosting a backup operation. Killing it
260 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800261 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 // This is a process holding a secondary server -- killing it will not
264 // have much of an impact as far as the user is concerned. Value set in
265 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800266 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700268 // This is a process with a heavy-weight application. It is in the
269 // background, but we want to try to avoid killing it. Value set in
270 // system/rootdir/init.rc on startup.
271 static final int HEAVY_WEIGHT_APP_ADJ;
272
273 // This is a process only hosting components that are perceptible to the
274 // user, and we really want to avoid killing them, but they are not
275 // immediately visible. An example is background music playback. Value set in
276 // system/rootdir/init.rc on startup.
277 static final int PERCEPTIBLE_APP_ADJ;
278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 // This is a process only hosting activities that are visible to the
280 // user, so we'd prefer they don't disappear. Value set in
281 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283
284 // This is the process running the current foreground app. We'd really
285 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
288 // This is a process running a core server, such as telephony. Definitely
289 // don't want to kill it, but doing so is not completely fatal.
290 static final int CORE_SERVER_ADJ = -12;
291
292 // The system process runs at the default adjustment.
293 static final int SYSTEM_ADJ = -16;
294
295 // Memory pages are 4K.
296 static final int PAGE_SIZE = 4*1024;
297
298 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800299 static final int EMPTY_APP_MEM;
300 static final int HIDDEN_APP_MEM;
301 static final int HOME_APP_MEM;
302 static final int BACKUP_APP_MEM;
303 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700304 static final int HEAVY_WEIGHT_APP_MEM;
305 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int VISIBLE_APP_MEM;
307 static final int FOREGROUND_APP_MEM;
308
309 // The minimum number of hidden apps we want to be able to keep around,
310 // without empty apps being able to push them out of memory.
311 static final int MIN_HIDDEN_APPS = 2;
312
Dianne Hackborn8633e682010-04-22 16:03:41 -0700313 // The maximum number of hidden processes we will keep around before
314 // killing them; this is just a control to not let us go too crazy with
315 // keeping around processes on devices with large amounts of RAM.
316 static final int MAX_HIDDEN_APPS = 15;
317
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800318 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700319 // been idle for less than 15 seconds.
320 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800321
322 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700323 // been idle for less than 120 seconds.
324 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800325
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700326 static int getIntProp(String name, boolean allowZero) {
327 String str = SystemProperties.get(name);
328 if (str == null) {
329 throw new IllegalArgumentException("Property not defined: " + name);
330 }
331 int val = Integer.valueOf(str);
332 if (val == 0 && !allowZero) {
333 throw new IllegalArgumentException("Property must not be zero: " + name);
334 }
335 return val;
336 }
337
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800338 static {
339 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700340 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
341 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
342 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
343 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
344 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
345 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
346 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
347 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
348 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
349 // These days we use the last empty slot for hidden apps as well.
350 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
351 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
352 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
353 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
354 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
355 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
356 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
357 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
358 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
359 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
Dan Egnor42471dd2010-01-07 17:25:22 -0800362 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
364 static final String[] EMPTY_STRING_ARRAY = new String[0];
365
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700366 public ActivityStack mMainStack;
367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700369 * Description of a request to start a new activity, which has been held
370 * due to app switches being disabled.
371 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700372 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700373 ActivityRecord r;
374 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700375 Uri[] grantedUriPermissions;
376 int grantedMode;
377 boolean onlyIfNeeded;
378 }
379
380 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
381 = new ArrayList<PendingActivityLaunch>();
382
383 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 * List of all active broadcasts that are to be executed immediately
385 * (without waiting for another broadcast to finish). Currently this only
386 * contains broadcasts to registered receivers, to avoid spinning up
387 * a bunch of processes to execute IntentReceiver components.
388 */
389 final ArrayList<BroadcastRecord> mParallelBroadcasts
390 = new ArrayList<BroadcastRecord>();
391
392 /**
393 * List of all active broadcasts that are to be executed one at a time.
394 * The object at the top of the list is the currently activity broadcasts;
395 * those after it are waiting for the top to finish..
396 */
397 final ArrayList<BroadcastRecord> mOrderedBroadcasts
398 = new ArrayList<BroadcastRecord>();
399
400 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800401 * Historical data of past broadcasts, for debugging.
402 */
403 static final int MAX_BROADCAST_HISTORY = 100;
404 final BroadcastRecord[] mBroadcastHistory
405 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * Set when we current have a BROADCAST_INTENT_MSG in flight.
409 */
410 boolean mBroadcastsScheduled = false;
411
412 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 * Activity we have told the window manager to have key focus.
414 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700415 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700416 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 * List of intents that were used to start the most recent tasks.
418 */
419 final ArrayList<TaskRecord> mRecentTasks
420 = new ArrayList<TaskRecord>();
421
422 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 * All of the applications we currently have running organized by name.
424 * The keys are strings of the application package name (as
425 * returned by the package manager), and the keys are ApplicationRecord
426 * objects.
427 */
428 final ProcessMap<ProcessRecord> mProcessNames
429 = new ProcessMap<ProcessRecord>();
430
431 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700432 * The currently running heavy-weight process, if any.
433 */
434 ProcessRecord mHeavyWeightProcess = null;
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * The last time that various processes have crashed.
438 */
439 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
440
441 /**
442 * Set of applications that we consider to be bad, and will reject
443 * incoming broadcasts from (which the user has no control over).
444 * Processes are added to this set when they have crashed twice within
445 * a minimum amount of time; they are removed from it when they are
446 * later restarted (hopefully due to some user action). The value is the
447 * time it was added to the list.
448 */
449 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
450
451 /**
452 * All of the processes we currently have running organized by pid.
453 * The keys are the pid running the application.
454 *
455 * <p>NOTE: This object is protected by its own lock, NOT the global
456 * activity manager lock!
457 */
458 final SparseArray<ProcessRecord> mPidsSelfLocked
459 = new SparseArray<ProcessRecord>();
460
461 /**
462 * All of the processes that have been forced to be foreground. The key
463 * is the pid of the caller who requested it (we hold a death
464 * link on it).
465 */
466 abstract class ForegroundToken implements IBinder.DeathRecipient {
467 int pid;
468 IBinder token;
469 }
470 final SparseArray<ForegroundToken> mForegroundProcesses
471 = new SparseArray<ForegroundToken>();
472
473 /**
474 * List of records for processes that someone had tried to start before the
475 * system was ready. We don't start them at that point, but ensure they
476 * are started by the time booting is complete.
477 */
478 final ArrayList<ProcessRecord> mProcessesOnHold
479 = new ArrayList<ProcessRecord>();
480
481 /**
482 * List of records for processes that we have started and are waiting
483 * for them to call back. This is really only needed when running in
484 * single processes mode, in which case we do not have a unique pid for
485 * each process.
486 */
487 final ArrayList<ProcessRecord> mStartingProcesses
488 = new ArrayList<ProcessRecord>();
489
490 /**
491 * List of persistent applications that are in the process
492 * of being started.
493 */
494 final ArrayList<ProcessRecord> mPersistentStartingProcesses
495 = new ArrayList<ProcessRecord>();
496
497 /**
498 * Processes that are being forcibly torn down.
499 */
500 final ArrayList<ProcessRecord> mRemovedProcesses
501 = new ArrayList<ProcessRecord>();
502
503 /**
504 * List of running applications, sorted by recent usage.
505 * The first entry in the list is the least recently used.
506 * It contains ApplicationRecord objects. This list does NOT include
507 * any persistent application records (since we never want to exit them).
508 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800509 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 = new ArrayList<ProcessRecord>();
511
512 /**
513 * List of processes that should gc as soon as things are idle.
514 */
515 final ArrayList<ProcessRecord> mProcessesToGc
516 = new ArrayList<ProcessRecord>();
517
518 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800519 * This is the process holding what we currently consider to be
520 * the "home" activity.
521 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700522 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800523
524 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 * Set of PendingResultRecord objects that are currently active.
526 */
527 final HashSet mPendingResultRecords = new HashSet();
528
529 /**
530 * Set of IntentSenderRecord objects that are currently active.
531 */
532 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
533 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
534
535 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700536 * Fingerprints (String.hashCode()) of stack traces that we've
537 * already logged DropBox entries for. Guarded by itself. If
538 * something (rogue user app) forces this over
539 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
540 */
541 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
542 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
543
544 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700545 * Strict Mode background batched logging state.
546 *
547 * The string buffer is guarded by itself, and its lock is also
548 * used to determine if another batched write is already
549 * in-flight.
550 */
551 private final StringBuilder mStrictModeBuffer = new StringBuilder();
552
553 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 * Intent broadcast that we have tried to start, but are
555 * waiting for its application's process to be created. We only
556 * need one (instead of a list) because we always process broadcasts
557 * one at a time, so no others can be started while waiting for this
558 * one.
559 */
560 BroadcastRecord mPendingBroadcast = null;
561
562 /**
563 * Keeps track of all IIntentReceivers that have been registered for
564 * broadcasts. Hash keys are the receiver IBinder, hash value is
565 * a ReceiverList.
566 */
567 final HashMap mRegisteredReceivers = new HashMap();
568
569 /**
570 * Resolver for broadcast intents to registered receivers.
571 * Holds BroadcastFilter (subclass of IntentFilter).
572 */
573 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
574 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
575 @Override
576 protected boolean allowFilterResult(
577 BroadcastFilter filter, List<BroadcastFilter> dest) {
578 IBinder target = filter.receiverList.receiver.asBinder();
579 for (int i=dest.size()-1; i>=0; i--) {
580 if (dest.get(i).receiverList.receiver.asBinder() == target) {
581 return false;
582 }
583 }
584 return true;
585 }
586 };
587
588 /**
589 * State of all active sticky broadcasts. Keys are the action of the
590 * sticky Intent, values are an ArrayList of all broadcasted intents with
591 * that action (which should usually be one).
592 */
593 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
594 new HashMap<String, ArrayList<Intent>>();
595
596 /**
597 * All currently running services.
598 */
599 final HashMap<ComponentName, ServiceRecord> mServices =
600 new HashMap<ComponentName, ServiceRecord>();
601
602 /**
603 * All currently running services indexed by the Intent used to start them.
604 */
605 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
606 new HashMap<Intent.FilterComparison, ServiceRecord>();
607
608 /**
609 * All currently bound service connections. Keys are the IBinder of
610 * the client's IServiceConnection.
611 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700612 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
613 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614
615 /**
616 * List of services that we have been asked to start,
617 * but haven't yet been able to. It is used to hold start requests
618 * while waiting for their corresponding application thread to get
619 * going.
620 */
621 final ArrayList<ServiceRecord> mPendingServices
622 = new ArrayList<ServiceRecord>();
623
624 /**
625 * List of services that are scheduled to restart following a crash.
626 */
627 final ArrayList<ServiceRecord> mRestartingServices
628 = new ArrayList<ServiceRecord>();
629
630 /**
631 * List of services that are in the process of being stopped.
632 */
633 final ArrayList<ServiceRecord> mStoppingServices
634 = new ArrayList<ServiceRecord>();
635
636 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700637 * Backup/restore process management
638 */
639 String mBackupAppName = null;
640 BackupRecord mBackupTarget = null;
641
642 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 * List of PendingThumbnailsRecord objects of clients who are still
644 * waiting to receive all of the thumbnails for a task.
645 */
646 final ArrayList mPendingThumbnails = new ArrayList();
647
648 /**
649 * List of HistoryRecord objects that have been finished and must
650 * still report back to a pending thumbnail receiver.
651 */
652 final ArrayList mCancelledThumbnails = new ArrayList();
653
654 /**
655 * All of the currently running global content providers. Keys are a
656 * string containing the provider name and values are a
657 * ContentProviderRecord object containing the data about it. Note
658 * that a single provider may be published under multiple names, so
659 * there may be multiple entries here for a single one in mProvidersByClass.
660 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700661 final HashMap<String, ContentProviderRecord> mProvidersByName
662 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663
664 /**
665 * All of the currently running global content providers. Keys are a
666 * string containing the provider's implementation class and values are a
667 * ContentProviderRecord object containing the data about it.
668 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700669 final HashMap<String, ContentProviderRecord> mProvidersByClass
670 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671
672 /**
673 * List of content providers who have clients waiting for them. The
674 * application is currently being launched and the provider will be
675 * removed from this list once it is published.
676 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700677 final ArrayList<ContentProviderRecord> mLaunchingProviders
678 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679
680 /**
681 * Global set of specific Uri permissions that have been granted.
682 */
683 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
684 = new SparseArray<HashMap<Uri, UriPermission>>();
685
686 /**
687 * Thread-local storage used to carry caller permissions over through
688 * indirect content-provider access.
689 * @see #ActivityManagerService.openContentUri()
690 */
691 private class Identity {
692 public int pid;
693 public int uid;
694
695 Identity(int _pid, int _uid) {
696 pid = _pid;
697 uid = _uid;
698 }
699 }
700 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
701
702 /**
703 * All information we have collected about the runtime performance of
704 * any user id that can impact battery performance.
705 */
706 final BatteryStatsService mBatteryStatsService;
707
708 /**
709 * information about component usage
710 */
711 final UsageStatsService mUsageStatsService;
712
713 /**
714 * Current configuration information. HistoryRecord objects are given
715 * a reference to this object to indicate which configuration they are
716 * currently running in, so this object must be kept immutable.
717 */
718 Configuration mConfiguration = new Configuration();
719
720 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800721 * Current sequencing integer of the configuration, for skipping old
722 * configurations.
723 */
724 int mConfigurationSeq = 0;
725
726 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700727 * Hardware-reported OpenGLES version.
728 */
729 final int GL_ES_VERSION;
730
731 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 * List of initialization arguments to pass to all processes when binding applications to them.
733 * For example, references to the commonly used services.
734 */
735 HashMap<String, IBinder> mAppBindArgs;
736
737 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700738 * Temporary to avoid allocations. Protected by main lock.
739 */
740 final StringBuilder mStringBuilder = new StringBuilder(256);
741
742 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 * Used to control how we initialize the service.
744 */
745 boolean mStartRunning = false;
746 ComponentName mTopComponent;
747 String mTopAction;
748 String mTopData;
749 boolean mSystemReady = false;
750 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700751 boolean mWaitingUpdate = false;
752 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753
754 Context mContext;
755
756 int mFactoryTest;
757
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700758 boolean mCheckedForSetup;
759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700761 * The time at which we will allow normal application switches again,
762 * after a call to {@link #stopAppSwitches()}.
763 */
764 long mAppSwitchesAllowedTime;
765
766 /**
767 * This is set to true after the first switch after mAppSwitchesAllowedTime
768 * is set; any switches after that will clear the time.
769 */
770 boolean mDidAppSwitch;
771
772 /**
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700773 * Last time (in realtime) at which we checked for wake lock usage.
774 */
775 long mLastWakeLockCheckTime;
776
777 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 * Set while we are wanting to sleep, to prevent any
779 * activities from being started/resumed.
780 */
781 boolean mSleeping = false;
782
783 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700784 * Set if we are shutting down the system, similar to sleeping.
785 */
786 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787
788 /**
789 * Task identifier that activities are currently being started
790 * in. Incremented each time a new task is created.
791 * todo: Replace this with a TokenSpace class that generates non-repeating
792 * integers that won't wrap.
793 */
794 int mCurTask = 1;
795
796 /**
797 * Current sequence id for oom_adj computation traversal.
798 */
799 int mAdjSeq = 0;
800
801 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700802 * Current sequence id for process LRU updating.
803 */
804 int mLruSeq = 0;
805
806 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
808 * is set, indicating the user wants processes started in such a way
809 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
810 * running in each process (thus no pre-initialized process, etc).
811 */
812 boolean mSimpleProcessManagement = false;
813
814 /**
815 * System monitoring: number of processes that died since the last
816 * N procs were started.
817 */
818 int[] mProcDeaths = new int[20];
819
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700820 /**
821 * This is set if we had to do a delayed dexopt of an app before launching
822 * it, to increasing the ANR timeouts in that case.
823 */
824 boolean mDidDexOpt;
825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 String mDebugApp = null;
827 boolean mWaitForDebugger = false;
828 boolean mDebugTransient = false;
829 String mOrigDebugApp = null;
830 boolean mOrigWaitForDebugger = false;
831 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700832 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700834 final RemoteCallbackList<IActivityWatcher> mWatchers
835 = new RemoteCallbackList<IActivityWatcher>();
836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 /**
838 * Callback of last caller to {@link #requestPss}.
839 */
840 Runnable mRequestPssCallback;
841
842 /**
843 * Remaining processes for which we are waiting results from the last
844 * call to {@link #requestPss}.
845 */
846 final ArrayList<ProcessRecord> mRequestPssList
847 = new ArrayList<ProcessRecord>();
848
849 /**
850 * Runtime statistics collection thread. This object's lock is used to
851 * protect all related state.
852 */
853 final Thread mProcessStatsThread;
854
855 /**
856 * Used to collect process stats when showing not responding dialog.
857 * Protected by mProcessStatsThread.
858 */
859 final ProcessStats mProcessStats = new ProcessStats(
860 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700861 final AtomicLong mLastCpuTime = new AtomicLong(0);
862 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 long mLastWriteTime = 0;
865
866 /**
867 * Set to true after the system has finished booting.
868 */
869 boolean mBooted = false;
870
871 int mProcessLimit = 0;
872
873 WindowManagerService mWindowManager;
874
875 static ActivityManagerService mSelf;
876 static ActivityThread mSystemThread;
877
878 private final class AppDeathRecipient implements IBinder.DeathRecipient {
879 final ProcessRecord mApp;
880 final int mPid;
881 final IApplicationThread mAppThread;
882
883 AppDeathRecipient(ProcessRecord app, int pid,
884 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800885 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 TAG, "New death recipient " + this
887 + " for thread " + thread.asBinder());
888 mApp = app;
889 mPid = pid;
890 mAppThread = thread;
891 }
892
893 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800894 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 TAG, "Death received in " + this
896 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 synchronized(ActivityManagerService.this) {
898 appDiedLocked(mApp, mPid, mAppThread);
899 }
900 }
901 }
902
903 static final int SHOW_ERROR_MSG = 1;
904 static final int SHOW_NOT_RESPONDING_MSG = 2;
905 static final int SHOW_FACTORY_ERROR_MSG = 3;
906 static final int UPDATE_CONFIGURATION_MSG = 4;
907 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
908 static final int WAIT_FOR_DEBUGGER_MSG = 6;
909 static final int BROADCAST_INTENT_MSG = 7;
910 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 static final int SERVICE_TIMEOUT_MSG = 12;
912 static final int UPDATE_TIME_ZONE = 13;
913 static final int SHOW_UID_ERROR_MSG = 14;
914 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700916 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700917 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800918 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700919 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
920 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700921 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700922 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923
924 AlertDialog mUidAlert;
925
926 final Handler mHandler = new Handler() {
927 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800928 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 //}
930
931 public void handleMessage(Message msg) {
932 switch (msg.what) {
933 case SHOW_ERROR_MSG: {
934 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 synchronized (ActivityManagerService.this) {
936 ProcessRecord proc = (ProcessRecord)data.get("app");
937 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800938 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 return;
940 }
941 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700942 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800943 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 d.show();
945 proc.crashDialog = d;
946 } else {
947 // The device is asleep, so just pretend that the user
948 // saw a crash dialog and hit "force quit".
949 res.set(0);
950 }
951 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700952
953 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 } break;
955 case SHOW_NOT_RESPONDING_MSG: {
956 synchronized (ActivityManagerService.this) {
957 HashMap data = (HashMap) msg.obj;
958 ProcessRecord proc = (ProcessRecord)data.get("app");
959 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800960 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 return;
962 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800963
964 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
965 null, null, 0, null, null, null,
966 false, false, MY_PID, Process.SYSTEM_UID);
967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700969 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 d.show();
971 proc.anrDialog = d;
972 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700973
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700974 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700976 case SHOW_STRICT_MODE_VIOLATION_MSG: {
977 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
978 synchronized (ActivityManagerService.this) {
979 ProcessRecord proc = (ProcessRecord) data.get("app");
980 if (proc == null) {
981 Slog.e(TAG, "App not found when showing strict mode dialog.");
982 break;
983 }
984 if (proc.crashDialog != null) {
985 Slog.e(TAG, "App already has strict mode dialog: " + proc);
986 return;
987 }
988 AppErrorResult res = (AppErrorResult) data.get("result");
989 if (!mSleeping && !mShuttingDown) {
990 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
991 d.show();
992 proc.crashDialog = d;
993 } else {
994 // The device is asleep, so just pretend that the user
995 // saw a crash dialog and hit "force quit".
996 res.set(0);
997 }
998 }
999 ensureBootCompleted();
1000 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 case SHOW_FACTORY_ERROR_MSG: {
1002 Dialog d = new FactoryErrorDialog(
1003 mContext, msg.getData().getCharSequence("msg"));
1004 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001005 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 } break;
1007 case UPDATE_CONFIGURATION_MSG: {
1008 final ContentResolver resolver = mContext.getContentResolver();
1009 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1010 } break;
1011 case GC_BACKGROUND_PROCESSES_MSG: {
1012 synchronized (ActivityManagerService.this) {
1013 performAppGcsIfAppropriateLocked();
1014 }
1015 } break;
1016 case WAIT_FOR_DEBUGGER_MSG: {
1017 synchronized (ActivityManagerService.this) {
1018 ProcessRecord app = (ProcessRecord)msg.obj;
1019 if (msg.arg1 != 0) {
1020 if (!app.waitedForDebugger) {
1021 Dialog d = new AppWaitingForDebuggerDialog(
1022 ActivityManagerService.this,
1023 mContext, app);
1024 app.waitDialog = d;
1025 app.waitedForDebugger = true;
1026 d.show();
1027 }
1028 } else {
1029 if (app.waitDialog != null) {
1030 app.waitDialog.dismiss();
1031 app.waitDialog = null;
1032 }
1033 }
1034 }
1035 } break;
1036 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001037 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 TAG, "Received BROADCAST_INTENT_MSG");
1039 processNextBroadcast(true);
1040 } break;
1041 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001042 if (mDidDexOpt) {
1043 mDidDexOpt = false;
1044 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1045 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1046 return;
1047 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001048 // Only process broadcast timeouts if the system is ready. That way
1049 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1050 // to do heavy lifting for system up
1051 if (mSystemReady) {
1052 broadcastTimeout();
1053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001056 if (mDidDexOpt) {
1057 mDidDexOpt = false;
1058 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1059 nmsg.obj = msg.obj;
1060 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1061 return;
1062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 serviceTimeout((ProcessRecord)msg.obj);
1064 } break;
1065 case UPDATE_TIME_ZONE: {
1066 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001067 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1068 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 if (r.thread != null) {
1070 try {
1071 r.thread.updateTimeZone();
1072 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001073 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 }
1075 }
1076 }
1077 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001078 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 case SHOW_UID_ERROR_MSG: {
1080 // XXX This is a temporary dialog, no need to localize.
1081 AlertDialog d = new BaseErrorDialog(mContext);
1082 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1083 d.setCancelable(false);
1084 d.setTitle("System UIDs Inconsistent");
1085 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1086 d.setButton("I'm Feeling Lucky",
1087 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1088 mUidAlert = d;
1089 d.show();
1090 } break;
1091 case IM_FEELING_LUCKY_MSG: {
1092 if (mUidAlert != null) {
1093 mUidAlert.dismiss();
1094 mUidAlert = null;
1095 }
1096 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001098 if (mDidDexOpt) {
1099 mDidDexOpt = false;
1100 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1101 nmsg.obj = msg.obj;
1102 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1103 return;
1104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 ProcessRecord app = (ProcessRecord)msg.obj;
1106 synchronized (ActivityManagerService.this) {
1107 processStartTimedOutLocked(app);
1108 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001109 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001110 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1111 synchronized (ActivityManagerService.this) {
1112 doPendingActivityLaunchesLocked(true);
1113 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001114 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001115 case KILL_APPLICATION_MSG: {
1116 synchronized (ActivityManagerService.this) {
1117 int uid = msg.arg1;
1118 boolean restart = (msg.arg2 == 1);
1119 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001120 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001121 }
1122 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001123 case FINALIZE_PENDING_INTENT_MSG: {
1124 ((PendingIntentRecord)msg.obj).completeFinalize();
1125 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001126 case POST_HEAVY_NOTIFICATION_MSG: {
1127 INotificationManager inm = NotificationManager.getService();
1128 if (inm == null) {
1129 return;
1130 }
1131
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001132 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001133 ProcessRecord process = root.app;
1134 if (process == null) {
1135 return;
1136 }
1137
1138 try {
1139 Context context = mContext.createPackageContext(process.info.packageName, 0);
1140 String text = mContext.getString(R.string.heavy_weight_notification,
1141 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1142 Notification notification = new Notification();
1143 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1144 notification.when = 0;
1145 notification.flags = Notification.FLAG_ONGOING_EVENT;
1146 notification.tickerText = text;
1147 notification.defaults = 0; // please be quiet
1148 notification.sound = null;
1149 notification.vibrate = null;
1150 notification.setLatestEventInfo(context, text,
1151 mContext.getText(R.string.heavy_weight_notification_detail),
1152 PendingIntent.getActivity(mContext, 0, root.intent,
1153 PendingIntent.FLAG_CANCEL_CURRENT));
1154
1155 try {
1156 int[] outId = new int[1];
1157 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1158 notification, outId);
1159 } catch (RuntimeException e) {
1160 Slog.w(ActivityManagerService.TAG,
1161 "Error showing notification for heavy-weight app", e);
1162 } catch (RemoteException e) {
1163 }
1164 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001165 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001166 }
1167 } break;
1168 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1169 INotificationManager inm = NotificationManager.getService();
1170 if (inm == null) {
1171 return;
1172 }
1173 try {
1174 inm.cancelNotification("android",
1175 R.string.heavy_weight_notification);
1176 } catch (RuntimeException e) {
1177 Slog.w(ActivityManagerService.TAG,
1178 "Error canceling notification for service", e);
1179 } catch (RemoteException e) {
1180 }
1181 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001182 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1183 synchronized (ActivityManagerService.this) {
1184 checkExcessiveWakeLocksLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001185 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001186 if (mSleeping) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001187 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1188 sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001189 }
1190 }
1191 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 }
1193 }
1194 };
1195
1196 public static void setSystemProcess() {
1197 try {
1198 ActivityManagerService m = mSelf;
1199
1200 ServiceManager.addService("activity", m);
1201 ServiceManager.addService("meminfo", new MemBinder(m));
1202 if (MONITOR_CPU_USAGE) {
1203 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 ServiceManager.addService("permission", new PermissionController(m));
1206
1207 ApplicationInfo info =
1208 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001209 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001210 mSystemThread.installSystemApplicationInfo(info);
1211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 synchronized (mSelf) {
1213 ProcessRecord app = mSelf.newProcessRecordLocked(
1214 mSystemThread.getApplicationThread(), info,
1215 info.processName);
1216 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001217 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 app.maxAdj = SYSTEM_ADJ;
1219 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1220 synchronized (mSelf.mPidsSelfLocked) {
1221 mSelf.mPidsSelfLocked.put(app.pid, app);
1222 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001223 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 }
1225 } catch (PackageManager.NameNotFoundException e) {
1226 throw new RuntimeException(
1227 "Unable to find android system package", e);
1228 }
1229 }
1230
1231 public void setWindowManager(WindowManagerService wm) {
1232 mWindowManager = wm;
1233 }
1234
1235 public static final Context main(int factoryTest) {
1236 AThread thr = new AThread();
1237 thr.start();
1238
1239 synchronized (thr) {
1240 while (thr.mService == null) {
1241 try {
1242 thr.wait();
1243 } catch (InterruptedException e) {
1244 }
1245 }
1246 }
1247
1248 ActivityManagerService m = thr.mService;
1249 mSelf = m;
1250 ActivityThread at = ActivityThread.systemMain();
1251 mSystemThread = at;
1252 Context context = at.getSystemContext();
1253 m.mContext = context;
1254 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001255 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256
1257 m.mBatteryStatsService.publish(context);
1258 m.mUsageStatsService.publish(context);
1259
1260 synchronized (thr) {
1261 thr.mReady = true;
1262 thr.notifyAll();
1263 }
1264
1265 m.startRunning(null, null, null, null);
1266
1267 return context;
1268 }
1269
1270 public static ActivityManagerService self() {
1271 return mSelf;
1272 }
1273
1274 static class AThread extends Thread {
1275 ActivityManagerService mService;
1276 boolean mReady = false;
1277
1278 public AThread() {
1279 super("ActivityManager");
1280 }
1281
1282 public void run() {
1283 Looper.prepare();
1284
1285 android.os.Process.setThreadPriority(
1286 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001287 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288
1289 ActivityManagerService m = new ActivityManagerService();
1290
1291 synchronized (this) {
1292 mService = m;
1293 notifyAll();
1294 }
1295
1296 synchronized (this) {
1297 while (!mReady) {
1298 try {
1299 wait();
1300 } catch (InterruptedException e) {
1301 }
1302 }
1303 }
1304
1305 Looper.loop();
1306 }
1307 }
1308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 static class MemBinder extends Binder {
1310 ActivityManagerService mActivityManagerService;
1311 MemBinder(ActivityManagerService activityManagerService) {
1312 mActivityManagerService = activityManagerService;
1313 }
1314
1315 @Override
1316 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1317 ActivityManagerService service = mActivityManagerService;
1318 ArrayList<ProcessRecord> procs;
1319 synchronized (mActivityManagerService) {
1320 if (args != null && args.length > 0
1321 && args[0].charAt(0) != '-') {
1322 procs = new ArrayList<ProcessRecord>();
1323 int pid = -1;
1324 try {
1325 pid = Integer.parseInt(args[0]);
1326 } catch (NumberFormatException e) {
1327
1328 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001329 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1330 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 if (proc.pid == pid) {
1332 procs.add(proc);
1333 } else if (proc.processName.equals(args[0])) {
1334 procs.add(proc);
1335 }
1336 }
1337 if (procs.size() <= 0) {
1338 pw.println("No process found for: " + args[0]);
1339 return;
1340 }
1341 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001342 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 }
1344 }
1345 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1346 }
1347 }
1348
1349 static class CpuBinder extends Binder {
1350 ActivityManagerService mActivityManagerService;
1351 CpuBinder(ActivityManagerService activityManagerService) {
1352 mActivityManagerService = activityManagerService;
1353 }
1354
1355 @Override
1356 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1357 synchronized (mActivityManagerService.mProcessStatsThread) {
1358 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1359 }
1360 }
1361 }
1362
1363 private ActivityManagerService() {
1364 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1365 if (v != null && Integer.getInteger(v) != 0) {
1366 mSimpleProcessManagement = true;
1367 }
1368 v = System.getenv("ANDROID_DEBUG_APP");
1369 if (v != null) {
1370 mSimpleProcessManagement = true;
1371 }
1372
Joe Onorato8a9b2202010-02-26 18:56:32 -08001373 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 File dataDir = Environment.getDataDirectory();
1376 File systemDir = new File(dataDir, "system");
1377 systemDir.mkdirs();
1378 mBatteryStatsService = new BatteryStatsService(new File(
1379 systemDir, "batterystats.bin").toString());
1380 mBatteryStatsService.getActiveStatistics().readLocked();
1381 mBatteryStatsService.getActiveStatistics().writeLocked();
1382
1383 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001384 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385
Jack Palevichb90d28c2009-07-22 15:35:24 -07001386 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1387 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1388
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001389 mConfiguration.setToDefaults();
1390 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 mProcessStats.init();
1392
1393 // Add ourself to the Watchdog monitors.
1394 Watchdog.getInstance().addMonitor(this);
1395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 mProcessStatsThread = new Thread("ProcessStats") {
1397 public void run() {
1398 while (true) {
1399 try {
1400 try {
1401 synchronized(this) {
1402 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001403 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001405 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 // + ", write delay=" + nextWriteDelay);
1407 if (nextWriteDelay < nextCpuDelay) {
1408 nextCpuDelay = nextWriteDelay;
1409 }
1410 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001411 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 this.wait(nextCpuDelay);
1413 }
1414 }
1415 } catch (InterruptedException e) {
1416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 updateCpuStatsNow();
1418 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001419 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 }
1421 }
1422 }
1423 };
1424 mProcessStatsThread.start();
1425 }
1426
1427 @Override
1428 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1429 throws RemoteException {
1430 try {
1431 return super.onTransact(code, data, reply, flags);
1432 } catch (RuntimeException e) {
1433 // The activity manager only throws security exceptions, so let's
1434 // log all others.
1435 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001436 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 }
1438 throw e;
1439 }
1440 }
1441
1442 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001443 final long now = SystemClock.uptimeMillis();
1444 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1445 return;
1446 }
1447 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1448 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 mProcessStatsThread.notify();
1450 }
1451 }
1452 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 void updateCpuStatsNow() {
1455 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001456 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 final long now = SystemClock.uptimeMillis();
1458 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001461 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1462 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 haveNewCpuStats = true;
1464 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001465 //Slog.i(TAG, mProcessStats.printCurrentState());
1466 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 // + mProcessStats.getTotalCpuPercent() + "%");
1468
Joe Onorato8a9b2202010-02-26 18:56:32 -08001469 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 if ("true".equals(SystemProperties.get("events.cpu"))) {
1471 int user = mProcessStats.getLastUserTime();
1472 int system = mProcessStats.getLastSystemTime();
1473 int iowait = mProcessStats.getLastIoWaitTime();
1474 int irq = mProcessStats.getLastIrqTime();
1475 int softIrq = mProcessStats.getLastSoftIrqTime();
1476 int idle = mProcessStats.getLastIdleTime();
1477
1478 int total = user + system + iowait + irq + softIrq + idle;
1479 if (total == 0) total = 1;
1480
Doug Zongker2bec3d42009-12-04 12:52:44 -08001481 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 ((user+system+iowait+irq+softIrq) * 100) / total,
1483 (user * 100) / total,
1484 (system * 100) / total,
1485 (iowait * 100) / total,
1486 (irq * 100) / total,
1487 (softIrq * 100) / total);
1488 }
1489 }
1490
Amith Yamasanie43530a2009-08-21 13:11:37 -07001491 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001492 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001493 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 synchronized(mPidsSelfLocked) {
1495 if (haveNewCpuStats) {
1496 if (mBatteryStatsService.isOnBattery()) {
1497 final int N = mProcessStats.countWorkingStats();
1498 for (int i=0; i<N; i++) {
1499 ProcessStats.Stats st
1500 = mProcessStats.getWorkingStats(i);
1501 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1502 if (pr != null) {
1503 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1504 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001505 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001506 } else {
1507 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001508 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001509 if (ps != null) {
1510 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001511 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 }
1514 }
1515 }
1516 }
1517 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1520 mLastWriteTime = now;
1521 mBatteryStatsService.getActiveStatistics().writeLocked();
1522 }
1523 }
1524 }
1525 }
1526
1527 /**
1528 * Initialize the application bind args. These are passed to each
1529 * process when the bindApplication() IPC is sent to the process. They're
1530 * lazily setup to make sure the services are running when they're asked for.
1531 */
1532 private HashMap<String, IBinder> getCommonServicesLocked() {
1533 if (mAppBindArgs == null) {
1534 mAppBindArgs = new HashMap<String, IBinder>();
1535
1536 // Setup the application init args
1537 mAppBindArgs.put("package", ServiceManager.getService("package"));
1538 mAppBindArgs.put("window", ServiceManager.getService("window"));
1539 mAppBindArgs.put(Context.ALARM_SERVICE,
1540 ServiceManager.getService(Context.ALARM_SERVICE));
1541 }
1542 return mAppBindArgs;
1543 }
1544
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001545 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 if (mFocusedActivity != r) {
1547 mFocusedActivity = r;
1548 mWindowManager.setFocusedApp(r, true);
1549 }
1550 }
1551
Dianne Hackborn906497c2010-05-10 15:57:38 -07001552 private final void updateLruProcessInternalLocked(ProcessRecord app,
1553 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001555 int lrui = mLruProcesses.indexOf(app);
1556 if (lrui >= 0) mLruProcesses.remove(lrui);
1557
1558 int i = mLruProcesses.size()-1;
1559 int skipTop = 0;
1560
Dianne Hackborn906497c2010-05-10 15:57:38 -07001561 app.lruSeq = mLruSeq;
1562
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001563 // compute the new weight for this process.
1564 if (updateActivityTime) {
1565 app.lastActivityTime = SystemClock.uptimeMillis();
1566 }
1567 if (app.activities.size() > 0) {
1568 // If this process has activities, we more strongly want to keep
1569 // it around.
1570 app.lruWeight = app.lastActivityTime;
1571 } else if (app.pubProviders.size() > 0) {
1572 // If this process contains content providers, we want to keep
1573 // it a little more strongly.
1574 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1575 // Also don't let it kick out the first few "real" hidden processes.
1576 skipTop = MIN_HIDDEN_APPS;
1577 } else {
1578 // If this process doesn't have activities, we less strongly
1579 // want to keep it around, and generally want to avoid getting
1580 // in front of any very recently used activities.
1581 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1582 // Also don't let it kick out the first few "real" hidden processes.
1583 skipTop = MIN_HIDDEN_APPS;
1584 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001585
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001586 while (i >= 0) {
1587 ProcessRecord p = mLruProcesses.get(i);
1588 // If this app shouldn't be in front of the first N background
1589 // apps, then skip over that many that are currently hidden.
1590 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1591 skipTop--;
1592 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001593 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001594 mLruProcesses.add(i+1, app);
1595 break;
1596 }
1597 i--;
1598 }
1599 if (i < 0) {
1600 mLruProcesses.add(0, app);
1601 }
1602
Dianne Hackborn906497c2010-05-10 15:57:38 -07001603 // If the app is currently using a content provider or service,
1604 // bump those processes as well.
1605 if (app.connections.size() > 0) {
1606 for (ConnectionRecord cr : app.connections) {
1607 if (cr.binding != null && cr.binding.service != null
1608 && cr.binding.service.app != null
1609 && cr.binding.service.app.lruSeq != mLruSeq) {
1610 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1611 updateActivityTime, i+1);
1612 }
1613 }
1614 }
1615 if (app.conProviders.size() > 0) {
1616 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1617 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1618 updateLruProcessInternalLocked(cpr.app, oomAdj,
1619 updateActivityTime, i+1);
1620 }
1621 }
1622 }
1623
Joe Onorato8a9b2202010-02-26 18:56:32 -08001624 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 if (oomAdj) {
1626 updateOomAdjLocked();
1627 }
1628 }
1629
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001630 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001631 boolean oomAdj, boolean updateActivityTime) {
1632 mLruSeq++;
1633 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1634 }
1635
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001636 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 String processName, int uid) {
1638 if (uid == Process.SYSTEM_UID) {
1639 // The system gets to run in any process. If there are multiple
1640 // processes with the same uid, just pick the first (this
1641 // should never happen).
1642 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1643 processName);
1644 return procs != null ? procs.valueAt(0) : null;
1645 }
1646 ProcessRecord proc = mProcessNames.get(processName, uid);
1647 return proc;
1648 }
1649
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001650 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001651 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001652 try {
1653 if (pm.performDexOpt(packageName)) {
1654 mDidDexOpt = true;
1655 }
1656 } catch (RemoteException e) {
1657 }
1658 }
1659
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001660 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 int transit = mWindowManager.getPendingAppTransition();
1662 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1663 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1664 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1665 }
1666
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001667 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001669 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1671 // We don't have to do anything more if:
1672 // (1) There is an existing application record; and
1673 // (2) The caller doesn't think it is dead, OR there is no thread
1674 // object attached to it so we know it couldn't have crashed; and
1675 // (3) There is a pid assigned to it, so it is either starting or
1676 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001677 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 + " app=" + app + " knownToBeDead=" + knownToBeDead
1679 + " thread=" + (app != null ? app.thread : null)
1680 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001681 if (app != null && app.pid > 0) {
1682 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001683 // We already have the app running, or are waiting for it to
1684 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001685 return app;
1686 } else {
1687 // An application record is attached to a previous process,
1688 // clean it up now.
1689 handleAppDiedLocked(app, true);
1690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 String hostingNameStr = hostingName != null
1694 ? hostingName.flattenToShortString() : null;
1695
1696 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1697 // If we are in the background, then check to see if this process
1698 // is bad. If so, we will just silently fail.
1699 if (mBadProcesses.get(info.processName, info.uid) != null) {
1700 return null;
1701 }
1702 } else {
1703 // When the user is explicitly starting a process, then clear its
1704 // crash count so that we won't make it bad until they see at
1705 // least one crash dialog again, and make the process good again
1706 // if it had been bad.
1707 mProcessCrashTimes.remove(info.processName, info.uid);
1708 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001709 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 info.processName);
1711 mBadProcesses.remove(info.processName, info.uid);
1712 if (app != null) {
1713 app.bad = false;
1714 }
1715 }
1716 }
1717
1718 if (app == null) {
1719 app = newProcessRecordLocked(null, info, processName);
1720 mProcessNames.put(processName, info.uid, app);
1721 } else {
1722 // If this is a new package in the process, add the package to the list
1723 app.addPackage(info.packageName);
1724 }
1725
1726 // If the system is not ready yet, then hold off on starting this
1727 // process until it is.
1728 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001729 && !isAllowedWhileBooting(info)
1730 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 if (!mProcessesOnHold.contains(app)) {
1732 mProcessesOnHold.add(app);
1733 }
1734 return app;
1735 }
1736
1737 startProcessLocked(app, hostingType, hostingNameStr);
1738 return (app.pid != 0) ? app : null;
1739 }
1740
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001741 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1742 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1743 }
1744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 private final void startProcessLocked(ProcessRecord app,
1746 String hostingType, String hostingNameStr) {
1747 if (app.pid > 0 && app.pid != MY_PID) {
1748 synchronized (mPidsSelfLocked) {
1749 mPidsSelfLocked.remove(app.pid);
1750 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1751 }
1752 app.pid = 0;
1753 }
1754
1755 mProcessesOnHold.remove(app);
1756
1757 updateCpuStats();
1758
1759 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1760 mProcDeaths[0] = 0;
1761
1762 try {
1763 int uid = app.info.uid;
1764 int[] gids = null;
1765 try {
1766 gids = mContext.getPackageManager().getPackageGids(
1767 app.info.packageName);
1768 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001769 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 }
1771 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1772 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1773 && mTopComponent != null
1774 && app.processName.equals(mTopComponent.getPackageName())) {
1775 uid = 0;
1776 }
1777 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1778 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1779 uid = 0;
1780 }
1781 }
1782 int debugFlags = 0;
1783 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1784 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1785 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001786 // Run the app in safe mode if its manifest requests so or the
1787 // system is booted in safe mode.
1788 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1789 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001790 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1793 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1794 }
1795 if ("1".equals(SystemProperties.get("debug.assert"))) {
1796 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1797 }
1798 int pid = Process.start("android.app.ActivityThread",
1799 mSimpleProcessManagement ? app.processName : null, uid, uid,
1800 gids, debugFlags, null);
1801 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1802 synchronized (bs) {
1803 if (bs.isOnBattery()) {
1804 app.batteryStats.incStartsLocked();
1805 }
1806 }
1807
Doug Zongker2bec3d42009-12-04 12:52:44 -08001808 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 app.processName, hostingType,
1810 hostingNameStr != null ? hostingNameStr : "");
1811
1812 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001813 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 }
1815
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001816 StringBuilder buf = mStringBuilder;
1817 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 buf.append("Start proc ");
1819 buf.append(app.processName);
1820 buf.append(" for ");
1821 buf.append(hostingType);
1822 if (hostingNameStr != null) {
1823 buf.append(" ");
1824 buf.append(hostingNameStr);
1825 }
1826 buf.append(": pid=");
1827 buf.append(pid);
1828 buf.append(" uid=");
1829 buf.append(uid);
1830 buf.append(" gids={");
1831 if (gids != null) {
1832 for (int gi=0; gi<gids.length; gi++) {
1833 if (gi != 0) buf.append(", ");
1834 buf.append(gids[gi]);
1835
1836 }
1837 }
1838 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001839 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 if (pid == 0 || pid == MY_PID) {
1841 // Processes are being emulated with threads.
1842 app.pid = MY_PID;
1843 app.removed = false;
1844 mStartingProcesses.add(app);
1845 } else if (pid > 0) {
1846 app.pid = pid;
1847 app.removed = false;
1848 synchronized (mPidsSelfLocked) {
1849 this.mPidsSelfLocked.put(pid, app);
1850 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1851 msg.obj = app;
1852 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1853 }
1854 } else {
1855 app.pid = 0;
1856 RuntimeException e = new RuntimeException(
1857 "Failure starting process " + app.processName
1858 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001859 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 }
1861 } catch (RuntimeException e) {
1862 // XXX do better error recovery.
1863 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001864 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865 }
1866 }
1867
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001868 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 if (resumed) {
1870 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1871 } else {
1872 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1873 }
1874 }
1875
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001876 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001877 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1878 && mTopAction == null) {
1879 // We are running in factory test mode, but unable to find
1880 // the factory test app, so just sit around displaying the
1881 // error message and don't try to start anything.
1882 return false;
1883 }
1884 Intent intent = new Intent(
1885 mTopAction,
1886 mTopData != null ? Uri.parse(mTopData) : null);
1887 intent.setComponent(mTopComponent);
1888 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1889 intent.addCategory(Intent.CATEGORY_HOME);
1890 }
1891 ActivityInfo aInfo =
1892 intent.resolveActivityInfo(mContext.getPackageManager(),
1893 STOCK_PM_FLAGS);
1894 if (aInfo != null) {
1895 intent.setComponent(new ComponentName(
1896 aInfo.applicationInfo.packageName, aInfo.name));
1897 // Don't do this if the home app is currently being
1898 // instrumented.
1899 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1900 aInfo.applicationInfo.uid);
1901 if (app == null || app.instrumentationClass == null) {
1902 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001903 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001904 null, null, 0, 0, 0, false, false);
1905 }
1906 }
1907
1908
1909 return true;
1910 }
1911
1912 /**
1913 * Starts the "new version setup screen" if appropriate.
1914 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001915 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001916 // Only do this once per boot.
1917 if (mCheckedForSetup) {
1918 return;
1919 }
1920
1921 // We will show this screen if the current one is a different
1922 // version than the last one shown, and we are not running in
1923 // low-level factory test mode.
1924 final ContentResolver resolver = mContext.getContentResolver();
1925 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1926 Settings.Secure.getInt(resolver,
1927 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1928 mCheckedForSetup = true;
1929
1930 // See if we should be showing the platform update setup UI.
1931 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1932 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1933 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1934
1935 // We don't allow third party apps to replace this.
1936 ResolveInfo ri = null;
1937 for (int i=0; ris != null && i<ris.size(); i++) {
1938 if ((ris.get(i).activityInfo.applicationInfo.flags
1939 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1940 ri = ris.get(i);
1941 break;
1942 }
1943 }
1944
1945 if (ri != null) {
1946 String vers = ri.activityInfo.metaData != null
1947 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1948 : null;
1949 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1950 vers = ri.activityInfo.applicationInfo.metaData.getString(
1951 Intent.METADATA_SETUP_VERSION);
1952 }
1953 String lastVers = Settings.Secure.getString(
1954 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1955 if (vers != null && !vers.equals(lastVers)) {
1956 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1957 intent.setComponent(new ComponentName(
1958 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001959 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001960 null, null, 0, 0, 0, false, false);
1961 }
1962 }
1963 }
1964 }
1965
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001966 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001967 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001968
1969 final int identHash = System.identityHashCode(r);
1970 updateUsageStats(r, true);
1971
1972 int i = mWatchers.beginBroadcast();
1973 while (i > 0) {
1974 i--;
1975 IActivityWatcher w = mWatchers.getBroadcastItem(i);
1976 if (w != null) {
1977 try {
1978 w.activityResuming(identHash);
1979 } catch (RemoteException e) {
1980 }
1981 }
1982 }
1983 mWatchers.finishBroadcast();
1984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001986 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001987 final int N = mPendingActivityLaunches.size();
1988 if (N <= 0) {
1989 return;
1990 }
1991 for (int i=0; i<N; i++) {
1992 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001993 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001994 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
1995 doResume && i == (N-1));
1996 }
1997 mPendingActivityLaunches.clear();
1998 }
1999
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002000 public final int startActivity(IApplicationThread caller,
2001 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2002 int grantedMode, IBinder resultTo,
2003 String resultWho, int requestCode, boolean onlyIfNeeded,
2004 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002005 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002006 grantedUriPermissions, grantedMode, resultTo, resultWho,
2007 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002008 }
2009
2010 public final WaitResult startActivityAndWait(IApplicationThread caller,
2011 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2012 int grantedMode, IBinder resultTo,
2013 String resultWho, int requestCode, boolean onlyIfNeeded,
2014 boolean debug) {
2015 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002016 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002017 grantedUriPermissions, grantedMode, resultTo, resultWho,
2018 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002019 return res;
2020 }
2021
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002022 public final int startActivityWithConfig(IApplicationThread caller,
2023 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2024 int grantedMode, IBinder resultTo,
2025 String resultWho, int requestCode, boolean onlyIfNeeded,
2026 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002027 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002028 grantedUriPermissions, grantedMode, resultTo, resultWho,
2029 requestCode, onlyIfNeeded, debug, null, config);
2030 }
2031
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002032 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002033 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002034 IBinder resultTo, String resultWho, int requestCode,
2035 int flagsMask, int flagsValues) {
2036 // Refuse possible leaked file descriptors
2037 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2038 throw new IllegalArgumentException("File descriptors passed in Intent");
2039 }
2040
2041 IIntentSender sender = intent.getTarget();
2042 if (!(sender instanceof PendingIntentRecord)) {
2043 throw new IllegalArgumentException("Bad PendingIntent object");
2044 }
2045
2046 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002047
2048 synchronized (this) {
2049 // If this is coming from the currently resumed activity, it is
2050 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002051 if (mMainStack.mResumedActivity != null
2052 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002053 Binder.getCallingUid()) {
2054 mAppSwitchesAllowedTime = 0;
2055 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002056 }
2057
2058 return pir.sendInner(0, fillInIntent, resolvedType,
2059 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2060 }
2061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 public boolean startNextMatchingActivity(IBinder callingActivity,
2063 Intent intent) {
2064 // Refuse possible leaked file descriptors
2065 if (intent != null && intent.hasFileDescriptors() == true) {
2066 throw new IllegalArgumentException("File descriptors passed in Intent");
2067 }
2068
2069 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002070 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 if (index < 0) {
2072 return false;
2073 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002074 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 if (r.app == null || r.app.thread == null) {
2076 // The caller is not running... d'oh!
2077 return false;
2078 }
2079 intent = new Intent(intent);
2080 // The caller is not allowed to change the data.
2081 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2082 // And we are resetting to find the next component...
2083 intent.setComponent(null);
2084
2085 ActivityInfo aInfo = null;
2086 try {
2087 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002088 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002090 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091
2092 // Look for the original activity in the list...
2093 final int N = resolves != null ? resolves.size() : 0;
2094 for (int i=0; i<N; i++) {
2095 ResolveInfo rInfo = resolves.get(i);
2096 if (rInfo.activityInfo.packageName.equals(r.packageName)
2097 && rInfo.activityInfo.name.equals(r.info.name)) {
2098 // We found the current one... the next matching is
2099 // after it.
2100 i++;
2101 if (i<N) {
2102 aInfo = resolves.get(i).activityInfo;
2103 }
2104 break;
2105 }
2106 }
2107 } catch (RemoteException e) {
2108 }
2109
2110 if (aInfo == null) {
2111 // Nobody who is next!
2112 return false;
2113 }
2114
2115 intent.setComponent(new ComponentName(
2116 aInfo.applicationInfo.packageName, aInfo.name));
2117 intent.setFlags(intent.getFlags()&~(
2118 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2119 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2120 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2121 Intent.FLAG_ACTIVITY_NEW_TASK));
2122
2123 // Okay now we need to start the new activity, replacing the
2124 // currently running activity. This is a little tricky because
2125 // we want to start the new one as if the current one is finished,
2126 // but not finish the current one first so that there is no flicker.
2127 // And thus...
2128 final boolean wasFinishing = r.finishing;
2129 r.finishing = true;
2130
2131 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002132 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 final String resultWho = r.resultWho;
2134 final int requestCode = r.requestCode;
2135 r.resultTo = null;
2136 if (resultTo != null) {
2137 resultTo.removeResultsLocked(r, resultWho, requestCode);
2138 }
2139
2140 final long origId = Binder.clearCallingIdentity();
2141 // XXX we are not dealing with propagating grantedUriPermissions...
2142 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002143 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002145 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 Binder.restoreCallingIdentity(origId);
2147
2148 r.finishing = wasFinishing;
2149 if (res != START_SUCCESS) {
2150 return false;
2151 }
2152 return true;
2153 }
2154 }
2155
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002156 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 Intent intent, String resolvedType, IBinder resultTo,
2158 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002159
2160 // This is so super not safe, that only the system (or okay root)
2161 // can do it.
2162 final int callingUid = Binder.getCallingUid();
2163 if (callingUid != 0 && callingUid != Process.myUid()) {
2164 throw new SecurityException(
2165 "startActivityInPackage only available to the system");
2166 }
2167
The Android Open Source Project4df24232009-03-05 14:34:35 -08002168 final boolean componentSpecified = intent.getComponent() != null;
2169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 // Don't modify the client's object!
2171 intent = new Intent(intent);
2172
2173 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 ActivityInfo aInfo;
2175 try {
2176 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002177 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002179 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 aInfo = rInfo != null ? rInfo.activityInfo : null;
2181 } catch (RemoteException e) {
2182 aInfo = null;
2183 }
2184
2185 if (aInfo != null) {
2186 // Store the found target back into the intent, because now that
2187 // we have it we never want to do this again. For example, if the
2188 // user navigates back to this point in the history, we should
2189 // always restart the exact same activity.
2190 intent.setComponent(new ComponentName(
2191 aInfo.applicationInfo.packageName, aInfo.name));
2192 }
2193
2194 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002195 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002197 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 }
2199 }
2200
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002201 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202 // Remove any existing entries that are the same kind of task.
2203 int N = mRecentTasks.size();
2204 for (int i=0; i<N; i++) {
2205 TaskRecord tr = mRecentTasks.get(i);
2206 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2207 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2208 mRecentTasks.remove(i);
2209 i--;
2210 N--;
2211 if (task.intent == null) {
2212 // If the new recent task we are adding is not fully
2213 // specified, then replace it with the existing recent task.
2214 task = tr;
2215 }
2216 }
2217 }
2218 if (N >= MAX_RECENT_TASKS) {
2219 mRecentTasks.remove(N-1);
2220 }
2221 mRecentTasks.add(0, task);
2222 }
2223
2224 public void setRequestedOrientation(IBinder token,
2225 int requestedOrientation) {
2226 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002227 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 if (index < 0) {
2229 return;
2230 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002231 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 final long origId = Binder.clearCallingIdentity();
2233 mWindowManager.setAppOrientation(r, requestedOrientation);
2234 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002235 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 r.mayFreezeScreenLocked(r.app) ? r : null);
2237 if (config != null) {
2238 r.frozenBeforeDestroy = true;
2239 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002240 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002241 }
2242 }
2243 Binder.restoreCallingIdentity(origId);
2244 }
2245 }
2246
2247 public int getRequestedOrientation(IBinder token) {
2248 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002249 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 if (index < 0) {
2251 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2252 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002253 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 return mWindowManager.getAppOrientation(r);
2255 }
2256 }
2257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 /**
2259 * This is the internal entry point for handling Activity.finish().
2260 *
2261 * @param token The Binder token referencing the Activity we want to finish.
2262 * @param resultCode Result code, if any, from this Activity.
2263 * @param resultData Result data (Intent), if any, from this Activity.
2264 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002265 * @return Returns true if the activity successfully finished, or false if it is still running.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 */
2267 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2268 // Refuse possible leaked file descriptors
2269 if (resultData != null && resultData.hasFileDescriptors() == true) {
2270 throw new IllegalArgumentException("File descriptors passed in Intent");
2271 }
2272
2273 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002274 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002276 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 if (next != null) {
2278 // ask watcher if this is allowed
2279 boolean resumeOK = true;
2280 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002281 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002283 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 }
2285
2286 if (!resumeOK) {
2287 return false;
2288 }
2289 }
2290 }
2291 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002292 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 resultData, "app-request");
2294 Binder.restoreCallingIdentity(origId);
2295 return res;
2296 }
2297 }
2298
Dianne Hackborn860755f2010-06-03 18:47:52 -07002299 public final void finishHeavyWeightApp() {
2300 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2301 != PackageManager.PERMISSION_GRANTED) {
2302 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2303 + Binder.getCallingPid()
2304 + ", uid=" + Binder.getCallingUid()
2305 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2306 Slog.w(TAG, msg);
2307 throw new SecurityException(msg);
2308 }
2309
2310 synchronized(this) {
2311 if (mHeavyWeightProcess == null) {
2312 return;
2313 }
2314
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002315 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002316 mHeavyWeightProcess.activities);
2317 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002318 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002319 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002320 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002321 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002322 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002323 null, "finish-heavy");
2324 }
2325 }
2326 }
2327
2328 mHeavyWeightProcess = null;
2329 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2330 }
2331 }
2332
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002333 public void crashApplication(int uid, int initialPid, String packageName,
2334 String message) {
2335 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2336 != PackageManager.PERMISSION_GRANTED) {
2337 String msg = "Permission Denial: crashApplication() from pid="
2338 + Binder.getCallingPid()
2339 + ", uid=" + Binder.getCallingUid()
2340 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2341 Slog.w(TAG, msg);
2342 throw new SecurityException(msg);
2343 }
2344
2345 synchronized(this) {
2346 ProcessRecord proc = null;
2347
2348 // Figure out which process to kill. We don't trust that initialPid
2349 // still has any relation to current pids, so must scan through the
2350 // list.
2351 synchronized (mPidsSelfLocked) {
2352 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2353 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2354 if (p.info.uid != uid) {
2355 continue;
2356 }
2357 if (p.pid == initialPid) {
2358 proc = p;
2359 break;
2360 }
2361 for (String str : p.pkgList) {
2362 if (str.equals(packageName)) {
2363 proc = p;
2364 }
2365 }
2366 }
2367 }
2368
2369 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002370 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002371 + " initialPid=" + initialPid
2372 + " packageName=" + packageName);
2373 return;
2374 }
2375
2376 if (proc.thread != null) {
2377 long ident = Binder.clearCallingIdentity();
2378 try {
2379 proc.thread.scheduleCrash(message);
2380 } catch (RemoteException e) {
2381 }
2382 Binder.restoreCallingIdentity(ident);
2383 }
2384 }
2385 }
2386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 public final void finishSubActivity(IBinder token, String resultWho,
2388 int requestCode) {
2389 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002390 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391 if (index < 0) {
2392 return;
2393 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002394 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002395
2396 final long origId = Binder.clearCallingIdentity();
2397
2398 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002399 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2400 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401 if (r.resultTo == self && r.requestCode == requestCode) {
2402 if ((r.resultWho == null && resultWho == null) ||
2403 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002404 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 Activity.RESULT_CANCELED, null, "request-sub");
2406 }
2407 }
2408 }
2409
2410 Binder.restoreCallingIdentity(origId);
2411 }
2412 }
2413
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002414 public boolean willActivityBeVisible(IBinder token) {
2415 synchronized(this) {
2416 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002417 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2418 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002419 if (r == token) {
2420 return true;
2421 }
2422 if (r.fullscreen && !r.finishing) {
2423 return false;
2424 }
2425 }
2426 return true;
2427 }
2428 }
2429
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002430 public void overridePendingTransition(IBinder token, String packageName,
2431 int enterAnim, int exitAnim) {
2432 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002433 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002434 if (index < 0) {
2435 return;
2436 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002437 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002438
2439 final long origId = Binder.clearCallingIdentity();
2440
2441 if (self.state == ActivityState.RESUMED
2442 || self.state == ActivityState.PAUSING) {
2443 mWindowManager.overridePendingAppTransition(packageName,
2444 enterAnim, exitAnim);
2445 }
2446
2447 Binder.restoreCallingIdentity(origId);
2448 }
2449 }
2450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002451 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002452 * Main function for removing an existing process from the activity manager
2453 * as a result of that process going away. Clears out all connections
2454 * to the process.
2455 */
2456 private final void handleAppDiedLocked(ProcessRecord app,
2457 boolean restarting) {
2458 cleanUpApplicationRecordLocked(app, restarting, -1);
2459 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002460 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461 }
2462
2463 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002464 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2465 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2466 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002468 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2469 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 }
2471
2472 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002473 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002474
2475 boolean atTop = true;
2476 boolean hasVisibleActivities = false;
2477
2478 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002479 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002480 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 TAG, "Removing app " + app + " from history with " + i + " entries");
2482 while (i > 0) {
2483 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002484 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002485 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2487 if (r.app == app) {
2488 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002489 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002490 TAG, "Removing this entry! frozen=" + r.haveState
2491 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002492 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493
2494 r.inHistory = false;
2495 mWindowManager.removeAppToken(r);
2496 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002497 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002499 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500
2501 } else {
2502 // We have the current state for this activity, so
2503 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002504 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 TAG, "Keeping entry, setting app to null");
2506 if (r.visible) {
2507 hasVisibleActivities = true;
2508 }
2509 r.app = null;
2510 r.nowVisible = false;
2511 if (!r.haveState) {
2512 r.icicle = null;
2513 }
2514 }
2515
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002516 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 r.state = ActivityState.STOPPED;
2518 }
2519 atTop = false;
2520 }
2521
2522 app.activities.clear();
2523
2524 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002525 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 + " running instrumentation " + app.instrumentationClass);
2527 Bundle info = new Bundle();
2528 info.putString("shortMsg", "Process crashed.");
2529 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2530 }
2531
2532 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002533 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002534 // If there was nothing to resume, and we are not already
2535 // restarting this process, but there is a visible activity that
2536 // is hosted by the process... then make sure all visible
2537 // activities are running, taking care of restarting this
2538 // process.
2539 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002540 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541 }
2542 }
2543 }
2544 }
2545
2546 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2547 IBinder threadBinder = thread.asBinder();
2548
2549 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002550 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2551 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2553 return i;
2554 }
2555 }
2556 return -1;
2557 }
2558
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002559 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 IApplicationThread thread) {
2561 if (thread == null) {
2562 return null;
2563 }
2564
2565 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002566 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567 }
2568
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002569 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 IApplicationThread thread) {
2571
2572 mProcDeaths[0]++;
2573
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002574 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2575 synchronized (stats) {
2576 stats.noteProcessDiedLocked(app.info.uid, pid);
2577 }
2578
Magnus Edlund7bb25812010-02-24 15:45:06 +01002579 // Clean up already done if the process has been re-started.
2580 if (app.pid == pid && app.thread != null &&
2581 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002582 if (!app.killedBackground) {
2583 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2584 + ") has died.");
2585 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002586 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002587 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 TAG, "Dying app: " + app + ", pid: " + pid
2589 + ", thread: " + thread.asBinder());
2590 boolean doLowMem = app.instrumentationClass == null;
2591 handleAppDiedLocked(app, false);
2592
2593 if (doLowMem) {
2594 // If there are no longer any background processes running,
2595 // and the app that died was not running instrumentation,
2596 // then tell everyone we are now low on memory.
2597 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002598 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2599 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2601 haveBg = true;
2602 break;
2603 }
2604 }
2605
2606 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002607 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002608 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002609 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002610 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2611 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002612 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002613 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2614 // The low memory report is overriding any current
2615 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002616 // heavy/important/visible/foreground processes first.
2617 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002618 rec.lastRequestedGc = 0;
2619 } else {
2620 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002622 rec.reportLowMemory = true;
2623 rec.lastLowMemory = now;
2624 mProcessesToGc.remove(rec);
2625 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 }
2627 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002628 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 }
2630 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002631 } else if (app.pid != pid) {
2632 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002633 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002634 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002635 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002636 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002637 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 + thread.asBinder());
2639 }
2640 }
2641
Dan Egnor42471dd2010-01-07 17:25:22 -08002642 /**
2643 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002644 * @param clearTraces causes the dump file to be erased prior to the new
2645 * traces being written, if true; when false, the new traces will be
2646 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08002647 * @param pids of dalvik VM processes to dump stack traces for
2648 * @return file containing stack traces, or null if no dump file is configured
2649 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07002650 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002651 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2652 if (tracesPath == null || tracesPath.length() == 0) {
2653 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002655
2656 File tracesFile = new File(tracesPath);
2657 try {
2658 File tracesDir = tracesFile.getParentFile();
2659 if (!tracesDir.exists()) tracesFile.mkdirs();
2660 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2661
Christopher Tate6ee412d2010-05-28 12:01:56 -07002662 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002663 tracesFile.createNewFile();
2664 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2665 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002666 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002667 return null;
2668 }
2669
2670 // Use a FileObserver to detect when traces finish writing.
2671 // The order of traces is considered important to maintain for legibility.
2672 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2673 public synchronized void onEvent(int event, String path) { notify(); }
2674 };
2675
2676 try {
2677 observer.startWatching();
2678 int num = pids.size();
2679 for (int i = 0; i < num; i++) {
2680 synchronized (observer) {
2681 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
2682 observer.wait(200); // Wait for write-close, give up after 200msec
2683 }
2684 }
2685 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08002686 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002687 } finally {
2688 observer.stopWatching();
2689 }
2690
2691 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 }
2693
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002694 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2695 ActivityRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002696 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002697
2698 synchronized (this) {
2699 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2700 if (mShuttingDown) {
2701 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2702 return;
2703 } else if (app.notResponding) {
2704 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2705 return;
2706 } else if (app.crashing) {
2707 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2708 return;
2709 }
2710
2711 // In case we come through here for the same app before completing
2712 // this one, mark as anring now so we will bail out.
2713 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002714
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002715 // Log the ANR to the event log.
2716 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2717 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002718
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002719 // Dump thread traces as quickly as we can, starting with "interesting" processes.
2720 pids.add(app.pid);
2721
2722 int parentPid = app.pid;
2723 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
2724 if (parentPid != app.pid) pids.add(parentPid);
2725
2726 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002727
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002728 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2729 ProcessRecord r = mLruProcesses.get(i);
2730 if (r != null && r.thread != null) {
2731 int pid = r.pid;
2732 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
2733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 }
2735 }
2736
Christopher Tate6ee412d2010-05-28 12:01:56 -07002737 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002738
2739 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002740 StringBuilder info = mStringBuilder;
2741 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002742 info.append("ANR in ").append(app.processName);
2743 if (activity != null && activity.shortComponentName != null) {
2744 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002745 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002746 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002747 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002748 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002750 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002751 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753
Dan Egnor42471dd2010-01-07 17:25:22 -08002754 String cpuInfo = null;
2755 if (MONITOR_CPU_USAGE) {
2756 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002757 synchronized (mProcessStatsThread) {
2758 cpuInfo = mProcessStats.printCurrentState();
2759 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002760 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 }
2762
Joe Onorato8a9b2202010-02-26 18:56:32 -08002763 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002764 if (tracesFile == null) {
2765 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2766 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2767 }
2768
2769 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2770
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002771 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002772 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002773 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2774 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002776 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2777 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 }
2779 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002780 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 }
2782 }
2783
Dan Egnor42471dd2010-01-07 17:25:22 -08002784 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2785 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2786 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002787
2788 synchronized (this) {
2789 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2790 Process.killProcess(app.pid);
2791 return;
2792 }
2793
2794 // Set the app's notResponding state, and look up the errorReportReceiver
2795 makeAppNotRespondingLocked(app,
2796 activity != null ? activity.shortComponentName : null,
2797 annotation != null ? "ANR " + annotation : "ANR",
2798 info.toString());
2799
2800 // Bring up the infamous App Not Responding dialog
2801 Message msg = Message.obtain();
2802 HashMap map = new HashMap();
2803 msg.what = SHOW_NOT_RESPONDING_MSG;
2804 msg.obj = map;
2805 map.put("app", app);
2806 if (activity != null) {
2807 map.put("activity", activity);
2808 }
2809
2810 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002812 }
2813
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002814 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 app.persistentActivities--;
2816 if (app.persistentActivities > 0) {
2817 // Still more of 'em...
2818 return;
2819 }
2820 if (app.persistent) {
2821 // Ah, but the application itself is persistent. Whatever!
2822 return;
2823 }
2824
2825 // App is no longer persistent... make sure it and the ones
2826 // following it in the LRU list have the correc oom_adj.
2827 updateOomAdjLocked();
2828 }
2829
2830 public void setPersistent(IBinder token, boolean isPersistent) {
2831 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2832 != PackageManager.PERMISSION_GRANTED) {
2833 String msg = "Permission Denial: setPersistent() from pid="
2834 + Binder.getCallingPid()
2835 + ", uid=" + Binder.getCallingUid()
2836 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002837 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002838 throw new SecurityException(msg);
2839 }
2840
2841 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002842 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002843 if (index < 0) {
2844 return;
2845 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002846 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002847 ProcessRecord app = r.app;
2848
Joe Onorato8a9b2202010-02-26 18:56:32 -08002849 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002850 TAG, "Setting persistence " + isPersistent + ": " + r);
2851
2852 if (isPersistent) {
2853 if (r.persistent) {
2854 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002855 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 return;
2857 }
2858 r.persistent = true;
2859 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002860 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002861 if (app.persistentActivities > 1) {
2862 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002863 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 return;
2865 }
2866 if (app.persistent) {
2867 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002868 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 return;
2870 }
2871
2872 // App is now persistent... make sure it and the ones
2873 // following it now have the correct oom_adj.
2874 final long origId = Binder.clearCallingIdentity();
2875 updateOomAdjLocked();
2876 Binder.restoreCallingIdentity(origId);
2877
2878 } else {
2879 if (!r.persistent) {
2880 // Okay okay, I heard you already!
2881 return;
2882 }
2883 r.persistent = false;
2884 final long origId = Binder.clearCallingIdentity();
2885 decPersistentCountLocked(app);
2886 Binder.restoreCallingIdentity(origId);
2887
2888 }
2889 }
2890 }
2891
2892 public boolean clearApplicationUserData(final String packageName,
2893 final IPackageDataObserver observer) {
2894 int uid = Binder.getCallingUid();
2895 int pid = Binder.getCallingPid();
2896 long callingId = Binder.clearCallingIdentity();
2897 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002898 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 int pkgUid = -1;
2900 synchronized(this) {
2901 try {
2902 pkgUid = pm.getPackageUid(packageName);
2903 } catch (RemoteException e) {
2904 }
2905 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002906 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002907 return false;
2908 }
2909 if (uid == pkgUid || checkComponentPermission(
2910 android.Manifest.permission.CLEAR_APP_USER_DATA,
2911 pid, uid, -1)
2912 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08002913 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914 } else {
2915 throw new SecurityException(pid+" does not have permission:"+
2916 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
2917 "for process:"+packageName);
2918 }
2919 }
2920
2921 try {
2922 //clear application user data
2923 pm.clearApplicationUserData(packageName, observer);
2924 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
2925 Uri.fromParts("package", packageName, null));
2926 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06002927 synchronized (this) {
2928 broadcastIntentLocked(null, null, intent,
2929 null, null, 0, null, null, null,
2930 false, false, MY_PID, Process.SYSTEM_UID);
2931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 } catch (RemoteException e) {
2933 }
2934 } finally {
2935 Binder.restoreCallingIdentity(callingId);
2936 }
2937 return true;
2938 }
2939
Dianne Hackborn03abb812010-01-04 18:43:19 -08002940 public void killBackgroundProcesses(final String packageName) {
2941 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
2942 != PackageManager.PERMISSION_GRANTED &&
2943 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
2944 != PackageManager.PERMISSION_GRANTED) {
2945 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 + Binder.getCallingPid()
2947 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08002948 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002949 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 throw new SecurityException(msg);
2951 }
2952
2953 long callingId = Binder.clearCallingIdentity();
2954 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002955 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002956 int pkgUid = -1;
2957 synchronized(this) {
2958 try {
2959 pkgUid = pm.getPackageUid(packageName);
2960 } catch (RemoteException e) {
2961 }
2962 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002963 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 return;
2965 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08002966 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002967 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002968 }
2969 } finally {
2970 Binder.restoreCallingIdentity(callingId);
2971 }
2972 }
2973
2974 public void forceStopPackage(final String packageName) {
2975 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2976 != PackageManager.PERMISSION_GRANTED) {
2977 String msg = "Permission Denial: forceStopPackage() from pid="
2978 + Binder.getCallingPid()
2979 + ", uid=" + Binder.getCallingUid()
2980 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002981 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002982 throw new SecurityException(msg);
2983 }
2984
2985 long callingId = Binder.clearCallingIdentity();
2986 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002987 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08002988 int pkgUid = -1;
2989 synchronized(this) {
2990 try {
2991 pkgUid = pm.getPackageUid(packageName);
2992 } catch (RemoteException e) {
2993 }
2994 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002995 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002996 return;
2997 }
2998 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002999 }
3000 } finally {
3001 Binder.restoreCallingIdentity(callingId);
3002 }
3003 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003004
3005 /*
3006 * The pkg name and uid have to be specified.
3007 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3008 */
3009 public void killApplicationWithUid(String pkg, int uid) {
3010 if (pkg == null) {
3011 return;
3012 }
3013 // Make sure the uid is valid.
3014 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003015 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003016 return;
3017 }
3018 int callerUid = Binder.getCallingUid();
3019 // Only the system server can kill an application
3020 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003021 // Post an aysnc message to kill the application
3022 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3023 msg.arg1 = uid;
3024 msg.arg2 = 0;
3025 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003026 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003027 } else {
3028 throw new SecurityException(callerUid + " cannot kill pkg: " +
3029 pkg);
3030 }
3031 }
3032
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003033 public void closeSystemDialogs(String reason) {
3034 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3035 if (reason != null) {
3036 intent.putExtra("reason", reason);
3037 }
3038
3039 final int uid = Binder.getCallingUid();
3040 final long origId = Binder.clearCallingIdentity();
3041 synchronized (this) {
3042 int i = mWatchers.beginBroadcast();
3043 while (i > 0) {
3044 i--;
3045 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3046 if (w != null) {
3047 try {
3048 w.closingSystemDialogs(reason);
3049 } catch (RemoteException e) {
3050 }
3051 }
3052 }
3053 mWatchers.finishBroadcast();
3054
Dianne Hackbornffa42482009-09-23 22:20:11 -07003055 mWindowManager.closeSystemDialogs(reason);
3056
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003057 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3058 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003059 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003060 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003061 Activity.RESULT_CANCELED, null, "close-sys");
3062 }
3063 }
3064
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003065 broadcastIntentLocked(null, null, intent, null,
3066 null, 0, null, null, null, false, false, -1, uid);
3067 }
3068 Binder.restoreCallingIdentity(origId);
3069 }
3070
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003071 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003072 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003073 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3074 for (int i=pids.length-1; i>=0; i--) {
3075 infos[i] = new Debug.MemoryInfo();
3076 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003077 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003078 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003079 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003080
3081 public void killApplicationProcess(String processName, int uid) {
3082 if (processName == null) {
3083 return;
3084 }
3085
3086 int callerUid = Binder.getCallingUid();
3087 // Only the system server can kill an application
3088 if (callerUid == Process.SYSTEM_UID) {
3089 synchronized (this) {
3090 ProcessRecord app = getProcessRecordLocked(processName, uid);
3091 if (app != null) {
3092 try {
3093 app.thread.scheduleSuicide();
3094 } catch (RemoteException e) {
3095 // If the other end already died, then our work here is done.
3096 }
3097 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003098 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003099 + processName + " / " + uid);
3100 }
3101 }
3102 } else {
3103 throw new SecurityException(callerUid + " cannot kill app process: " +
3104 processName);
3105 }
3106 }
3107
Dianne Hackborn03abb812010-01-04 18:43:19 -08003108 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003109 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3111 Uri.fromParts("package", packageName, null));
3112 intent.putExtra(Intent.EXTRA_UID, uid);
3113 broadcastIntentLocked(null, null, intent,
3114 null, null, 0, null, null, null,
3115 false, false, MY_PID, Process.SYSTEM_UID);
3116 }
3117
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003118 private final boolean killPackageProcessesLocked(String packageName, int uid,
3119 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003120 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121
Dianne Hackborn03abb812010-01-04 18:43:19 -08003122 // Remove all processes this package may have touched: all with the
3123 // same UID (except for the system or root user), and all whose name
3124 // matches the package name.
3125 final String procNamePrefix = packageName + ":";
3126 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3127 final int NA = apps.size();
3128 for (int ia=0; ia<NA; ia++) {
3129 ProcessRecord app = apps.valueAt(ia);
3130 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003131 if (doit) {
3132 procs.add(app);
3133 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003134 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3135 || app.processName.equals(packageName)
3136 || app.processName.startsWith(procNamePrefix)) {
3137 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003138 if (!doit) {
3139 return true;
3140 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003141 app.removed = true;
3142 procs.add(app);
3143 }
3144 }
3145 }
3146 }
3147
3148 int N = procs.size();
3149 for (int i=0; i<N; i++) {
3150 removeProcessLocked(procs.get(i), callerWillRestart);
3151 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003152 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003153 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003154
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003155 private final boolean forceStopPackageLocked(String name, int uid,
3156 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 int i, N;
3158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 if (uid < 0) {
3160 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003161 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 } catch (RemoteException e) {
3163 }
3164 }
3165
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003166 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003167 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003168
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003169 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3170 while (badApps.hasNext()) {
3171 SparseArray<Long> ba = badApps.next();
3172 if (ba.get(uid) != null) {
3173 badApps.remove();
3174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 }
3176 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003177
3178 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3179 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003181 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3182 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003183 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003184 if (!doit) {
3185 return true;
3186 }
3187 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003188 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 if (r.app != null) {
3190 r.app.removed = true;
3191 }
3192 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003193 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 }
3195 }
3196
3197 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3198 for (ServiceRecord service : mServices.values()) {
3199 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003200 if (!doit) {
3201 return true;
3202 }
3203 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003204 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 if (service.app != null) {
3206 service.app.removed = true;
3207 }
3208 service.app = null;
3209 services.add(service);
3210 }
3211 }
3212
3213 N = services.size();
3214 for (i=0; i<N; i++) {
3215 bringDownServiceLocked(services.get(i), true);
3216 }
3217
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003218 if (doit) {
3219 if (purgeCache) {
3220 AttributeCache ac = AttributeCache.instance();
3221 if (ac != null) {
3222 ac.removePackage(name);
3223 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003224 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003225 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003226 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003227
3228 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 }
3230
3231 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3232 final String name = app.processName;
3233 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003234 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003235 TAG, "Force removing process " + app + " (" + name
3236 + "/" + uid + ")");
3237
3238 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003239 if (mHeavyWeightProcess == app) {
3240 mHeavyWeightProcess = null;
3241 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003243 boolean needRestart = false;
3244 if (app.pid > 0 && app.pid != MY_PID) {
3245 int pid = app.pid;
3246 synchronized (mPidsSelfLocked) {
3247 mPidsSelfLocked.remove(pid);
3248 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3249 }
3250 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003251 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003252 Process.killProcess(pid);
3253
3254 if (app.persistent) {
3255 if (!callerWillRestart) {
3256 addAppLocked(app.info);
3257 } else {
3258 needRestart = true;
3259 }
3260 }
3261 } else {
3262 mRemovedProcesses.add(app);
3263 }
3264
3265 return needRestart;
3266 }
3267
3268 private final void processStartTimedOutLocked(ProcessRecord app) {
3269 final int pid = app.pid;
3270 boolean gone = false;
3271 synchronized (mPidsSelfLocked) {
3272 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3273 if (knownApp != null && knownApp.thread == null) {
3274 mPidsSelfLocked.remove(pid);
3275 gone = true;
3276 }
3277 }
3278
3279 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003280 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003281 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003282 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003283 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003284 if (mHeavyWeightProcess == app) {
3285 mHeavyWeightProcess = null;
3286 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3287 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003288 // Take care of any launching providers waiting for this process.
3289 checkAppInLaunchingProvidersLocked(app, true);
3290 // Take care of any services that are waiting for the process.
3291 for (int i=0; i<mPendingServices.size(); i++) {
3292 ServiceRecord sr = mPendingServices.get(i);
3293 if (app.info.uid == sr.appInfo.uid
3294 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003295 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003296 mPendingServices.remove(i);
3297 i--;
3298 bringDownServiceLocked(sr, true);
3299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003300 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003301 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003302 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003303 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003304 try {
3305 IBackupManager bm = IBackupManager.Stub.asInterface(
3306 ServiceManager.getService(Context.BACKUP_SERVICE));
3307 bm.agentDisconnected(app.info.packageName);
3308 } catch (RemoteException e) {
3309 // Can't happen; the backup manager is local
3310 }
3311 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003312 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003313 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003314 mPendingBroadcast = null;
3315 scheduleBroadcastsLocked();
3316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003318 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 }
3320 }
3321
3322 private final boolean attachApplicationLocked(IApplicationThread thread,
3323 int pid) {
3324
3325 // Find the application record that is being attached... either via
3326 // the pid if we are running in multiple processes, or just pull the
3327 // next app record if we are emulating process with anonymous threads.
3328 ProcessRecord app;
3329 if (pid != MY_PID && pid >= 0) {
3330 synchronized (mPidsSelfLocked) {
3331 app = mPidsSelfLocked.get(pid);
3332 }
3333 } else if (mStartingProcesses.size() > 0) {
3334 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003335 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 } else {
3337 app = null;
3338 }
3339
3340 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003341 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003343 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 if (pid > 0 && pid != MY_PID) {
3345 Process.killProcess(pid);
3346 } else {
3347 try {
3348 thread.scheduleExit();
3349 } catch (Exception e) {
3350 // Ignore exceptions.
3351 }
3352 }
3353 return false;
3354 }
3355
3356 // If this application record is still attached to a previous
3357 // process, clean it up now.
3358 if (app.thread != null) {
3359 handleAppDiedLocked(app, true);
3360 }
3361
3362 // Tell the process all about itself.
3363
Joe Onorato8a9b2202010-02-26 18:56:32 -08003364 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 TAG, "Binding process pid " + pid + " to record " + app);
3366
3367 String processName = app.processName;
3368 try {
3369 thread.asBinder().linkToDeath(new AppDeathRecipient(
3370 app, pid, thread), 0);
3371 } catch (RemoteException e) {
3372 app.resetPackageList();
3373 startProcessLocked(app, "link fail", processName);
3374 return false;
3375 }
3376
Doug Zongker2bec3d42009-12-04 12:52:44 -08003377 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003378
3379 app.thread = thread;
3380 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003381 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3382 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 app.forcingToForeground = null;
3384 app.foregroundServices = false;
3385 app.debugging = false;
3386
3387 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3388
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003389 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3390 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003392 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003393 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003394 }
3395
Joe Onorato8a9b2202010-02-26 18:56:32 -08003396 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397 TAG, "New app record " + app
3398 + " thread=" + thread.asBinder() + " pid=" + pid);
3399 try {
3400 int testMode = IApplicationThread.DEBUG_OFF;
3401 if (mDebugApp != null && mDebugApp.equals(processName)) {
3402 testMode = mWaitForDebugger
3403 ? IApplicationThread.DEBUG_WAIT
3404 : IApplicationThread.DEBUG_ON;
3405 app.debugging = true;
3406 if (mDebugTransient) {
3407 mDebugApp = mOrigDebugApp;
3408 mWaitForDebugger = mOrigWaitForDebugger;
3409 }
3410 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003411
Christopher Tate181fafa2009-05-14 11:12:14 -07003412 // If the app is being launched for restore or full backup, set it up specially
3413 boolean isRestrictedBackupMode = false;
3414 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3415 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3416 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3417 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003418
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003419 ensurePackageDexOpt(app.instrumentationInfo != null
3420 ? app.instrumentationInfo.packageName
3421 : app.info.packageName);
3422 if (app.instrumentationClass != null) {
3423 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003424 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003425 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003426 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003427 thread.bindApplication(processName, app.instrumentationInfo != null
3428 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 app.instrumentationClass, app.instrumentationProfileFile,
3430 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003431 isRestrictedBackupMode || !normalMode,
3432 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003433 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003434 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 } catch (Exception e) {
3436 // todo: Yikes! What should we do? For now we will try to
3437 // start another process, but that could easily get us in
3438 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003439 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440
3441 app.resetPackageList();
3442 startProcessLocked(app, "bind fail", processName);
3443 return false;
3444 }
3445
3446 // Remove this record from the list of starting applications.
3447 mPersistentStartingProcesses.remove(app);
3448 mProcessesOnHold.remove(app);
3449
3450 boolean badApp = false;
3451 boolean didSomething = false;
3452
3453 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003454 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003455 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3457 && processName.equals(hr.processName)) {
3458 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003459 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 didSomething = true;
3461 }
3462 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003463 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 + hr.intent.getComponent().flattenToShortString(), e);
3465 badApp = true;
3466 }
3467 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003468 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 }
3470 }
3471
3472 // Find any services that should be running in this process...
3473 if (!badApp && mPendingServices.size() > 0) {
3474 ServiceRecord sr = null;
3475 try {
3476 for (int i=0; i<mPendingServices.size(); i++) {
3477 sr = mPendingServices.get(i);
3478 if (app.info.uid != sr.appInfo.uid
3479 || !processName.equals(sr.processName)) {
3480 continue;
3481 }
3482
3483 mPendingServices.remove(i);
3484 i--;
3485 realStartServiceLocked(sr, app);
3486 didSomething = true;
3487 }
3488 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003489 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490 + sr.shortName, e);
3491 badApp = true;
3492 }
3493 }
3494
3495 // Check if the next broadcast receiver is in this process...
3496 BroadcastRecord br = mPendingBroadcast;
3497 if (!badApp && br != null && br.curApp == app) {
3498 try {
3499 mPendingBroadcast = null;
3500 processCurBroadcastLocked(br, app);
3501 didSomething = true;
3502 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003503 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 + br.curComponent.flattenToShortString(), e);
3505 badApp = true;
3506 logBroadcastReceiverDiscard(br);
3507 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3508 br.resultExtras, br.resultAbort, true);
3509 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003510 // We need to reset the state if we fails to start the receiver.
3511 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 }
3513 }
3514
Christopher Tate181fafa2009-05-14 11:12:14 -07003515 // Check whether the next backup agent is in this process...
3516 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003517 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003518 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003519 try {
3520 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3521 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003522 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003523 e.printStackTrace();
3524 }
3525 }
3526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003527 if (badApp) {
3528 // todo: Also need to kill application to deal with all
3529 // kinds of exceptions.
3530 handleAppDiedLocked(app, false);
3531 return false;
3532 }
3533
3534 if (!didSomething) {
3535 updateOomAdjLocked();
3536 }
3537
3538 return true;
3539 }
3540
3541 public final void attachApplication(IApplicationThread thread) {
3542 synchronized (this) {
3543 int callingPid = Binder.getCallingPid();
3544 final long origId = Binder.clearCallingIdentity();
3545 attachApplicationLocked(thread, callingPid);
3546 Binder.restoreCallingIdentity(origId);
3547 }
3548 }
3549
Dianne Hackborne88846e2009-09-30 21:34:25 -07003550 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003552 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003553 Binder.restoreCallingIdentity(origId);
3554 }
3555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003557 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003558 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 mWindowManager.enableScreenAfterBoot();
3560 }
3561
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003562 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003563 IntentFilter pkgFilter = new IntentFilter();
3564 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3565 pkgFilter.addDataScheme("package");
3566 mContext.registerReceiver(new BroadcastReceiver() {
3567 @Override
3568 public void onReceive(Context context, Intent intent) {
3569 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3570 if (pkgs != null) {
3571 for (String pkg : pkgs) {
3572 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3573 setResultCode(Activity.RESULT_OK);
3574 return;
3575 }
3576 }
3577 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003578 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003579 }, pkgFilter);
3580
3581 synchronized (this) {
3582 // Ensure that any processes we had put on hold are now started
3583 // up.
3584 final int NP = mProcessesOnHold.size();
3585 if (NP > 0) {
3586 ArrayList<ProcessRecord> procs =
3587 new ArrayList<ProcessRecord>(mProcessesOnHold);
3588 for (int ip=0; ip<NP; ip++) {
3589 this.startProcessLocked(procs.get(ip), "on-hold", null);
3590 }
3591 }
3592
3593 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003594 // Start looking for apps that are abusing wake locks.
3595 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
3596 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003597 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003598 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003599 broadcastIntentLocked(null, null,
3600 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3601 null, null, 0, null, null,
3602 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3603 false, false, MY_PID, Process.SYSTEM_UID);
3604 }
3605 }
3606 }
3607
3608 final void ensureBootCompleted() {
3609 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003610 boolean enableScreen;
3611 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003612 booting = mBooting;
3613 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003614 enableScreen = !mBooted;
3615 mBooted = true;
3616 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003617
3618 if (booting) {
3619 finishBooting();
3620 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003621
3622 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003623 enableScreenAfterBoot();
3624 }
3625 }
3626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 public final void activityPaused(IBinder token, Bundle icicle) {
3628 // Refuse possible leaked file descriptors
3629 if (icicle != null && icicle.hasFileDescriptors()) {
3630 throw new IllegalArgumentException("File descriptors passed in Bundle");
3631 }
3632
3633 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003634 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635 Binder.restoreCallingIdentity(origId);
3636 }
3637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 public final void activityStopped(IBinder token, Bitmap thumbnail,
3639 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003640 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 TAG, "Activity stopped: token=" + token);
3642
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003643 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644
3645 final long origId = Binder.clearCallingIdentity();
3646
3647 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003648 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003649 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003650 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 r.thumbnail = thumbnail;
3652 r.description = description;
3653 r.stopped = true;
3654 r.state = ActivityState.STOPPED;
3655 if (!r.finishing) {
3656 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003657 r.stack.destroyActivityLocked(r, true);
3658 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 }
3660 }
3661 }
3662 }
3663
3664 if (r != null) {
3665 sendPendingThumbnail(r, null, null, null, false);
3666 }
3667
3668 trimApplications();
3669
3670 Binder.restoreCallingIdentity(origId);
3671 }
3672
3673 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003674 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003675 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 }
3677
3678 public String getCallingPackage(IBinder token) {
3679 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003680 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003681 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 }
3683 }
3684
3685 public ComponentName getCallingActivity(IBinder token) {
3686 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003687 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 return r != null ? r.intent.getComponent() : null;
3689 }
3690 }
3691
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003692 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003693 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003695 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003696 if (r != null) {
3697 return r.resultTo;
3698 }
3699 }
3700 return null;
3701 }
3702
3703 public ComponentName getActivityClassForToken(IBinder token) {
3704 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003705 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003707 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 return r.intent.getComponent();
3709 }
3710 return null;
3711 }
3712 }
3713
3714 public String getPackageForToken(IBinder token) {
3715 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003716 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003718 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003719 return r.packageName;
3720 }
3721 return null;
3722 }
3723 }
3724
3725 public IIntentSender getIntentSender(int type,
3726 String packageName, IBinder token, String resultWho,
3727 int requestCode, Intent intent, String resolvedType, int flags) {
3728 // Refuse possible leaked file descriptors
3729 if (intent != null && intent.hasFileDescriptors() == true) {
3730 throw new IllegalArgumentException("File descriptors passed in Intent");
3731 }
3732
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003733 if (type == INTENT_SENDER_BROADCAST) {
3734 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3735 throw new IllegalArgumentException(
3736 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3737 }
3738 }
3739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 synchronized(this) {
3741 int callingUid = Binder.getCallingUid();
3742 try {
3743 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3744 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003745 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003746 .getPackageUid(packageName);
3747 if (uid != Binder.getCallingUid()) {
3748 String msg = "Permission Denial: getIntentSender() from pid="
3749 + Binder.getCallingPid()
3750 + ", uid=" + Binder.getCallingUid()
3751 + ", (need uid=" + uid + ")"
3752 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003753 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 throw new SecurityException(msg);
3755 }
3756 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003757
3758 return getIntentSenderLocked(type, packageName, callingUid,
3759 token, resultWho, requestCode, intent, resolvedType, flags);
3760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003761 } catch (RemoteException e) {
3762 throw new SecurityException(e);
3763 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003764 }
3765 }
3766
3767 IIntentSender getIntentSenderLocked(int type,
3768 String packageName, int callingUid, IBinder token, String resultWho,
3769 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003770 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003771 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003772 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003773 if (index < 0) {
3774 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003776 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003777 if (activity.finishing) {
3778 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003780 }
3781
3782 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3783 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3784 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3785 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3786 |PendingIntent.FLAG_UPDATE_CURRENT);
3787
3788 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3789 type, packageName, activity, resultWho,
3790 requestCode, intent, resolvedType, flags);
3791 WeakReference<PendingIntentRecord> ref;
3792 ref = mIntentSenderRecords.get(key);
3793 PendingIntentRecord rec = ref != null ? ref.get() : null;
3794 if (rec != null) {
3795 if (!cancelCurrent) {
3796 if (updateCurrent) {
3797 rec.key.requestIntent.replaceExtras(intent);
3798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 return rec;
3800 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003801 rec.canceled = true;
3802 mIntentSenderRecords.remove(key);
3803 }
3804 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 return rec;
3806 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003807 rec = new PendingIntentRecord(this, key, callingUid);
3808 mIntentSenderRecords.put(key, rec.ref);
3809 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3810 if (activity.pendingResults == null) {
3811 activity.pendingResults
3812 = new HashSet<WeakReference<PendingIntentRecord>>();
3813 }
3814 activity.pendingResults.add(rec.ref);
3815 }
3816 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 }
3818
3819 public void cancelIntentSender(IIntentSender sender) {
3820 if (!(sender instanceof PendingIntentRecord)) {
3821 return;
3822 }
3823 synchronized(this) {
3824 PendingIntentRecord rec = (PendingIntentRecord)sender;
3825 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003826 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 .getPackageUid(rec.key.packageName);
3828 if (uid != Binder.getCallingUid()) {
3829 String msg = "Permission Denial: cancelIntentSender() from pid="
3830 + Binder.getCallingPid()
3831 + ", uid=" + Binder.getCallingUid()
3832 + " is not allowed to cancel packges "
3833 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003834 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 throw new SecurityException(msg);
3836 }
3837 } catch (RemoteException e) {
3838 throw new SecurityException(e);
3839 }
3840 cancelIntentSenderLocked(rec, true);
3841 }
3842 }
3843
3844 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3845 rec.canceled = true;
3846 mIntentSenderRecords.remove(rec.key);
3847 if (cleanActivity && rec.key.activity != null) {
3848 rec.key.activity.pendingResults.remove(rec.ref);
3849 }
3850 }
3851
3852 public String getPackageForIntentSender(IIntentSender pendingResult) {
3853 if (!(pendingResult instanceof PendingIntentRecord)) {
3854 return null;
3855 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003856 try {
3857 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3858 return res.key.packageName;
3859 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 }
3861 return null;
3862 }
3863
3864 public void setProcessLimit(int max) {
3865 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3866 "setProcessLimit()");
3867 mProcessLimit = max;
3868 }
3869
3870 public int getProcessLimit() {
3871 return mProcessLimit;
3872 }
3873
3874 void foregroundTokenDied(ForegroundToken token) {
3875 synchronized (ActivityManagerService.this) {
3876 synchronized (mPidsSelfLocked) {
3877 ForegroundToken cur
3878 = mForegroundProcesses.get(token.pid);
3879 if (cur != token) {
3880 return;
3881 }
3882 mForegroundProcesses.remove(token.pid);
3883 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3884 if (pr == null) {
3885 return;
3886 }
3887 pr.forcingToForeground = null;
3888 pr.foregroundServices = false;
3889 }
3890 updateOomAdjLocked();
3891 }
3892 }
3893
3894 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3895 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3896 "setProcessForeground()");
3897 synchronized(this) {
3898 boolean changed = false;
3899
3900 synchronized (mPidsSelfLocked) {
3901 ProcessRecord pr = mPidsSelfLocked.get(pid);
3902 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003903 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003904 return;
3905 }
3906 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3907 if (oldToken != null) {
3908 oldToken.token.unlinkToDeath(oldToken, 0);
3909 mForegroundProcesses.remove(pid);
3910 pr.forcingToForeground = null;
3911 changed = true;
3912 }
3913 if (isForeground && token != null) {
3914 ForegroundToken newToken = new ForegroundToken() {
3915 public void binderDied() {
3916 foregroundTokenDied(this);
3917 }
3918 };
3919 newToken.pid = pid;
3920 newToken.token = token;
3921 try {
3922 token.linkToDeath(newToken, 0);
3923 mForegroundProcesses.put(pid, newToken);
3924 pr.forcingToForeground = token;
3925 changed = true;
3926 } catch (RemoteException e) {
3927 // If the process died while doing this, we will later
3928 // do the cleanup with the process death link.
3929 }
3930 }
3931 }
3932
3933 if (changed) {
3934 updateOomAdjLocked();
3935 }
3936 }
3937 }
3938
3939 // =========================================================
3940 // PERMISSIONS
3941 // =========================================================
3942
3943 static class PermissionController extends IPermissionController.Stub {
3944 ActivityManagerService mActivityManagerService;
3945 PermissionController(ActivityManagerService activityManagerService) {
3946 mActivityManagerService = activityManagerService;
3947 }
3948
3949 public boolean checkPermission(String permission, int pid, int uid) {
3950 return mActivityManagerService.checkPermission(permission, pid,
3951 uid) == PackageManager.PERMISSION_GRANTED;
3952 }
3953 }
3954
3955 /**
3956 * This can be called with or without the global lock held.
3957 */
3958 int checkComponentPermission(String permission, int pid, int uid,
3959 int reqUid) {
3960 // We might be performing an operation on behalf of an indirect binder
3961 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
3962 // client identity accordingly before proceeding.
3963 Identity tlsIdentity = sCallerIdentity.get();
3964 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003965 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
3967 uid = tlsIdentity.uid;
3968 pid = tlsIdentity.pid;
3969 }
3970
3971 // Root, system server and our own process get to do everything.
3972 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
3973 !Process.supportsProcesses()) {
3974 return PackageManager.PERMISSION_GRANTED;
3975 }
3976 // If the target requires a specific UID, always fail for others.
3977 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003978 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 return PackageManager.PERMISSION_DENIED;
3980 }
3981 if (permission == null) {
3982 return PackageManager.PERMISSION_GRANTED;
3983 }
3984 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003985 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003986 .checkUidPermission(permission, uid);
3987 } catch (RemoteException e) {
3988 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003989 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003990 }
3991 return PackageManager.PERMISSION_DENIED;
3992 }
3993
3994 /**
3995 * As the only public entry point for permissions checking, this method
3996 * can enforce the semantic that requesting a check on a null global
3997 * permission is automatically denied. (Internally a null permission
3998 * string is used when calling {@link #checkComponentPermission} in cases
3999 * when only uid-based security is needed.)
4000 *
4001 * This can be called with or without the global lock held.
4002 */
4003 public int checkPermission(String permission, int pid, int uid) {
4004 if (permission == null) {
4005 return PackageManager.PERMISSION_DENIED;
4006 }
4007 return checkComponentPermission(permission, pid, uid, -1);
4008 }
4009
4010 /**
4011 * Binder IPC calls go through the public entry point.
4012 * This can be called with or without the global lock held.
4013 */
4014 int checkCallingPermission(String permission) {
4015 return checkPermission(permission,
4016 Binder.getCallingPid(),
4017 Binder.getCallingUid());
4018 }
4019
4020 /**
4021 * This can be called with or without the global lock held.
4022 */
4023 void enforceCallingPermission(String permission, String func) {
4024 if (checkCallingPermission(permission)
4025 == PackageManager.PERMISSION_GRANTED) {
4026 return;
4027 }
4028
4029 String msg = "Permission Denial: " + func + " from pid="
4030 + Binder.getCallingPid()
4031 + ", uid=" + Binder.getCallingUid()
4032 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004033 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 throw new SecurityException(msg);
4035 }
4036
4037 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4038 ProviderInfo pi, int uid, int modeFlags) {
4039 try {
4040 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4041 if ((pi.readPermission != null) &&
4042 (pm.checkUidPermission(pi.readPermission, uid)
4043 != PackageManager.PERMISSION_GRANTED)) {
4044 return false;
4045 }
4046 }
4047 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4048 if ((pi.writePermission != null) &&
4049 (pm.checkUidPermission(pi.writePermission, uid)
4050 != PackageManager.PERMISSION_GRANTED)) {
4051 return false;
4052 }
4053 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004054 if (!pi.exported && pi.applicationInfo.uid != uid) {
4055 return false;
4056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 return true;
4058 } catch (RemoteException e) {
4059 return false;
4060 }
4061 }
4062
4063 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4064 int modeFlags) {
4065 // Root gets to do everything.
4066 if (uid == 0 || !Process.supportsProcesses()) {
4067 return true;
4068 }
4069 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4070 if (perms == null) return false;
4071 UriPermission perm = perms.get(uri);
4072 if (perm == null) return false;
4073 return (modeFlags&perm.modeFlags) == modeFlags;
4074 }
4075
4076 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4077 // Another redirected-binder-call permissions check as in
4078 // {@link checkComponentPermission}.
4079 Identity tlsIdentity = sCallerIdentity.get();
4080 if (tlsIdentity != null) {
4081 uid = tlsIdentity.uid;
4082 pid = tlsIdentity.pid;
4083 }
4084
4085 // Our own process gets to do everything.
4086 if (pid == MY_PID) {
4087 return PackageManager.PERMISSION_GRANTED;
4088 }
4089 synchronized(this) {
4090 return checkUriPermissionLocked(uri, uid, modeFlags)
4091 ? PackageManager.PERMISSION_GRANTED
4092 : PackageManager.PERMISSION_DENIED;
4093 }
4094 }
4095
Dianne Hackborn39792d22010-08-19 18:01:52 -07004096 /**
4097 * Check if the targetPkg can be granted permission to access uri by
4098 * the callingUid using the given modeFlags. Throws a security exception
4099 * if callingUid is not allowed to do this. Returns the uid of the target
4100 * if the URI permission grant should be performed; returns -1 if it is not
4101 * needed (for example targetPkg already has permission to access the URI).
4102 */
4103 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4104 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004105 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4106 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4107 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004108 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004109 }
4110
Joe Onorato8a9b2202010-02-26 18:56:32 -08004111 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004112 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004113
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004114 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115
4116 // If this is not a content: uri, we can't do anything with it.
4117 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004118 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004119 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004120 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 }
4122
4123 String name = uri.getAuthority();
4124 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004125 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004126 if (cpr != null) {
4127 pi = cpr.info;
4128 } else {
4129 try {
4130 pi = pm.resolveContentProvider(name,
4131 PackageManager.GET_URI_PERMISSION_PATTERNS);
4132 } catch (RemoteException ex) {
4133 }
4134 }
4135 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004136 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004137 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004138 }
4139
4140 int targetUid;
4141 try {
4142 targetUid = pm.getPackageUid(targetPkg);
4143 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004144 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004145 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004146 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004147 }
4148 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004149 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 }
4151
4152 // First... does the target actually need this permission?
4153 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4154 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004155 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004156 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004157 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 }
4159
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004160 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 if (!pi.grantUriPermissions) {
4162 throw new SecurityException("Provider " + pi.packageName
4163 + "/" + pi.name
4164 + " does not allow granting of Uri permissions (uri "
4165 + uri + ")");
4166 }
4167 if (pi.uriPermissionPatterns != null) {
4168 final int N = pi.uriPermissionPatterns.length;
4169 boolean allowed = false;
4170 for (int i=0; i<N; i++) {
4171 if (pi.uriPermissionPatterns[i] != null
4172 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4173 allowed = true;
4174 break;
4175 }
4176 }
4177 if (!allowed) {
4178 throw new SecurityException("Provider " + pi.packageName
4179 + "/" + pi.name
4180 + " does not allow granting of permission to path of Uri "
4181 + uri);
4182 }
4183 }
4184
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004185 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004186 // this uri?
4187 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4188 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4189 throw new SecurityException("Uid " + callingUid
4190 + " does not have permission to uri " + uri);
4191 }
4192 }
4193
Dianne Hackborn39792d22010-08-19 18:01:52 -07004194 return targetUid;
4195 }
4196
4197 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4198 Uri uri, int modeFlags, UriPermissionOwner owner) {
4199 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4200 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4201 if (modeFlags == 0) {
4202 return;
4203 }
4204
4205 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206 // to the uri, and the target doesn't. Let's now give this to
4207 // the target.
4208
Joe Onorato8a9b2202010-02-26 18:56:32 -08004209 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004210 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 HashMap<Uri, UriPermission> targetUris
4213 = mGrantedUriPermissions.get(targetUid);
4214 if (targetUris == null) {
4215 targetUris = new HashMap<Uri, UriPermission>();
4216 mGrantedUriPermissions.put(targetUid, targetUris);
4217 }
4218
4219 UriPermission perm = targetUris.get(uri);
4220 if (perm == null) {
4221 perm = new UriPermission(targetUid, uri);
4222 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004226 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 perm.globalModeFlags |= modeFlags;
4228 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004229 perm.readOwners.add(owner);
4230 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004231 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004232 perm.writeOwners.add(owner);
4233 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 }
4235 }
4236
Dianne Hackborn39792d22010-08-19 18:01:52 -07004237 void grantUriPermissionLocked(int callingUid,
4238 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4239 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4240 if (targetUid < 0) {
4241 return;
4242 }
4243
4244 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4245 }
4246
4247 /**
4248 * Like checkGrantUriPermissionLocked, but takes an Intent.
4249 */
4250 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4251 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004252 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004253 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004254 + " from " + intent + "; flags=0x"
4255 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004257 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004258 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 }
4260 Uri data = intent.getData();
4261 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004262 return -1;
4263 }
4264 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4265 intent.getFlags());
4266 }
4267
4268 /**
4269 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4270 */
4271 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4272 String targetPkg, Intent intent, UriPermissionOwner owner) {
4273 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4274 intent.getFlags(), owner);
4275 }
4276
4277 void grantUriPermissionFromIntentLocked(int callingUid,
4278 String targetPkg, Intent intent, UriPermissionOwner owner) {
4279 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4280 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 return;
4282 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004283
4284 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 }
4286
4287 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4288 Uri uri, int modeFlags) {
4289 synchronized(this) {
4290 final ProcessRecord r = getRecordForAppLocked(caller);
4291 if (r == null) {
4292 throw new SecurityException("Unable to find app for caller "
4293 + caller
4294 + " when granting permission to uri " + uri);
4295 }
4296 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004297 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 return;
4299 }
4300 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004301 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 return;
4303 }
4304
4305 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4306 null);
4307 }
4308 }
4309
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004310 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4312 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4313 HashMap<Uri, UriPermission> perms
4314 = mGrantedUriPermissions.get(perm.uid);
4315 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004316 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004317 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 perms.remove(perm.uri);
4319 if (perms.size() == 0) {
4320 mGrantedUriPermissions.remove(perm.uid);
4321 }
4322 }
4323 }
4324 }
4325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004326 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4327 int modeFlags) {
4328 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4329 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4330 if (modeFlags == 0) {
4331 return;
4332 }
4333
Joe Onorato8a9b2202010-02-26 18:56:32 -08004334 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004335 "Revoking all granted permissions to " + uri);
4336
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004337 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338
4339 final String authority = uri.getAuthority();
4340 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004341 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004342 if (cpr != null) {
4343 pi = cpr.info;
4344 } else {
4345 try {
4346 pi = pm.resolveContentProvider(authority,
4347 PackageManager.GET_URI_PERMISSION_PATTERNS);
4348 } catch (RemoteException ex) {
4349 }
4350 }
4351 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004352 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004353 return;
4354 }
4355
4356 // Does the caller have this permission on the URI?
4357 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4358 // Right now, if you are not the original owner of the permission,
4359 // you are not allowed to revoke it.
4360 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4361 throw new SecurityException("Uid " + callingUid
4362 + " does not have permission to uri " + uri);
4363 //}
4364 }
4365
4366 // Go through all of the permissions and remove any that match.
4367 final List<String> SEGMENTS = uri.getPathSegments();
4368 if (SEGMENTS != null) {
4369 final int NS = SEGMENTS.size();
4370 int N = mGrantedUriPermissions.size();
4371 for (int i=0; i<N; i++) {
4372 HashMap<Uri, UriPermission> perms
4373 = mGrantedUriPermissions.valueAt(i);
4374 Iterator<UriPermission> it = perms.values().iterator();
4375 toploop:
4376 while (it.hasNext()) {
4377 UriPermission perm = it.next();
4378 Uri targetUri = perm.uri;
4379 if (!authority.equals(targetUri.getAuthority())) {
4380 continue;
4381 }
4382 List<String> targetSegments = targetUri.getPathSegments();
4383 if (targetSegments == null) {
4384 continue;
4385 }
4386 if (targetSegments.size() < NS) {
4387 continue;
4388 }
4389 for (int j=0; j<NS; j++) {
4390 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4391 continue toploop;
4392 }
4393 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004394 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004395 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 perm.clearModes(modeFlags);
4397 if (perm.modeFlags == 0) {
4398 it.remove();
4399 }
4400 }
4401 if (perms.size() == 0) {
4402 mGrantedUriPermissions.remove(
4403 mGrantedUriPermissions.keyAt(i));
4404 N--;
4405 i--;
4406 }
4407 }
4408 }
4409 }
4410
4411 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4412 int modeFlags) {
4413 synchronized(this) {
4414 final ProcessRecord r = getRecordForAppLocked(caller);
4415 if (r == null) {
4416 throw new SecurityException("Unable to find app for caller "
4417 + caller
4418 + " when revoking permission to uri " + uri);
4419 }
4420 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004421 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 return;
4423 }
4424
4425 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4426 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4427 if (modeFlags == 0) {
4428 return;
4429 }
4430
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004431 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432
4433 final String authority = uri.getAuthority();
4434 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004435 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 if (cpr != null) {
4437 pi = cpr.info;
4438 } else {
4439 try {
4440 pi = pm.resolveContentProvider(authority,
4441 PackageManager.GET_URI_PERMISSION_PATTERNS);
4442 } catch (RemoteException ex) {
4443 }
4444 }
4445 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004446 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 return;
4448 }
4449
4450 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4451 }
4452 }
4453
4454 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4455 synchronized (this) {
4456 ProcessRecord app =
4457 who != null ? getRecordForAppLocked(who) : null;
4458 if (app == null) return;
4459
4460 Message msg = Message.obtain();
4461 msg.what = WAIT_FOR_DEBUGGER_MSG;
4462 msg.obj = app;
4463 msg.arg1 = waiting ? 1 : 0;
4464 mHandler.sendMessage(msg);
4465 }
4466 }
4467
4468 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4469 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004470 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004472 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 }
4474
4475 // =========================================================
4476 // TASK MANAGEMENT
4477 // =========================================================
4478
4479 public List getTasks(int maxNum, int flags,
4480 IThumbnailReceiver receiver) {
4481 ArrayList list = new ArrayList();
4482
4483 PendingThumbnailsRecord pending = null;
4484 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004485 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486
4487 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4490 + ", receiver=" + receiver);
4491
4492 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4493 != PackageManager.PERMISSION_GRANTED) {
4494 if (receiver != null) {
4495 // If the caller wants to wait for pending thumbnails,
4496 // it ain't gonna get them.
4497 try {
4498 receiver.finished();
4499 } catch (RemoteException ex) {
4500 }
4501 }
4502 String msg = "Permission Denial: getTasks() from pid="
4503 + Binder.getCallingPid()
4504 + ", uid=" + Binder.getCallingUid()
4505 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004506 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004507 throw new SecurityException(msg);
4508 }
4509
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004510 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004511 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004512 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004513 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 CharSequence topDescription = null;
4515 TaskRecord curTask = null;
4516 int numActivities = 0;
4517 int numRunning = 0;
4518 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004519 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004520 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004521 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004522
4523 // Initialize state for next task if needed.
4524 if (top == null ||
4525 (top.state == ActivityState.INITIALIZING
4526 && top.task == r.task)) {
4527 top = r;
4528 topDescription = r.description;
4529 curTask = r.task;
4530 numActivities = numRunning = 0;
4531 }
4532
4533 // Add 'r' into the current task.
4534 numActivities++;
4535 if (r.app != null && r.app.thread != null) {
4536 numRunning++;
4537 }
4538 if (topDescription == null) {
4539 topDescription = r.description;
4540 }
4541
Joe Onorato8a9b2202010-02-26 18:56:32 -08004542 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004543 TAG, r.intent.getComponent().flattenToShortString()
4544 + ": task=" + r.task);
4545
4546 // If the next one is a different task, generate a new
4547 // TaskInfo entry for what we have.
4548 if (next == null || next.task != curTask) {
4549 ActivityManager.RunningTaskInfo ci
4550 = new ActivityManager.RunningTaskInfo();
4551 ci.id = curTask.taskId;
4552 ci.baseActivity = r.intent.getComponent();
4553 ci.topActivity = top.intent.getComponent();
4554 ci.thumbnail = top.thumbnail;
4555 ci.description = topDescription;
4556 ci.numActivities = numActivities;
4557 ci.numRunning = numRunning;
4558 //System.out.println(
4559 // "#" + maxNum + ": " + " descr=" + ci.description);
4560 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004561 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004562 TAG, "State=" + top.state + "Idle=" + top.idle
4563 + " app=" + top.app
4564 + " thr=" + (top.app != null ? top.app.thread : null));
4565 if (top.state == ActivityState.RESUMED
4566 || top.state == ActivityState.PAUSING) {
4567 if (top.idle && top.app != null
4568 && top.app.thread != null) {
4569 topRecord = top;
4570 topThumbnail = top.app.thread;
4571 } else {
4572 top.thumbnailNeeded = true;
4573 }
4574 }
4575 if (pending == null) {
4576 pending = new PendingThumbnailsRecord(receiver);
4577 }
4578 pending.pendingRecords.add(top);
4579 }
4580 list.add(ci);
4581 maxNum--;
4582 top = null;
4583 }
4584 }
4585
4586 if (pending != null) {
4587 mPendingThumbnails.add(pending);
4588 }
4589 }
4590
Joe Onorato8a9b2202010-02-26 18:56:32 -08004591 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592
4593 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004594 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004595 try {
4596 topThumbnail.requestThumbnail(topRecord);
4597 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004598 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 sendPendingThumbnail(null, topRecord, null, null, true);
4600 }
4601 }
4602
4603 if (pending == null && receiver != null) {
4604 // In this case all thumbnails were available and the client
4605 // is being asked to be told when the remaining ones come in...
4606 // which is unusually, since the top-most currently running
4607 // activity should never have a canned thumbnail! Oh well.
4608 try {
4609 receiver.finished();
4610 } catch (RemoteException ex) {
4611 }
4612 }
4613
4614 return list;
4615 }
4616
4617 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4618 int flags) {
4619 synchronized (this) {
4620 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4621 "getRecentTasks()");
4622
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004623 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 final int N = mRecentTasks.size();
4626 ArrayList<ActivityManager.RecentTaskInfo> res
4627 = new ArrayList<ActivityManager.RecentTaskInfo>(
4628 maxNum < N ? maxNum : N);
4629 for (int i=0; i<N && maxNum > 0; i++) {
4630 TaskRecord tr = mRecentTasks.get(i);
4631 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4632 || (tr.intent == null)
4633 || ((tr.intent.getFlags()
4634 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4635 ActivityManager.RecentTaskInfo rti
4636 = new ActivityManager.RecentTaskInfo();
4637 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4638 rti.baseIntent = new Intent(
4639 tr.intent != null ? tr.intent : tr.affinityIntent);
4640 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004641
4642 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4643 // Check whether this activity is currently available.
4644 try {
4645 if (rti.origActivity != null) {
4646 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4647 continue;
4648 }
4649 } else if (rti.baseIntent != null) {
4650 if (pm.queryIntentActivities(rti.baseIntent,
4651 null, 0) == null) {
4652 continue;
4653 }
4654 }
4655 } catch (RemoteException e) {
4656 // Will never happen.
4657 }
4658 }
4659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004660 res.add(rti);
4661 maxNum--;
4662 }
4663 }
4664 return res;
4665 }
4666 }
4667
4668 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4669 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004670 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004671 TaskRecord jt = startTask;
4672
4673 // First look backwards
4674 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004675 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004676 if (r.task != jt) {
4677 jt = r.task;
4678 if (affinity.equals(jt.affinity)) {
4679 return j;
4680 }
4681 }
4682 }
4683
4684 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004685 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686 jt = startTask;
4687 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004688 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004689 if (r.task != jt) {
4690 if (affinity.equals(jt.affinity)) {
4691 return j;
4692 }
4693 jt = r.task;
4694 }
4695 }
4696
4697 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004698 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004699 return N-1;
4700 }
4701
4702 return -1;
4703 }
4704
4705 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004706 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 */
4708 public void moveTaskToFront(int task) {
4709 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4710 "moveTaskToFront()");
4711
4712 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004713 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4714 Binder.getCallingUid(), "Task to front")) {
4715 return;
4716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 final long origId = Binder.clearCallingIdentity();
4718 try {
4719 int N = mRecentTasks.size();
4720 for (int i=0; i<N; i++) {
4721 TaskRecord tr = mRecentTasks.get(i);
4722 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004723 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 return;
4725 }
4726 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004727 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4728 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004730 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731 return;
4732 }
4733 }
4734 } finally {
4735 Binder.restoreCallingIdentity(origId);
4736 }
4737 }
4738 }
4739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 public void moveTaskToBack(int task) {
4741 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4742 "moveTaskToBack()");
4743
4744 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004745 if (mMainStack.mResumedActivity != null
4746 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004747 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4748 Binder.getCallingUid(), "Task to back")) {
4749 return;
4750 }
4751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004753 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 Binder.restoreCallingIdentity(origId);
4755 }
4756 }
4757
4758 /**
4759 * Moves an activity, and all of the other activities within the same task, to the bottom
4760 * of the history stack. The activity's order within the task is unchanged.
4761 *
4762 * @param token A reference to the activity we wish to move
4763 * @param nonRoot If false then this only works if the activity is the root
4764 * of a task; if true it will work for any activity in a task.
4765 * @return Returns true if the move completed, false if not.
4766 */
4767 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4768 synchronized(this) {
4769 final long origId = Binder.clearCallingIdentity();
4770 int taskId = getTaskForActivityLocked(token, !nonRoot);
4771 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004772 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 }
4774 Binder.restoreCallingIdentity(origId);
4775 }
4776 return false;
4777 }
4778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004779 public void moveTaskBackwards(int task) {
4780 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4781 "moveTaskBackwards()");
4782
4783 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004784 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4785 Binder.getCallingUid(), "Task backwards")) {
4786 return;
4787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 final long origId = Binder.clearCallingIdentity();
4789 moveTaskBackwardsLocked(task);
4790 Binder.restoreCallingIdentity(origId);
4791 }
4792 }
4793
4794 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004795 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 }
4797
4798 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4799 synchronized(this) {
4800 return getTaskForActivityLocked(token, onlyRoot);
4801 }
4802 }
4803
4804 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004805 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 TaskRecord lastTask = null;
4807 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004808 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 if (r == token) {
4810 if (!onlyRoot || lastTask != r.task) {
4811 return r.task.taskId;
4812 }
4813 return -1;
4814 }
4815 lastTask = r.task;
4816 }
4817
4818 return -1;
4819 }
4820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004821 public void finishOtherInstances(IBinder token, ComponentName className) {
4822 synchronized(this) {
4823 final long origId = Binder.clearCallingIdentity();
4824
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004825 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 TaskRecord lastTask = null;
4827 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004828 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004829 if (r.realActivity.equals(className)
4830 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004831 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 null, "others")) {
4833 i--;
4834 N--;
4835 }
4836 }
4837 lastTask = r.task;
4838 }
4839
4840 Binder.restoreCallingIdentity(origId);
4841 }
4842 }
4843
4844 // =========================================================
4845 // THUMBNAILS
4846 // =========================================================
4847
4848 public void reportThumbnail(IBinder token,
4849 Bitmap thumbnail, CharSequence description) {
4850 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4851 final long origId = Binder.clearCallingIdentity();
4852 sendPendingThumbnail(null, token, thumbnail, description, true);
4853 Binder.restoreCallingIdentity(origId);
4854 }
4855
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004856 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857 Bitmap thumbnail, CharSequence description, boolean always) {
4858 TaskRecord task = null;
4859 ArrayList receivers = null;
4860
4861 //System.out.println("Send pending thumbnail: " + r);
4862
4863 synchronized(this) {
4864 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004865 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 if (index < 0) {
4867 return;
4868 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004869 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004870 }
4871 if (thumbnail == null) {
4872 thumbnail = r.thumbnail;
4873 description = r.description;
4874 }
4875 if (thumbnail == null && !always) {
4876 // If there is no thumbnail, and this entry is not actually
4877 // going away, then abort for now and pick up the next
4878 // thumbnail we get.
4879 return;
4880 }
4881 task = r.task;
4882
4883 int N = mPendingThumbnails.size();
4884 int i=0;
4885 while (i<N) {
4886 PendingThumbnailsRecord pr =
4887 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4888 //System.out.println("Looking in " + pr.pendingRecords);
4889 if (pr.pendingRecords.remove(r)) {
4890 if (receivers == null) {
4891 receivers = new ArrayList();
4892 }
4893 receivers.add(pr);
4894 if (pr.pendingRecords.size() == 0) {
4895 pr.finished = true;
4896 mPendingThumbnails.remove(i);
4897 N--;
4898 continue;
4899 }
4900 }
4901 i++;
4902 }
4903 }
4904
4905 if (receivers != null) {
4906 final int N = receivers.size();
4907 for (int i=0; i<N; i++) {
4908 try {
4909 PendingThumbnailsRecord pr =
4910 (PendingThumbnailsRecord)receivers.get(i);
4911 pr.receiver.newThumbnail(
4912 task != null ? task.taskId : -1, thumbnail, description);
4913 if (pr.finished) {
4914 pr.receiver.finished();
4915 }
4916 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004917 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 }
4919 }
4920 }
4921 }
4922
4923 // =========================================================
4924 // CONTENT PROVIDERS
4925 // =========================================================
4926
4927 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4928 List providers = null;
4929 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004930 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004931 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004932 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 } catch (RemoteException ex) {
4934 }
4935 if (providers != null) {
4936 final int N = providers.size();
4937 for (int i=0; i<N; i++) {
4938 ProviderInfo cpi =
4939 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004940 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 if (cpr == null) {
4942 cpr = new ContentProviderRecord(cpi, app.info);
4943 mProvidersByClass.put(cpi.name, cpr);
4944 }
4945 app.pubProviders.put(cpi.name, cpr);
4946 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004947 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 }
4949 }
4950 return providers;
4951 }
4952
4953 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07004954 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
4956 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
4957 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
4958 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004959 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 return null;
4961 }
4962 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
4963 cpi.exported ? -1 : cpi.applicationInfo.uid)
4964 == PackageManager.PERMISSION_GRANTED) {
4965 return null;
4966 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004967
4968 PathPermission[] pps = cpi.pathPermissions;
4969 if (pps != null) {
4970 int i = pps.length;
4971 while (i > 0) {
4972 i--;
4973 PathPermission pp = pps[i];
4974 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
4975 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004976 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004977 return null;
4978 }
4979 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
4980 cpi.exported ? -1 : cpi.applicationInfo.uid)
4981 == PackageManager.PERMISSION_GRANTED) {
4982 return null;
4983 }
4984 }
4985 }
4986
Dianne Hackbornb424b632010-08-18 15:59:05 -07004987 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
4988 if (perms != null) {
4989 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
4990 if (uri.getKey().getAuthority().equals(cpi.authority)) {
4991 return null;
4992 }
4993 }
4994 }
4995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 String msg = "Permission Denial: opening provider " + cpi.name
4997 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
4998 + ", uid=" + callingUid + ") requires "
4999 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005000 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 return msg;
5002 }
5003
5004 private final ContentProviderHolder getContentProviderImpl(
5005 IApplicationThread caller, String name) {
5006 ContentProviderRecord cpr;
5007 ProviderInfo cpi = null;
5008
5009 synchronized(this) {
5010 ProcessRecord r = null;
5011 if (caller != null) {
5012 r = getRecordForAppLocked(caller);
5013 if (r == null) {
5014 throw new SecurityException(
5015 "Unable to find app for caller " + caller
5016 + " (pid=" + Binder.getCallingPid()
5017 + ") when getting content provider " + name);
5018 }
5019 }
5020
5021 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005022 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 if (cpr != null) {
5024 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005025 String msg;
5026 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5027 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005028 }
5029
5030 if (r != null && cpr.canRunHere(r)) {
5031 // This provider has been published or is in the process
5032 // of being published... but it is also allowed to run
5033 // in the caller's process, so don't make a connection
5034 // and just let the caller instantiate its own instance.
5035 if (cpr.provider != null) {
5036 // don't give caller the provider object, it needs
5037 // to make its own.
5038 cpr = new ContentProviderRecord(cpr);
5039 }
5040 return cpr;
5041 }
5042
5043 final long origId = Binder.clearCallingIdentity();
5044
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005045 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 // return it right away.
5047 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005048 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005049 "Adding provider requested by "
5050 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005051 + cpr.info.processName);
5052 Integer cnt = r.conProviders.get(cpr);
5053 if (cnt == null) {
5054 r.conProviders.put(cpr, new Integer(1));
5055 } else {
5056 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5057 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005059 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5060 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005061 // make sure to count it as being accessed and thus
5062 // back up on the LRU list. This is good because
5063 // content providers are often expensive to start.
5064 updateLruProcessLocked(cpr.app, false, true);
5065 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005066 } else {
5067 cpr.externals++;
5068 }
5069
5070 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 updateOomAdjLocked(cpr.app);
5072 }
5073
5074 Binder.restoreCallingIdentity(origId);
5075
5076 } else {
5077 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005078 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005079 resolveContentProvider(name,
5080 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005081 } catch (RemoteException ex) {
5082 }
5083 if (cpi == null) {
5084 return null;
5085 }
5086
Dianne Hackbornb424b632010-08-18 15:59:05 -07005087 String msg;
5088 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5089 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 }
5091
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005092 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5093 && !cpi.processName.equals("system")) {
5094 // If this content provider does not run in the system
5095 // process, and the system is not yet ready to run other
5096 // processes, then fail fast instead of hanging.
5097 throw new IllegalArgumentException(
5098 "Attempt to launch content provider before system ready");
5099 }
5100
Dianne Hackborn860755f2010-06-03 18:47:52 -07005101 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 final boolean firstClass = cpr == null;
5103 if (firstClass) {
5104 try {
5105 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005106 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005107 getApplicationInfo(
5108 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005109 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005111 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 + cpi.name);
5113 return null;
5114 }
5115 cpr = new ContentProviderRecord(cpi, ai);
5116 } catch (RemoteException ex) {
5117 // pm is in same process, this will never happen.
5118 }
5119 }
5120
5121 if (r != null && cpr.canRunHere(r)) {
5122 // If this is a multiprocess provider, then just return its
5123 // info and allow the caller to instantiate it. Only do
5124 // this if the provider is the same user as the caller's
5125 // process, or can run as root (so can be in any process).
5126 return cpr;
5127 }
5128
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005129 if (DEBUG_PROVIDER) {
5130 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005131 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005132 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005133 }
5134
5135 // This is single process, and our app is now connecting to it.
5136 // See if we are already in the process of launching this
5137 // provider.
5138 final int N = mLaunchingProviders.size();
5139 int i;
5140 for (i=0; i<N; i++) {
5141 if (mLaunchingProviders.get(i) == cpr) {
5142 break;
5143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005144 }
5145
5146 // If the provider is not already being launched, then get it
5147 // started.
5148 if (i >= N) {
5149 final long origId = Binder.clearCallingIdentity();
5150 ProcessRecord proc = startProcessLocked(cpi.processName,
5151 cpr.appInfo, false, 0, "content provider",
5152 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005153 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005155 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005156 + cpi.applicationInfo.packageName + "/"
5157 + cpi.applicationInfo.uid + " for provider "
5158 + name + ": process is bad");
5159 return null;
5160 }
5161 cpr.launchingApp = proc;
5162 mLaunchingProviders.add(cpr);
5163 Binder.restoreCallingIdentity(origId);
5164 }
5165
5166 // Make sure the provider is published (the same provider class
5167 // may be published under multiple names).
5168 if (firstClass) {
5169 mProvidersByClass.put(cpi.name, cpr);
5170 }
5171 mProvidersByName.put(name, cpr);
5172
5173 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005174 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005175 "Adding provider requested by "
5176 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005177 + cpr.info.processName);
5178 Integer cnt = r.conProviders.get(cpr);
5179 if (cnt == null) {
5180 r.conProviders.put(cpr, new Integer(1));
5181 } else {
5182 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005184 cpr.clients.add(r);
5185 } else {
5186 cpr.externals++;
5187 }
5188 }
5189 }
5190
5191 // Wait for the provider to be published...
5192 synchronized (cpr) {
5193 while (cpr.provider == null) {
5194 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005195 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005196 + cpi.applicationInfo.packageName + "/"
5197 + cpi.applicationInfo.uid + " for provider "
5198 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005199 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 cpi.applicationInfo.packageName,
5201 cpi.applicationInfo.uid, name);
5202 return null;
5203 }
5204 try {
5205 cpr.wait();
5206 } catch (InterruptedException ex) {
5207 }
5208 }
5209 }
5210 return cpr;
5211 }
5212
5213 public final ContentProviderHolder getContentProvider(
5214 IApplicationThread caller, String name) {
5215 if (caller == null) {
5216 String msg = "null IApplicationThread when getting content provider "
5217 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005218 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005219 throw new SecurityException(msg);
5220 }
5221
5222 return getContentProviderImpl(caller, name);
5223 }
5224
5225 private ContentProviderHolder getContentProviderExternal(String name) {
5226 return getContentProviderImpl(null, name);
5227 }
5228
5229 /**
5230 * Drop a content provider from a ProcessRecord's bookkeeping
5231 * @param cpr
5232 */
5233 public void removeContentProvider(IApplicationThread caller, String name) {
5234 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005235 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005237 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005238 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005239 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 return;
5241 }
5242 final ProcessRecord r = getRecordForAppLocked(caller);
5243 if (r == null) {
5244 throw new SecurityException(
5245 "Unable to find app for caller " + caller +
5246 " when removing content provider " + name);
5247 }
5248 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005249 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005250 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005251 + r.info.processName + " from process "
5252 + localCpr.appInfo.processName);
5253 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005255 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005256 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 return;
5258 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005259 Integer cnt = r.conProviders.get(localCpr);
5260 if (cnt == null || cnt.intValue() <= 1) {
5261 localCpr.clients.remove(r);
5262 r.conProviders.remove(localCpr);
5263 } else {
5264 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 }
5267 updateOomAdjLocked();
5268 }
5269 }
5270
5271 private void removeContentProviderExternal(String name) {
5272 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005273 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 if(cpr == null) {
5275 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005276 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005277 return;
5278 }
5279
5280 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005281 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 localCpr.externals--;
5283 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005284 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005285 }
5286 updateOomAdjLocked();
5287 }
5288 }
5289
5290 public final void publishContentProviders(IApplicationThread caller,
5291 List<ContentProviderHolder> providers) {
5292 if (providers == null) {
5293 return;
5294 }
5295
5296 synchronized(this) {
5297 final ProcessRecord r = getRecordForAppLocked(caller);
5298 if (r == null) {
5299 throw new SecurityException(
5300 "Unable to find app for caller " + caller
5301 + " (pid=" + Binder.getCallingPid()
5302 + ") when publishing content providers");
5303 }
5304
5305 final long origId = Binder.clearCallingIdentity();
5306
5307 final int N = providers.size();
5308 for (int i=0; i<N; i++) {
5309 ContentProviderHolder src = providers.get(i);
5310 if (src == null || src.info == null || src.provider == null) {
5311 continue;
5312 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005313 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 if (dst != null) {
5315 mProvidersByClass.put(dst.info.name, dst);
5316 String names[] = dst.info.authority.split(";");
5317 for (int j = 0; j < names.length; j++) {
5318 mProvidersByName.put(names[j], dst);
5319 }
5320
5321 int NL = mLaunchingProviders.size();
5322 int j;
5323 for (j=0; j<NL; j++) {
5324 if (mLaunchingProviders.get(j) == dst) {
5325 mLaunchingProviders.remove(j);
5326 j--;
5327 NL--;
5328 }
5329 }
5330 synchronized (dst) {
5331 dst.provider = src.provider;
5332 dst.app = r;
5333 dst.notifyAll();
5334 }
5335 updateOomAdjLocked(r);
5336 }
5337 }
5338
5339 Binder.restoreCallingIdentity(origId);
5340 }
5341 }
5342
5343 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005344 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005345 synchronized (mSelf) {
5346 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5347 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005348 if (providers != null) {
5349 for (int i=providers.size()-1; i>=0; i--) {
5350 ProviderInfo pi = (ProviderInfo)providers.get(i);
5351 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5352 Slog.w(TAG, "Not installing system proc provider " + pi.name
5353 + ": not system .apk");
5354 providers.remove(i);
5355 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005356 }
5357 }
5358 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005359 if (providers != null) {
5360 mSystemThread.installSystemProviders(providers);
5361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362 }
5363
5364 // =========================================================
5365 // GLOBAL MANAGEMENT
5366 // =========================================================
5367
5368 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5369 ApplicationInfo info, String customProcess) {
5370 String proc = customProcess != null ? customProcess : info.processName;
5371 BatteryStatsImpl.Uid.Proc ps = null;
5372 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5373 synchronized (stats) {
5374 ps = stats.getProcessStatsLocked(info.uid, proc);
5375 }
5376 return new ProcessRecord(ps, thread, info, proc);
5377 }
5378
5379 final ProcessRecord addAppLocked(ApplicationInfo info) {
5380 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5381
5382 if (app == null) {
5383 app = newProcessRecordLocked(null, info, null);
5384 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005385 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 }
5387
5388 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5389 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5390 app.persistent = true;
5391 app.maxAdj = CORE_SERVER_ADJ;
5392 }
5393 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5394 mPersistentStartingProcesses.add(app);
5395 startProcessLocked(app, "added application", app.processName);
5396 }
5397
5398 return app;
5399 }
5400
5401 public void unhandledBack() {
5402 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5403 "unhandledBack()");
5404
5405 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005406 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005407 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 TAG, "Performing unhandledBack(): stack size = " + count);
5409 if (count > 1) {
5410 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005411 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005412 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5413 Binder.restoreCallingIdentity(origId);
5414 }
5415 }
5416 }
5417
5418 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5419 String name = uri.getAuthority();
5420 ContentProviderHolder cph = getContentProviderExternal(name);
5421 ParcelFileDescriptor pfd = null;
5422 if (cph != null) {
5423 // We record the binder invoker's uid in thread-local storage before
5424 // going to the content provider to open the file. Later, in the code
5425 // that handles all permissions checks, we look for this uid and use
5426 // that rather than the Activity Manager's own uid. The effect is that
5427 // we do the check against the caller's permissions even though it looks
5428 // to the content provider like the Activity Manager itself is making
5429 // the request.
5430 sCallerIdentity.set(new Identity(
5431 Binder.getCallingPid(), Binder.getCallingUid()));
5432 try {
5433 pfd = cph.provider.openFile(uri, "r");
5434 } catch (FileNotFoundException e) {
5435 // do nothing; pfd will be returned null
5436 } finally {
5437 // Ensure that whatever happens, we clean up the identity state
5438 sCallerIdentity.remove();
5439 }
5440
5441 // We've got the fd now, so we're done with the provider.
5442 removeContentProviderExternal(name);
5443 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005444 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445 }
5446 return pfd;
5447 }
5448
5449 public void goingToSleep() {
5450 synchronized(this) {
5451 mSleeping = true;
5452 mWindowManager.setEventDispatching(false);
5453
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005454 if (mMainStack.mResumedActivity != null) {
5455 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005456 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005457 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005458 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005459
5460 // Initialize the wake times of all processes.
5461 checkExcessiveWakeLocksLocked(false);
5462 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5463 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5464 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005465 }
5466 }
5467
Dianne Hackborn55280a92009-05-07 15:53:46 -07005468 public boolean shutdown(int timeout) {
5469 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5470 != PackageManager.PERMISSION_GRANTED) {
5471 throw new SecurityException("Requires permission "
5472 + android.Manifest.permission.SHUTDOWN);
5473 }
5474
5475 boolean timedout = false;
5476
5477 synchronized(this) {
5478 mShuttingDown = true;
5479 mWindowManager.setEventDispatching(false);
5480
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005481 if (mMainStack.mResumedActivity != null) {
5482 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005483 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005484 while (mMainStack.mResumedActivity != null
5485 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005486 long delay = endTime - System.currentTimeMillis();
5487 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005488 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005489 timedout = true;
5490 break;
5491 }
5492 try {
5493 this.wait();
5494 } catch (InterruptedException e) {
5495 }
5496 }
5497 }
5498 }
5499
5500 mUsageStatsService.shutdown();
5501 mBatteryStatsService.shutdown();
5502
5503 return timedout;
5504 }
5505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005506 public void wakingUp() {
5507 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005508 if (mMainStack.mGoingToSleep.isHeld()) {
5509 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 }
5511 mWindowManager.setEventDispatching(true);
5512 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005513 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005514 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005515 }
5516 }
5517
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005518 public void stopAppSwitches() {
5519 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5520 != PackageManager.PERMISSION_GRANTED) {
5521 throw new SecurityException("Requires permission "
5522 + android.Manifest.permission.STOP_APP_SWITCHES);
5523 }
5524
5525 synchronized(this) {
5526 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5527 + APP_SWITCH_DELAY_TIME;
5528 mDidAppSwitch = false;
5529 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5530 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5531 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5532 }
5533 }
5534
5535 public void resumeAppSwitches() {
5536 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5537 != PackageManager.PERMISSION_GRANTED) {
5538 throw new SecurityException("Requires permission "
5539 + android.Manifest.permission.STOP_APP_SWITCHES);
5540 }
5541
5542 synchronized(this) {
5543 // Note that we don't execute any pending app switches... we will
5544 // let those wait until either the timeout, or the next start
5545 // activity request.
5546 mAppSwitchesAllowedTime = 0;
5547 }
5548 }
5549
5550 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5551 String name) {
5552 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5553 return true;
5554 }
5555
5556 final int perm = checkComponentPermission(
5557 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5558 callingUid, -1);
5559 if (perm == PackageManager.PERMISSION_GRANTED) {
5560 return true;
5561 }
5562
Joe Onorato8a9b2202010-02-26 18:56:32 -08005563 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005564 return false;
5565 }
5566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 public void setDebugApp(String packageName, boolean waitForDebugger,
5568 boolean persistent) {
5569 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5570 "setDebugApp()");
5571
5572 // Note that this is not really thread safe if there are multiple
5573 // callers into it at the same time, but that's not a situation we
5574 // care about.
5575 if (persistent) {
5576 final ContentResolver resolver = mContext.getContentResolver();
5577 Settings.System.putString(
5578 resolver, Settings.System.DEBUG_APP,
5579 packageName);
5580 Settings.System.putInt(
5581 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5582 waitForDebugger ? 1 : 0);
5583 }
5584
5585 synchronized (this) {
5586 if (!persistent) {
5587 mOrigDebugApp = mDebugApp;
5588 mOrigWaitForDebugger = mWaitForDebugger;
5589 }
5590 mDebugApp = packageName;
5591 mWaitForDebugger = waitForDebugger;
5592 mDebugTransient = !persistent;
5593 if (packageName != null) {
5594 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005595 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005596 Binder.restoreCallingIdentity(origId);
5597 }
5598 }
5599 }
5600
5601 public void setAlwaysFinish(boolean enabled) {
5602 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5603 "setAlwaysFinish()");
5604
5605 Settings.System.putInt(
5606 mContext.getContentResolver(),
5607 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5608
5609 synchronized (this) {
5610 mAlwaysFinishActivities = enabled;
5611 }
5612 }
5613
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005614 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005616 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005618 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005619 }
5620 }
5621
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005622 public boolean isUserAMonkey() {
5623 // For now the fact that there is a controller implies
5624 // we have a monkey.
5625 synchronized (this) {
5626 return mController != null;
5627 }
5628 }
5629
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005630 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005631 synchronized (this) {
5632 mWatchers.register(watcher);
5633 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005634 }
5635
5636 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005637 synchronized (this) {
5638 mWatchers.unregister(watcher);
5639 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005640 }
5641
Daniel Sandler69a48172010-06-23 16:29:36 -04005642 public void setImmersive(IBinder token, boolean immersive) {
5643 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005644 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005645 if (index < 0) {
5646 throw new IllegalArgumentException();
5647 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005648 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005649 r.immersive = immersive;
5650 }
5651 }
5652
5653 public boolean isImmersive(IBinder token) {
5654 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005655 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005656 if (index < 0) {
5657 throw new IllegalArgumentException();
5658 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005659 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005660 return r.immersive;
5661 }
5662 }
5663
5664 public boolean isTopActivityImmersive() {
5665 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005666 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005667 return (r != null) ? r.immersive : false;
5668 }
5669 }
5670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 public final void enterSafeMode() {
5672 synchronized(this) {
5673 // It only makes sense to do this before the system is ready
5674 // and started launching other packages.
5675 if (!mSystemReady) {
5676 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005677 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 } catch (RemoteException e) {
5679 }
5680
5681 View v = LayoutInflater.from(mContext).inflate(
5682 com.android.internal.R.layout.safe_mode, null);
5683 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5684 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5685 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5686 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5687 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5688 lp.format = v.getBackground().getOpacity();
5689 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5690 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5691 ((WindowManager)mContext.getSystemService(
5692 Context.WINDOW_SERVICE)).addView(v, lp);
5693 }
5694 }
5695 }
5696
5697 public void noteWakeupAlarm(IIntentSender sender) {
5698 if (!(sender instanceof PendingIntentRecord)) {
5699 return;
5700 }
5701 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5702 synchronized (stats) {
5703 if (mBatteryStatsService.isOnBattery()) {
5704 mBatteryStatsService.enforceCallingPermission();
5705 PendingIntentRecord rec = (PendingIntentRecord)sender;
5706 int MY_UID = Binder.getCallingUid();
5707 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5708 BatteryStatsImpl.Uid.Pkg pkg =
5709 stats.getPackageStatsLocked(uid, rec.key.packageName);
5710 pkg.incWakeupsLocked();
5711 }
5712 }
5713 }
5714
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005715 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005716 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005717 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005719 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 // XXX Note: don't acquire main activity lock here, because the window
5721 // manager calls in with its locks held.
5722
5723 boolean killed = false;
5724 synchronized (mPidsSelfLocked) {
5725 int[] types = new int[pids.length];
5726 int worstType = 0;
5727 for (int i=0; i<pids.length; i++) {
5728 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5729 if (proc != null) {
5730 int type = proc.setAdj;
5731 types[i] = type;
5732 if (type > worstType) {
5733 worstType = type;
5734 }
5735 }
5736 }
5737
5738 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5739 // then constrain it so we will kill all hidden procs.
5740 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5741 worstType = HIDDEN_APP_MIN_ADJ;
5742 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005743 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 for (int i=0; i<pids.length; i++) {
5745 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5746 if (proc == null) {
5747 continue;
5748 }
5749 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005750 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005751 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005752 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5753 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005755 proc.killedBackground = true;
5756 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005757 }
5758 }
5759 }
5760 return killed;
5761 }
5762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005763 public final void startRunning(String pkg, String cls, String action,
5764 String data) {
5765 synchronized(this) {
5766 if (mStartRunning) {
5767 return;
5768 }
5769 mStartRunning = true;
5770 mTopComponent = pkg != null && cls != null
5771 ? new ComponentName(pkg, cls) : null;
5772 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5773 mTopData = data;
5774 if (!mSystemReady) {
5775 return;
5776 }
5777 }
5778
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005779 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780 }
5781
5782 private void retrieveSettings() {
5783 final ContentResolver resolver = mContext.getContentResolver();
5784 String debugApp = Settings.System.getString(
5785 resolver, Settings.System.DEBUG_APP);
5786 boolean waitForDebugger = Settings.System.getInt(
5787 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5788 boolean alwaysFinishActivities = Settings.System.getInt(
5789 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5790
5791 Configuration configuration = new Configuration();
5792 Settings.System.getConfiguration(resolver, configuration);
5793
5794 synchronized (this) {
5795 mDebugApp = mOrigDebugApp = debugApp;
5796 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5797 mAlwaysFinishActivities = alwaysFinishActivities;
5798 // This happens before any activities are started, so we can
5799 // change mConfiguration in-place.
5800 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005801 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005802 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005803 }
5804 }
5805
5806 public boolean testIsSystemReady() {
5807 // no need to synchronize(this) just to read & return the value
5808 return mSystemReady;
5809 }
5810
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005811 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005812 // In the simulator, startRunning will never have been called, which
5813 // normally sets a few crucial variables. Do it here instead.
5814 if (!Process.supportsProcesses()) {
5815 mStartRunning = true;
5816 mTopAction = Intent.ACTION_MAIN;
5817 }
5818
5819 synchronized(this) {
5820 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005821 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 return;
5823 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005824
5825 // Check to see if there are any update receivers to run.
5826 if (!mDidUpdate) {
5827 if (mWaitingUpdate) {
5828 return;
5829 }
5830 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5831 List<ResolveInfo> ris = null;
5832 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005833 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005834 intent, null, 0);
5835 } catch (RemoteException e) {
5836 }
5837 if (ris != null) {
5838 for (int i=ris.size()-1; i>=0; i--) {
5839 if ((ris.get(i).activityInfo.applicationInfo.flags
5840 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5841 ris.remove(i);
5842 }
5843 }
5844 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5845 for (int i=0; i<ris.size(); i++) {
5846 ActivityInfo ai = ris.get(i).activityInfo;
5847 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5848 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005849 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005850 finisher = new IIntentReceiver.Stub() {
5851 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005852 String data, Bundle extras, boolean ordered,
5853 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005854 throws RemoteException {
5855 synchronized (ActivityManagerService.this) {
5856 mDidUpdate = true;
5857 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005858 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005859 }
5860 };
5861 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005862 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005863 broadcastIntentLocked(null, null, intent, null, finisher,
5864 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005865 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005866 mWaitingUpdate = true;
5867 }
5868 }
5869 }
5870 if (mWaitingUpdate) {
5871 return;
5872 }
5873 mDidUpdate = true;
5874 }
5875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005876 mSystemReady = true;
5877 if (!mStartRunning) {
5878 return;
5879 }
5880 }
5881
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005882 ArrayList<ProcessRecord> procsToKill = null;
5883 synchronized(mPidsSelfLocked) {
5884 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5885 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5886 if (!isAllowedWhileBooting(proc.info)){
5887 if (procsToKill == null) {
5888 procsToKill = new ArrayList<ProcessRecord>();
5889 }
5890 procsToKill.add(proc);
5891 }
5892 }
5893 }
5894
5895 if (procsToKill != null) {
5896 synchronized(this) {
5897 for (int i=procsToKill.size()-1; i>=0; i--) {
5898 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005899 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005900 removeProcessLocked(proc, true);
5901 }
5902 }
5903 }
5904
Joe Onorato8a9b2202010-02-26 18:56:32 -08005905 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005906 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 SystemClock.uptimeMillis());
5908
5909 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005910 // Make sure we have no pre-ready processes sitting around.
5911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005912 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5913 ResolveInfo ri = mContext.getPackageManager()
5914 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005915 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 CharSequence errorMsg = null;
5917 if (ri != null) {
5918 ActivityInfo ai = ri.activityInfo;
5919 ApplicationInfo app = ai.applicationInfo;
5920 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5921 mTopAction = Intent.ACTION_FACTORY_TEST;
5922 mTopData = null;
5923 mTopComponent = new ComponentName(app.packageName,
5924 ai.name);
5925 } else {
5926 errorMsg = mContext.getResources().getText(
5927 com.android.internal.R.string.factorytest_not_system);
5928 }
5929 } else {
5930 errorMsg = mContext.getResources().getText(
5931 com.android.internal.R.string.factorytest_no_action);
5932 }
5933 if (errorMsg != null) {
5934 mTopAction = null;
5935 mTopData = null;
5936 mTopComponent = null;
5937 Message msg = Message.obtain();
5938 msg.what = SHOW_FACTORY_ERROR_MSG;
5939 msg.getData().putCharSequence("msg", errorMsg);
5940 mHandler.sendMessage(msg);
5941 }
5942 }
5943 }
5944
5945 retrieveSettings();
5946
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005947 if (goingCallback != null) goingCallback.run();
5948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005949 synchronized (this) {
5950 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5951 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005952 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005953 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005954 if (apps != null) {
5955 int N = apps.size();
5956 int i;
5957 for (i=0; i<N; i++) {
5958 ApplicationInfo info
5959 = (ApplicationInfo)apps.get(i);
5960 if (info != null &&
5961 !info.packageName.equals("android")) {
5962 addAppLocked(info);
5963 }
5964 }
5965 }
5966 } catch (RemoteException ex) {
5967 // pm is in same process, this will never happen.
5968 }
5969 }
5970
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005971 // Start up initial activity.
5972 mBooting = true;
5973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005974 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005975 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 Message msg = Message.obtain();
5977 msg.what = SHOW_UID_ERROR_MSG;
5978 mHandler.sendMessage(msg);
5979 }
5980 } catch (RemoteException e) {
5981 }
5982
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005983 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 }
5985 }
5986
Dan Egnorb7f03672009-12-09 16:22:32 -08005987 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005988 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005990 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005991 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005992 startAppProblemLocked(app);
5993 app.stopFreezingAllLocked();
5994 return handleAppCrashLocked(app);
5995 }
5996
Dan Egnorb7f03672009-12-09 16:22:32 -08005997 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005998 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005999 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006000 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006001 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6002 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 startAppProblemLocked(app);
6004 app.stopFreezingAllLocked();
6005 }
6006
6007 /**
6008 * Generate a process error record, suitable for attachment to a ProcessRecord.
6009 *
6010 * @param app The ProcessRecord in which the error occurred.
6011 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6012 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006013 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 * @param shortMsg Short message describing the crash.
6015 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006016 * @param stackTrace Full crash stack trace, may be null.
6017 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006018 * @return Returns a fully-formed AppErrorStateInfo record.
6019 */
6020 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006021 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006024 report.condition = condition;
6025 report.processName = app.processName;
6026 report.pid = app.pid;
6027 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006028 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006029 report.shortMsg = shortMsg;
6030 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006031 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032
6033 return report;
6034 }
6035
Dan Egnor42471dd2010-01-07 17:25:22 -08006036 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006037 synchronized (this) {
6038 app.crashing = false;
6039 app.crashingReport = null;
6040 app.notResponding = false;
6041 app.notRespondingReport = null;
6042 if (app.anrDialog == fromDialog) {
6043 app.anrDialog = null;
6044 }
6045 if (app.waitDialog == fromDialog) {
6046 app.waitDialog = null;
6047 }
6048 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006049 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006050 Slog.i(ActivityManagerService.TAG, "Killing "
6051 + app.processName + " (pid=" + app.pid + "): user's request");
6052 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6053 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006054 Process.killProcess(app.pid);
6055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 }
6057 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006058
Dan Egnorb7f03672009-12-09 16:22:32 -08006059 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006060 long now = SystemClock.uptimeMillis();
6061
6062 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6063 app.info.uid);
6064 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6065 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006066 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006068 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006069 app.info.processName, app.info.uid);
6070 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006071 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6072 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006073 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006074 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006075 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006076 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006077 }
6078 }
6079 if (!app.persistent) {
6080 // We don't want to start this process again until the user
6081 // explicitly does so... but for persistent process, we really
6082 // need to keep it running. If a persistent process is actually
6083 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006084 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006085 app.info.processName);
6086 mBadProcesses.put(app.info.processName, app.info.uid, now);
6087 app.bad = true;
6088 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6089 app.removed = true;
6090 removeProcessLocked(app, false);
6091 return false;
6092 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006093 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006094 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006095 if (r.app == app) {
6096 // If the top running activity is from this crashing
6097 // process, then terminate it to avoid getting in a loop.
6098 Slog.w(TAG, " Force finishing activity "
6099 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006100 int index = mMainStack.indexOfTokenLocked(r);
6101 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006102 Activity.RESULT_CANCELED, null, "crashed");
6103 // Also terminate an activities below it that aren't yet
6104 // stopped, to avoid a situation where one will get
6105 // re-start our crashing activity once it gets resumed again.
6106 index--;
6107 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006108 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006109 if (r.state == ActivityState.RESUMED
6110 || r.state == ActivityState.PAUSING
6111 || r.state == ActivityState.PAUSED) {
6112 if (!r.isHomeActivity) {
6113 Slog.w(TAG, " Force finishing activity "
6114 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006115 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006116 Activity.RESULT_CANCELED, null, "crashed");
6117 }
6118 }
6119 }
6120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006121 }
6122
6123 // Bump up the crash count of any services currently running in the proc.
6124 if (app.services.size() != 0) {
6125 // Any services running in the application need to be placed
6126 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006127 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006128 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006129 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006130 sr.crashCount++;
6131 }
6132 }
6133
6134 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6135 return true;
6136 }
6137
6138 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006139 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6140 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006141 skipCurrentReceiverLocked(app);
6142 }
6143
6144 void skipCurrentReceiverLocked(ProcessRecord app) {
6145 boolean reschedule = false;
6146 BroadcastRecord r = app.curReceiver;
6147 if (r != null) {
6148 // The current broadcast is waiting for this app's receiver
6149 // to be finished. Looks like that's not going to happen, so
6150 // let the broadcast continue.
6151 logBroadcastReceiverDiscard(r);
6152 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6153 r.resultExtras, r.resultAbort, true);
6154 reschedule = true;
6155 }
6156 r = mPendingBroadcast;
6157 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006158 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006159 "skip & discard pending app " + r);
6160 logBroadcastReceiverDiscard(r);
6161 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6162 r.resultExtras, r.resultAbort, true);
6163 reschedule = true;
6164 }
6165 if (reschedule) {
6166 scheduleBroadcastsLocked();
6167 }
6168 }
6169
Dan Egnor60d87622009-12-16 16:32:58 -08006170 /**
6171 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6172 * The application process will exit immediately after this call returns.
6173 * @param app object of the crashing app, null for the system server
6174 * @param crashInfo describing the exception
6175 */
6176 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6177 ProcessRecord r = findAppProcess(app);
6178
6179 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6180 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006181 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006182 crashInfo.exceptionClassName,
6183 crashInfo.exceptionMessage,
6184 crashInfo.throwFileName,
6185 crashInfo.throwLineNumber);
6186
Dan Egnor42471dd2010-01-07 17:25:22 -08006187 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006188
6189 crashApplication(r, crashInfo);
6190 }
6191
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006192 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006193 IBinder app,
6194 int violationMask,
6195 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006196 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006197
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006198 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006199 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006200 boolean logIt = true;
6201 synchronized (mAlreadyLoggedViolatedStacks) {
6202 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6203 logIt = false;
6204 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006205 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006206 // the relative pain numbers, without logging all
6207 // the stack traces repeatedly. We'd want to do
6208 // likewise in the client code, which also does
6209 // dup suppression, before the Binder call.
6210 } else {
6211 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6212 mAlreadyLoggedViolatedStacks.clear();
6213 }
6214 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6215 }
6216 }
6217 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006218 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006219 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006220 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006221
6222 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6223 AppErrorResult result = new AppErrorResult();
6224 synchronized (this) {
6225 final long origId = Binder.clearCallingIdentity();
6226
6227 Message msg = Message.obtain();
6228 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6229 HashMap<String, Object> data = new HashMap<String, Object>();
6230 data.put("result", result);
6231 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006232 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006233 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006234 msg.obj = data;
6235 mHandler.sendMessage(msg);
6236
6237 Binder.restoreCallingIdentity(origId);
6238 }
6239 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006240 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006241 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006242 }
6243
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006244 // Depending on the policy in effect, there could be a bunch of
6245 // these in quick succession so we try to batch these together to
6246 // minimize disk writes, number of dropbox entries, and maximize
6247 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006248 private void logStrictModeViolationToDropBox(
6249 ProcessRecord process,
6250 StrictMode.ViolationInfo info) {
6251 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006252 return;
6253 }
6254 final boolean isSystemApp = process == null ||
6255 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6256 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6257 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6258 final DropBoxManager dbox = (DropBoxManager)
6259 mContext.getSystemService(Context.DROPBOX_SERVICE);
6260
6261 // Exit early if the dropbox isn't configured to accept this report type.
6262 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6263
6264 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006265 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006266 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6267 synchronized (sb) {
6268 bufferWasEmpty = sb.length() == 0;
6269 appendDropBoxProcessHeaders(process, sb);
6270 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6271 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006272 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6273 if (info.violationNumThisLoop != 0) {
6274 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6275 }
6276 if (info != null && info.durationMillis != -1) {
6277 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006278 }
6279 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006280 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6281 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006282 }
6283 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006284
6285 // Only buffer up to ~64k. Various logging bits truncate
6286 // things at 128k.
6287 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006288 }
6289
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006290 // Flush immediately if the buffer's grown too large, or this
6291 // is a non-system app. Non-system apps are isolated with a
6292 // different tag & policy and not batched.
6293 //
6294 // Batching is useful during internal testing with
6295 // StrictMode settings turned up high. Without batching,
6296 // thousands of separate files could be created on boot.
6297 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006298 new Thread("Error dump: " + dropboxTag) {
6299 @Override
6300 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006301 String report;
6302 synchronized (sb) {
6303 report = sb.toString();
6304 sb.delete(0, sb.length());
6305 sb.trimToSize();
6306 }
6307 if (report.length() != 0) {
6308 dbox.addText(dropboxTag, report);
6309 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006310 }
6311 }.start();
6312 return;
6313 }
6314
6315 // System app batching:
6316 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006317 // An existing dropbox-writing thread is outstanding, so
6318 // we don't need to start it up. The existing thread will
6319 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006320 return;
6321 }
6322
6323 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6324 // (After this point, we shouldn't access AMS internal data structures.)
6325 new Thread("Error dump: " + dropboxTag) {
6326 @Override
6327 public void run() {
6328 // 5 second sleep to let stacks arrive and be batched together
6329 try {
6330 Thread.sleep(5000); // 5 seconds
6331 } catch (InterruptedException e) {}
6332
6333 String errorReport;
6334 synchronized (mStrictModeBuffer) {
6335 errorReport = mStrictModeBuffer.toString();
6336 if (errorReport.length() == 0) {
6337 return;
6338 }
6339 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6340 mStrictModeBuffer.trimToSize();
6341 }
6342 dbox.addText(dropboxTag, errorReport);
6343 }
6344 }.start();
6345 }
6346
Dan Egnor60d87622009-12-16 16:32:58 -08006347 /**
6348 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6349 * @param app object of the crashing app, null for the system server
6350 * @param tag reported by the caller
6351 * @param crashInfo describing the context of the error
6352 * @return true if the process should exit immediately (WTF is fatal)
6353 */
6354 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006355 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006356 ProcessRecord r = findAppProcess(app);
6357
6358 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6359 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006360 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006361 tag, crashInfo.exceptionMessage);
6362
Dan Egnor42471dd2010-01-07 17:25:22 -08006363 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006364
Doug Zongker43866e02010-01-07 12:09:54 -08006365 if (Settings.Secure.getInt(mContext.getContentResolver(),
6366 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006367 crashApplication(r, crashInfo);
6368 return true;
6369 } else {
6370 return false;
6371 }
6372 }
6373
6374 /**
6375 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6376 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6377 */
6378 private ProcessRecord findAppProcess(IBinder app) {
6379 if (app == null) {
6380 return null;
6381 }
6382
6383 synchronized (this) {
6384 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6385 final int NA = apps.size();
6386 for (int ia=0; ia<NA; ia++) {
6387 ProcessRecord p = apps.valueAt(ia);
6388 if (p.thread != null && p.thread.asBinder() == app) {
6389 return p;
6390 }
6391 }
6392 }
6393
Joe Onorato8a9b2202010-02-26 18:56:32 -08006394 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006395 return null;
6396 }
6397 }
6398
6399 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006400 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6401 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006402 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006403 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006404 if (process == null || process.pid == MY_PID) {
6405 sb.append("Process: system_server\n");
6406 } else {
6407 sb.append("Process: ").append(process.processName).append("\n");
6408 }
6409 if (process != null) {
6410 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006411 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006412 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6413 for (String pkg : process.pkgList) {
6414 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006415 try {
Dan Egnora455d192010-03-12 08:52:28 -08006416 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6417 if (pi != null) {
6418 sb.append(" v").append(pi.versionCode);
6419 if (pi.versionName != null) {
6420 sb.append(" (").append(pi.versionName).append(")");
6421 }
6422 }
6423 } catch (RemoteException e) {
6424 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006425 }
Dan Egnora455d192010-03-12 08:52:28 -08006426 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006427 }
Dan Egnora455d192010-03-12 08:52:28 -08006428 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006429 }
6430
6431 private static String processClass(ProcessRecord process) {
6432 if (process == null || process.pid == MY_PID) {
6433 return "system_server";
6434 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6435 return "system_app";
6436 } else {
6437 return "data_app";
6438 }
6439 }
6440
6441 /**
6442 * Write a description of an error (crash, WTF, ANR) to the drop box.
6443 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6444 * @param process which caused the error, null means the system server
6445 * @param activity which triggered the error, null if unknown
6446 * @param parent activity related to the error, null if unknown
6447 * @param subject line related to the error, null if absent
6448 * @param report in long form describing the error, null if absent
6449 * @param logFile to include in the report, null if none
6450 * @param crashInfo giving an application stack trace, null if absent
6451 */
6452 public void addErrorToDropBox(String eventType,
6453 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6454 final String report, final File logFile,
6455 final ApplicationErrorReport.CrashInfo crashInfo) {
6456 // NOTE -- this must never acquire the ActivityManagerService lock,
6457 // otherwise the watchdog may be prevented from resetting the system.
6458
6459 final String dropboxTag = processClass(process) + "_" + eventType;
6460 final DropBoxManager dbox = (DropBoxManager)
6461 mContext.getSystemService(Context.DROPBOX_SERVICE);
6462
6463 // Exit early if the dropbox isn't configured to accept this report type.
6464 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6465
6466 final StringBuilder sb = new StringBuilder(1024);
6467 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006468 if (activity != null) {
6469 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6470 }
6471 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6472 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6473 }
6474 if (parent != null && parent != activity) {
6475 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6476 }
6477 if (subject != null) {
6478 sb.append("Subject: ").append(subject).append("\n");
6479 }
6480 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6481 sb.append("\n");
6482
6483 // Do the rest in a worker thread to avoid blocking the caller on I/O
6484 // (After this point, we shouldn't access AMS internal data structures.)
6485 Thread worker = new Thread("Error dump: " + dropboxTag) {
6486 @Override
6487 public void run() {
6488 if (report != null) {
6489 sb.append(report);
6490 }
6491 if (logFile != null) {
6492 try {
6493 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6494 } catch (IOException e) {
6495 Slog.e(TAG, "Error reading " + logFile, e);
6496 }
6497 }
6498 if (crashInfo != null && crashInfo.stackTrace != null) {
6499 sb.append(crashInfo.stackTrace);
6500 }
6501
6502 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6503 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6504 if (lines > 0) {
6505 sb.append("\n");
6506
6507 // Merge several logcat streams, and take the last N lines
6508 InputStreamReader input = null;
6509 try {
6510 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6511 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6512 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6513
6514 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6515 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6516 input = new InputStreamReader(logcat.getInputStream());
6517
6518 int num;
6519 char[] buf = new char[8192];
6520 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6521 } catch (IOException e) {
6522 Slog.e(TAG, "Error running logcat", e);
6523 } finally {
6524 if (input != null) try { input.close(); } catch (IOException e) {}
6525 }
6526 }
6527
6528 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006529 }
Dan Egnora455d192010-03-12 08:52:28 -08006530 };
6531
6532 if (process == null || process.pid == MY_PID) {
6533 worker.run(); // We may be about to die -- need to run this synchronously
6534 } else {
6535 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006536 }
6537 }
6538
6539 /**
6540 * Bring up the "unexpected error" dialog box for a crashing app.
6541 * Deal with edge cases (intercepts from instrumented applications,
6542 * ActivityController, error intent receivers, that sort of thing).
6543 * @param r the application crashing
6544 * @param crashInfo describing the failure
6545 */
6546 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006547 long timeMillis = System.currentTimeMillis();
6548 String shortMsg = crashInfo.exceptionClassName;
6549 String longMsg = crashInfo.exceptionMessage;
6550 String stackTrace = crashInfo.stackTrace;
6551 if (shortMsg != null && longMsg != null) {
6552 longMsg = shortMsg + ": " + longMsg;
6553 } else if (shortMsg != null) {
6554 longMsg = shortMsg;
6555 }
6556
Dan Egnor60d87622009-12-16 16:32:58 -08006557 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006559 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006560 try {
6561 String name = r != null ? r.processName : null;
6562 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006563 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006564 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006565 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 + " at watcher's request");
6567 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006568 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006569 }
6570 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006571 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006572 }
6573 }
6574
6575 final long origId = Binder.clearCallingIdentity();
6576
6577 // If this process is running instrumentation, finish it.
6578 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006579 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006580 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006581 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6582 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 Bundle info = new Bundle();
6584 info.putString("shortMsg", shortMsg);
6585 info.putString("longMsg", longMsg);
6586 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6587 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006588 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006589 }
6590
Dan Egnor60d87622009-12-16 16:32:58 -08006591 // If we can't identify the process or it's already exceeded its crash quota,
6592 // quit right away without showing a crash dialog.
6593 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006594 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006595 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006596 }
6597
6598 Message msg = Message.obtain();
6599 msg.what = SHOW_ERROR_MSG;
6600 HashMap data = new HashMap();
6601 data.put("result", result);
6602 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006603 msg.obj = data;
6604 mHandler.sendMessage(msg);
6605
6606 Binder.restoreCallingIdentity(origId);
6607 }
6608
6609 int res = result.get();
6610
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006611 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006612 synchronized (this) {
6613 if (r != null) {
6614 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6615 SystemClock.uptimeMillis());
6616 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006617 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006618 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006619 }
6620 }
6621
6622 if (appErrorIntent != null) {
6623 try {
6624 mContext.startActivity(appErrorIntent);
6625 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006626 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006629 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006630
6631 Intent createAppErrorIntentLocked(ProcessRecord r,
6632 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6633 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006634 if (report == null) {
6635 return null;
6636 }
6637 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6638 result.setComponent(r.errorReportReceiver);
6639 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6640 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6641 return result;
6642 }
6643
Dan Egnorb7f03672009-12-09 16:22:32 -08006644 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6645 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006646 if (r.errorReportReceiver == null) {
6647 return null;
6648 }
6649
6650 if (!r.crashing && !r.notResponding) {
6651 return null;
6652 }
6653
Dan Egnorb7f03672009-12-09 16:22:32 -08006654 ApplicationErrorReport report = new ApplicationErrorReport();
6655 report.packageName = r.info.packageName;
6656 report.installerPackageName = r.errorReportReceiver.getPackageName();
6657 report.processName = r.processName;
6658 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006659 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006660
Dan Egnorb7f03672009-12-09 16:22:32 -08006661 if (r.crashing) {
6662 report.type = ApplicationErrorReport.TYPE_CRASH;
6663 report.crashInfo = crashInfo;
6664 } else if (r.notResponding) {
6665 report.type = ApplicationErrorReport.TYPE_ANR;
6666 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006667
Dan Egnorb7f03672009-12-09 16:22:32 -08006668 report.anrInfo.activity = r.notRespondingReport.tag;
6669 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6670 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006671 }
6672
Dan Egnorb7f03672009-12-09 16:22:32 -08006673 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006674 }
6675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006676 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6677 // assume our apps are happy - lazy create the list
6678 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6679
6680 synchronized (this) {
6681
6682 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006683 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6684 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006685 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6686 // This one's in trouble, so we'll generate a report for it
6687 // crashes are higher priority (in case there's a crash *and* an anr)
6688 ActivityManager.ProcessErrorStateInfo report = null;
6689 if (app.crashing) {
6690 report = app.crashingReport;
6691 } else if (app.notResponding) {
6692 report = app.notRespondingReport;
6693 }
6694
6695 if (report != null) {
6696 if (errList == null) {
6697 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6698 }
6699 errList.add(report);
6700 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006701 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 " crashing = " + app.crashing +
6703 " notResponding = " + app.notResponding);
6704 }
6705 }
6706 }
6707 }
6708
6709 return errList;
6710 }
6711
6712 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6713 // Lazy instantiation of list
6714 List<ActivityManager.RunningAppProcessInfo> runList = null;
6715 synchronized (this) {
6716 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006717 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6718 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006719 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6720 // Generate process state info for running application
6721 ActivityManager.RunningAppProcessInfo currApp =
6722 new ActivityManager.RunningAppProcessInfo(app.processName,
6723 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006724 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006725 if (mHeavyWeightProcess == app) {
6726 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006728 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006729 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6731 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6732 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006733 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6734 } else if (adj >= HOME_APP_ADJ) {
6735 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6736 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006737 } else if (adj >= SECONDARY_SERVER_ADJ) {
6738 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006739 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6740 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6741 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6742 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006743 } else if (adj >= VISIBLE_APP_ADJ) {
6744 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6745 } else {
6746 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6747 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006748 currApp.importanceReasonCode = app.adjTypeCode;
6749 if (app.adjSource instanceof ProcessRecord) {
6750 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006751 } else if (app.adjSource instanceof ActivityRecord) {
6752 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006753 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6754 }
6755 if (app.adjTarget instanceof ComponentName) {
6756 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6757 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006758 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006759 // + " lru=" + currApp.lru);
6760 if (runList == null) {
6761 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6762 }
6763 runList.add(currApp);
6764 }
6765 }
6766 }
6767 return runList;
6768 }
6769
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006770 public List<ApplicationInfo> getRunningExternalApplications() {
6771 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6772 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6773 if (runningApps != null && runningApps.size() > 0) {
6774 Set<String> extList = new HashSet<String>();
6775 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6776 if (app.pkgList != null) {
6777 for (String pkg : app.pkgList) {
6778 extList.add(pkg);
6779 }
6780 }
6781 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006782 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006783 for (String pkg : extList) {
6784 try {
6785 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6786 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6787 retList.add(info);
6788 }
6789 } catch (RemoteException e) {
6790 }
6791 }
6792 }
6793 return retList;
6794 }
6795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006796 @Override
6797 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006798 if (checkCallingPermission(android.Manifest.permission.DUMP)
6799 != PackageManager.PERMISSION_GRANTED) {
6800 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6801 + Binder.getCallingPid()
6802 + ", uid=" + Binder.getCallingUid()
6803 + " without permission "
6804 + android.Manifest.permission.DUMP);
6805 return;
6806 }
6807
6808 boolean dumpAll = false;
6809
6810 int opti = 0;
6811 while (opti < args.length) {
6812 String opt = args[opti];
6813 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6814 break;
6815 }
6816 opti++;
6817 if ("-a".equals(opt)) {
6818 dumpAll = true;
6819 } else if ("-h".equals(opt)) {
6820 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006821 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006822 pw.println(" cmd may be one of:");
6823 pw.println(" activities: activity stack state");
6824 pw.println(" broadcasts: broadcast state");
6825 pw.println(" intents: pending intent state");
6826 pw.println(" processes: process state");
6827 pw.println(" providers: content provider state");
6828 pw.println(" services: service state");
6829 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006830 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006831 } else {
6832 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006833 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006834 }
6835
6836 // Is the caller requesting to dump a particular piece of data?
6837 if (opti < args.length) {
6838 String cmd = args[opti];
6839 opti++;
6840 if ("activities".equals(cmd) || "a".equals(cmd)) {
6841 synchronized (this) {
6842 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006843 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006844 return;
6845 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6846 synchronized (this) {
6847 dumpBroadcastsLocked(fd, pw, args, opti, true);
6848 }
6849 return;
6850 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6851 synchronized (this) {
6852 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6853 }
6854 return;
6855 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6856 synchronized (this) {
6857 dumpProcessesLocked(fd, pw, args, opti, true);
6858 }
6859 return;
6860 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6861 synchronized (this) {
6862 dumpProvidersLocked(fd, pw, args, opti, true);
6863 }
6864 return;
6865 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006866 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006867 return;
6868 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6869 synchronized (this) {
6870 dumpServicesLocked(fd, pw, args, opti, true);
6871 }
6872 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006873 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006874 }
6875
6876 // No piece of data specified, dump everything.
6877 synchronized (this) {
6878 boolean needSep;
6879 if (dumpAll) {
6880 pw.println("Providers in Current Activity Manager State:");
6881 }
6882 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6883 if (needSep) {
6884 pw.println(" ");
6885 }
6886 if (dumpAll) {
6887 pw.println("-------------------------------------------------------------------------------");
6888 pw.println("Broadcasts in Current Activity Manager State:");
6889 }
6890 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6891 if (needSep) {
6892 pw.println(" ");
6893 }
6894 if (dumpAll) {
6895 pw.println("-------------------------------------------------------------------------------");
6896 pw.println("Services in Current Activity Manager State:");
6897 }
6898 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6899 if (needSep) {
6900 pw.println(" ");
6901 }
6902 if (dumpAll) {
6903 pw.println("-------------------------------------------------------------------------------");
6904 pw.println("PendingIntents in Current Activity Manager State:");
6905 }
6906 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6907 if (needSep) {
6908 pw.println(" ");
6909 }
6910 if (dumpAll) {
6911 pw.println("-------------------------------------------------------------------------------");
6912 pw.println("Activities in Current Activity Manager State:");
6913 }
6914 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6915 if (needSep) {
6916 pw.println(" ");
6917 }
6918 if (dumpAll) {
6919 pw.println("-------------------------------------------------------------------------------");
6920 pw.println("Processes in Current Activity Manager State:");
6921 }
6922 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6923 }
6924 }
6925
6926 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6927 int opti, boolean dumpAll, boolean needHeader) {
6928 if (needHeader) {
6929 pw.println(" Activity stack:");
6930 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006931 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006932 pw.println(" ");
6933 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006934 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6935 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006936 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006937 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006938 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006939 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006940 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006942 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006943 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006944 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006945 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006946 pw.println(" ");
6947 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006948 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006950
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006951 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006952 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
6953 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006954 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006955 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006956
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006957 if (dumpAll && mRecentTasks.size() > 0) {
6958 pw.println(" ");
6959 pw.println("Recent tasks in Current Activity Manager State:");
6960
6961 final int N = mRecentTasks.size();
6962 for (int i=0; i<N; i++) {
6963 TaskRecord tr = mRecentTasks.get(i);
6964 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
6965 pw.println(tr);
6966 mRecentTasks.get(i).dump(pw, " ");
6967 }
6968 }
6969
6970 pw.println(" ");
6971 pw.println(" mCurTask: " + mCurTask);
6972
6973 return true;
6974 }
6975
6976 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6977 int opti, boolean dumpAll) {
6978 boolean needSep = false;
6979 int numPers = 0;
6980
6981 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006982 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
6983 final int NA = procs.size();
6984 for (int ia=0; ia<NA; ia++) {
6985 if (!needSep) {
6986 pw.println(" All known processes:");
6987 needSep = true;
6988 }
6989 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006990 pw.print(r.persistent ? " *PERS*" : " *APP*");
6991 pw.print(" UID "); pw.print(procs.keyAt(ia));
6992 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 r.dump(pw, " ");
6994 if (r.persistent) {
6995 numPers++;
6996 }
6997 }
6998 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006999 }
7000
7001 if (mLruProcesses.size() > 0) {
7002 if (needSep) pw.println(" ");
7003 needSep = true;
7004 pw.println(" Running processes (most recent first):");
7005 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007006 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007007 needSep = true;
7008 }
7009
7010 synchronized (mPidsSelfLocked) {
7011 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007012 if (needSep) pw.println(" ");
7013 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007014 pw.println(" PID mappings:");
7015 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7016 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7017 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007018 }
7019 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007020 }
7021
7022 if (mForegroundProcesses.size() > 0) {
7023 if (needSep) pw.println(" ");
7024 needSep = true;
7025 pw.println(" Foreground Processes:");
7026 for (int i=0; i<mForegroundProcesses.size(); i++) {
7027 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7028 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007030 }
7031
7032 if (mPersistentStartingProcesses.size() > 0) {
7033 if (needSep) pw.println(" ");
7034 needSep = true;
7035 pw.println(" Persisent processes that are starting:");
7036 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
7037 "Starting Norm", "Restarting PERS", false);
7038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007039
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007040 if (mStartingProcesses.size() > 0) {
7041 if (needSep) pw.println(" ");
7042 needSep = true;
7043 pw.println(" Processes that are starting:");
7044 dumpProcessList(pw, this, mStartingProcesses, " ",
7045 "Starting Norm", "Starting PERS", false);
7046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007047
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007048 if (mRemovedProcesses.size() > 0) {
7049 if (needSep) pw.println(" ");
7050 needSep = true;
7051 pw.println(" Processes that are being removed:");
7052 dumpProcessList(pw, this, mRemovedProcesses, " ",
7053 "Removed Norm", "Removed PERS", false);
7054 }
7055
7056 if (mProcessesOnHold.size() > 0) {
7057 if (needSep) pw.println(" ");
7058 needSep = true;
7059 pw.println(" Processes that are on old until the system is ready:");
7060 dumpProcessList(pw, this, mProcessesOnHold, " ",
7061 "OnHold Norm", "OnHold PERS", false);
7062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007063
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007064 if (mProcessesToGc.size() > 0) {
7065 if (needSep) pw.println(" ");
7066 needSep = true;
7067 pw.println(" Processes that are waiting to GC:");
7068 long now = SystemClock.uptimeMillis();
7069 for (int i=0; i<mProcessesToGc.size(); i++) {
7070 ProcessRecord proc = mProcessesToGc.get(i);
7071 pw.print(" Process "); pw.println(proc);
7072 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7073 pw.print(", last gced=");
7074 pw.print(now-proc.lastRequestedGc);
7075 pw.print(" ms ago, last lowMem=");
7076 pw.print(now-proc.lastLowMemory);
7077 pw.println(" ms ago");
7078
7079 }
7080 }
7081
7082 if (mProcessCrashTimes.getMap().size() > 0) {
7083 if (needSep) pw.println(" ");
7084 needSep = true;
7085 pw.println(" Time since processes crashed:");
7086 long now = SystemClock.uptimeMillis();
7087 for (Map.Entry<String, SparseArray<Long>> procs
7088 : mProcessCrashTimes.getMap().entrySet()) {
7089 SparseArray<Long> uids = procs.getValue();
7090 final int N = uids.size();
7091 for (int i=0; i<N; i++) {
7092 pw.print(" Process "); pw.print(procs.getKey());
7093 pw.print(" uid "); pw.print(uids.keyAt(i));
7094 pw.print(": last crashed ");
7095 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007096 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007097 }
7098 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007101 if (mBadProcesses.getMap().size() > 0) {
7102 if (needSep) pw.println(" ");
7103 needSep = true;
7104 pw.println(" Bad processes:");
7105 for (Map.Entry<String, SparseArray<Long>> procs
7106 : mBadProcesses.getMap().entrySet()) {
7107 SparseArray<Long> uids = procs.getValue();
7108 final int N = uids.size();
7109 for (int i=0; i<N; i++) {
7110 pw.print(" Bad process "); pw.print(procs.getKey());
7111 pw.print(" uid "); pw.print(uids.keyAt(i));
7112 pw.print(": crashed at time ");
7113 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 }
7115 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007118 pw.println(" ");
7119 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007120 if (mHeavyWeightProcess != null) {
7121 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7122 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007123 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007124 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007125 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7126 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7127 || mOrigWaitForDebugger) {
7128 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7129 + " mDebugTransient=" + mDebugTransient
7130 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7131 }
7132 if (mAlwaysFinishActivities || mController != null) {
7133 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7134 + " mController=" + mController);
7135 }
7136 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007138 pw.println(" mStartRunning=" + mStartRunning
7139 + " mSystemReady=" + mSystemReady
7140 + " mBooting=" + mBooting
7141 + " mBooted=" + mBooted
7142 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007143 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7144 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007145 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007146 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007147
7148 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149 }
7150
7151 /**
7152 * There are three ways to call this:
7153 * - no service specified: dump all the services
7154 * - a flattened component name that matched an existing service was specified as the
7155 * first arg: dump that one service
7156 * - the first arg isn't the flattened component name of an existing service:
7157 * dump all services whose component contains the first arg as a substring
7158 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007159 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7160 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 String[] newArgs;
7162 String componentNameString;
7163 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007164 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 componentNameString = null;
7166 newArgs = EMPTY_STRING_ARRAY;
7167 r = null;
7168 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007169 componentNameString = args[opti];
7170 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007171 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007172 synchronized (this) {
7173 r = componentName != null ? mServices.get(componentName) : null;
7174 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007175 newArgs = new String[args.length - opti];
7176 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007177 }
7178
7179 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007180 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007181 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007182 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7183 synchronized (this) {
7184 for (ServiceRecord r1 : mServices.values()) {
7185 if (componentNameString == null
7186 || r1.name.flattenToString().contains(componentNameString)) {
7187 services.add(r1);
7188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007189 }
7190 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007191 for (int i=0; i<services.size(); i++) {
7192 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 }
7195 }
7196
7197 /**
7198 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7199 * there is a thread associated with the service.
7200 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007201 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7202 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007203 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007204 if (dumpAll) {
7205 synchronized (this) {
7206 pw.print(" * "); pw.println(r);
7207 r.dump(pw, " ");
7208 }
7209 pw.println("");
7210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007211 if (r.app != null && r.app.thread != null) {
7212 try {
7213 // flush anything that is already in the PrintWriter since the thread is going
7214 // to write to the file descriptor directly
7215 pw.flush();
7216 r.app.thread.dumpService(fd, r, args);
7217 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007218 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219 } catch (RemoteException e) {
7220 pw.println("got a RemoteException while dumping the service");
7221 }
7222 }
7223 }
7224
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007225 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7226 int opti, boolean dumpAll) {
7227 boolean needSep = false;
7228
7229 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007230 if (mRegisteredReceivers.size() > 0) {
7231 pw.println(" ");
7232 pw.println(" Registered Receivers:");
7233 Iterator it = mRegisteredReceivers.values().iterator();
7234 while (it.hasNext()) {
7235 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007236 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007237 r.dump(pw, " ");
7238 }
7239 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241 pw.println(" ");
7242 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007243 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007244 needSep = true;
7245 }
7246
7247 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7248 || mPendingBroadcast != null) {
7249 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007251 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007253 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7254 pw.println(" Broadcast #" + i + ":");
7255 mParallelBroadcasts.get(i).dump(pw, " ");
7256 }
7257 if (mOrderedBroadcasts.size() > 0) {
7258 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007259 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007260 }
7261 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7262 pw.println(" Serialized Broadcast #" + i + ":");
7263 mOrderedBroadcasts.get(i).dump(pw, " ");
7264 }
7265 pw.println(" ");
7266 pw.println(" Pending broadcast:");
7267 if (mPendingBroadcast != null) {
7268 mPendingBroadcast.dump(pw, " ");
7269 } else {
7270 pw.println(" (null)");
7271 }
7272 needSep = true;
7273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007274
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007275 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007276 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007277 pw.println(" Historical broadcasts:");
7278 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7279 BroadcastRecord r = mBroadcastHistory[i];
7280 if (r == null) {
7281 break;
7282 }
7283 pw.println(" Historical Broadcast #" + i + ":");
7284 r.dump(pw, " ");
7285 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007286 needSep = true;
7287 }
7288
7289 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007290 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007291 pw.println(" Sticky broadcasts:");
7292 StringBuilder sb = new StringBuilder(128);
7293 for (Map.Entry<String, ArrayList<Intent>> ent
7294 : mStickyBroadcasts.entrySet()) {
7295 pw.print(" * Sticky action "); pw.print(ent.getKey());
7296 pw.println(":");
7297 ArrayList<Intent> intents = ent.getValue();
7298 final int N = intents.size();
7299 for (int i=0; i<N; i++) {
7300 sb.setLength(0);
7301 sb.append(" Intent: ");
7302 intents.get(i).toShortString(sb, true, false);
7303 pw.println(sb.toString());
7304 Bundle bundle = intents.get(i).getExtras();
7305 if (bundle != null) {
7306 pw.print(" ");
7307 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 }
7309 }
7310 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007311 needSep = true;
7312 }
7313
7314 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007316 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317 pw.println(" mHandler:");
7318 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007319 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007321
7322 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007323 }
7324
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007325 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7326 int opti, boolean dumpAll) {
7327 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007328
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007329 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007330 if (mServices.size() > 0) {
7331 pw.println(" Active services:");
7332 Iterator<ServiceRecord> it = mServices.values().iterator();
7333 while (it.hasNext()) {
7334 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007335 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 r.dump(pw, " ");
7337 }
7338 needSep = true;
7339 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007342 if (mPendingServices.size() > 0) {
7343 if (needSep) pw.println(" ");
7344 pw.println(" Pending services:");
7345 for (int i=0; i<mPendingServices.size(); i++) {
7346 ServiceRecord r = mPendingServices.get(i);
7347 pw.print(" * Pending "); pw.println(r);
7348 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007349 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007350 needSep = true;
7351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007353 if (mRestartingServices.size() > 0) {
7354 if (needSep) pw.println(" ");
7355 pw.println(" Restarting services:");
7356 for (int i=0; i<mRestartingServices.size(); i++) {
7357 ServiceRecord r = mRestartingServices.get(i);
7358 pw.print(" * Restarting "); pw.println(r);
7359 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007361 needSep = true;
7362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007363
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007364 if (mStoppingServices.size() > 0) {
7365 if (needSep) pw.println(" ");
7366 pw.println(" Stopping services:");
7367 for (int i=0; i<mStoppingServices.size(); i++) {
7368 ServiceRecord r = mStoppingServices.get(i);
7369 pw.print(" * Stopping "); pw.println(r);
7370 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007372 needSep = true;
7373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007374
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007375 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 if (mServiceConnections.size() > 0) {
7377 if (needSep) pw.println(" ");
7378 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007379 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 = mServiceConnections.values().iterator();
7381 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007382 ArrayList<ConnectionRecord> r = it.next();
7383 for (int i=0; i<r.size(); i++) {
7384 pw.print(" * "); pw.println(r.get(i));
7385 r.get(i).dump(pw, " ");
7386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007388 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389 }
7390 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007391
7392 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007393 }
7394
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007395 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7396 int opti, boolean dumpAll) {
7397 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007399 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400 if (mProvidersByClass.size() > 0) {
7401 if (needSep) pw.println(" ");
7402 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007403 Iterator<Map.Entry<String, ContentProviderRecord>> it
7404 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007405 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007406 Map.Entry<String, ContentProviderRecord> e = it.next();
7407 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007408 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409 r.dump(pw, " ");
7410 }
7411 needSep = true;
7412 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007413
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007414 if (mProvidersByName.size() > 0) {
7415 pw.println(" ");
7416 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007417 Iterator<Map.Entry<String, ContentProviderRecord>> it
7418 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007419 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007420 Map.Entry<String, ContentProviderRecord> e = it.next();
7421 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007422 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7423 pw.println(r);
7424 }
7425 needSep = true;
7426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007428
7429 if (mLaunchingProviders.size() > 0) {
7430 if (needSep) pw.println(" ");
7431 pw.println(" Launching content providers:");
7432 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7433 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7434 pw.println(mLaunchingProviders.get(i));
7435 }
7436 needSep = true;
7437 }
7438
7439 if (mGrantedUriPermissions.size() > 0) {
7440 pw.println();
7441 pw.println("Granted Uri Permissions:");
7442 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7443 int uid = mGrantedUriPermissions.keyAt(i);
7444 HashMap<Uri, UriPermission> perms
7445 = mGrantedUriPermissions.valueAt(i);
7446 pw.print(" * UID "); pw.print(uid);
7447 pw.println(" holds:");
7448 for (UriPermission perm : perms.values()) {
7449 pw.print(" "); pw.println(perm);
7450 perm.dump(pw, " ");
7451 }
7452 }
7453 needSep = true;
7454 }
7455
7456 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007457 }
7458
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007459 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7460 int opti, boolean dumpAll) {
7461 boolean needSep = false;
7462
7463 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007464 if (this.mIntentSenderRecords.size() > 0) {
7465 Iterator<WeakReference<PendingIntentRecord>> it
7466 = mIntentSenderRecords.values().iterator();
7467 while (it.hasNext()) {
7468 WeakReference<PendingIntentRecord> ref = it.next();
7469 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007470 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007472 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007473 rec.dump(pw, " ");
7474 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007475 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476 }
7477 }
7478 }
7479 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007480
7481 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007482 }
7483
7484 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007485 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007486 TaskRecord lastTask = null;
7487 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007488 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007489 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007490 if (lastTask != r.task) {
7491 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007492 pw.print(prefix);
7493 pw.print(full ? "* " : " ");
7494 pw.println(lastTask);
7495 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007496 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007498 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007499 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7500 pw.print(" #"); pw.print(i); pw.print(": ");
7501 pw.println(r);
7502 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007503 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007505 }
7506 }
7507
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007508 private static String buildOomTag(String prefix, String space, int val, int base) {
7509 if (val == base) {
7510 if (space == null) return prefix;
7511 return prefix + " ";
7512 }
7513 return prefix + "+" + Integer.toString(val-base);
7514 }
7515
7516 private static final int dumpProcessList(PrintWriter pw,
7517 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 String prefix, String normalLabel, String persistentLabel,
7519 boolean inclOomAdj) {
7520 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007521 final int N = list.size()-1;
7522 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 ProcessRecord r = (ProcessRecord)list.get(i);
7524 if (false) {
7525 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7526 + " #" + i + ":");
7527 r.dump(pw, prefix + " ");
7528 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007529 String oomAdj;
7530 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007531 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007532 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007533 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7534 } else if (r.setAdj >= HOME_APP_ADJ) {
7535 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7536 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7537 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7538 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7539 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007540 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7541 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7542 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7543 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007544 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7545 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7546 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7547 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007548 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007549 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007550 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007551 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007552 } else {
7553 oomAdj = Integer.toString(r.setAdj);
7554 }
7555 String schedGroup;
7556 switch (r.setSchedGroup) {
7557 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7558 schedGroup = "B";
7559 break;
7560 case Process.THREAD_GROUP_DEFAULT:
7561 schedGroup = "F";
7562 break;
7563 default:
7564 schedGroup = Integer.toString(r.setSchedGroup);
7565 break;
7566 }
7567 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007569 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007570 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007571 pw.print(prefix);
7572 pw.print(" ");
7573 if (r.adjTarget instanceof ComponentName) {
7574 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7575 } else if (r.adjTarget != null) {
7576 pw.print(r.adjTarget.toString());
7577 } else {
7578 pw.print("{null}");
7579 }
7580 pw.print("<=");
7581 if (r.adjSource instanceof ProcessRecord) {
7582 pw.print("Proc{");
7583 pw.print(((ProcessRecord)r.adjSource).toShortString());
7584 pw.println("}");
7585 } else if (r.adjSource != null) {
7586 pw.println(r.adjSource.toString());
7587 } else {
7588 pw.println("{null}");
7589 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 } else {
7592 pw.println(String.format("%s%s #%2d: %s",
7593 prefix, (r.persistent ? persistentLabel : normalLabel),
7594 i, r.toString()));
7595 }
7596 if (r.persistent) {
7597 numPers++;
7598 }
7599 }
7600 return numPers;
7601 }
7602
Dianne Hackborn472ad872010-04-07 17:31:48 -07007603 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007605 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 long uptime = SystemClock.uptimeMillis();
7607 long realtime = SystemClock.elapsedRealtime();
7608
7609 if (isCheckinRequest) {
7610 // short checkin version
7611 pw.println(uptime + "," + realtime);
7612 pw.flush();
7613 } else {
7614 pw.println("Applications Memory Usage (kB):");
7615 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7616 }
7617 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7618 ProcessRecord r = (ProcessRecord)list.get(i);
7619 if (r.thread != null) {
7620 if (!isCheckinRequest) {
7621 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7622 pw.flush();
7623 }
7624 try {
7625 r.thread.asBinder().dump(fd, args);
7626 } catch (RemoteException e) {
7627 if (!isCheckinRequest) {
7628 pw.println("Got RemoteException!");
7629 pw.flush();
7630 }
7631 }
7632 }
7633 }
7634 }
7635
7636 /**
7637 * Searches array of arguments for the specified string
7638 * @param args array of argument strings
7639 * @param value value to search for
7640 * @return true if the value is contained in the array
7641 */
7642 private static boolean scanArgs(String[] args, String value) {
7643 if (args != null) {
7644 for (String arg : args) {
7645 if (value.equals(arg)) {
7646 return true;
7647 }
7648 }
7649 }
7650 return false;
7651 }
7652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 private final void killServicesLocked(ProcessRecord app,
7654 boolean allowRestart) {
7655 // Report disconnected services.
7656 if (false) {
7657 // XXX we are letting the client link to the service for
7658 // death notifications.
7659 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007660 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007661 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007662 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007663 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007664 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 = r.connections.values().iterator();
7666 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007667 ArrayList<ConnectionRecord> cl = jt.next();
7668 for (int i=0; i<cl.size(); i++) {
7669 ConnectionRecord c = cl.get(i);
7670 if (c.binding.client != app) {
7671 try {
7672 //c.conn.connected(r.className, null);
7673 } catch (Exception e) {
7674 // todo: this should be asynchronous!
7675 Slog.w(TAG, "Exception thrown disconnected servce "
7676 + r.shortName
7677 + " from app " + app.processName, e);
7678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007679 }
7680 }
7681 }
7682 }
7683 }
7684 }
7685 }
7686
7687 // Clean up any connections this application has to other services.
7688 if (app.connections.size() > 0) {
7689 Iterator<ConnectionRecord> it = app.connections.iterator();
7690 while (it.hasNext()) {
7691 ConnectionRecord r = it.next();
7692 removeConnectionLocked(r, app, null);
7693 }
7694 }
7695 app.connections.clear();
7696
7697 if (app.services.size() != 0) {
7698 // Any services running in the application need to be placed
7699 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007700 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007702 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703 synchronized (sr.stats.getBatteryStats()) {
7704 sr.stats.stopLaunchedLocked();
7705 }
7706 sr.app = null;
7707 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007708 if (mStoppingServices.remove(sr)) {
7709 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
7710 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007711
7712 boolean hasClients = sr.bindings.size() > 0;
7713 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714 Iterator<IntentBindRecord> bindings
7715 = sr.bindings.values().iterator();
7716 while (bindings.hasNext()) {
7717 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007718 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719 + ": shouldUnbind=" + b.hasBound);
7720 b.binder = null;
7721 b.requested = b.received = b.hasBound = false;
7722 }
7723 }
7724
7725 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007726 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007727 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007728 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 sr.crashCount, sr.shortName, app.pid);
7730 bringDownServiceLocked(sr, true);
7731 } else if (!allowRestart) {
7732 bringDownServiceLocked(sr, true);
7733 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007734 boolean canceled = scheduleServiceRestartLocked(sr, true);
7735
7736 // Should the service remain running? Note that in the
7737 // extreme case of so many attempts to deliver a command
7738 // that it failed, that we also will stop it here.
7739 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7740 if (sr.pendingStarts.size() == 0) {
7741 sr.startRequested = false;
7742 if (!hasClients) {
7743 // Whoops, no reason to restart!
7744 bringDownServiceLocked(sr, true);
7745 }
7746 }
7747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748 }
7749 }
7750
7751 if (!allowRestart) {
7752 app.services.clear();
7753 }
7754 }
7755
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007756 // Make sure we have no more records on the stopping list.
7757 int i = mStoppingServices.size();
7758 while (i > 0) {
7759 i--;
7760 ServiceRecord sr = mStoppingServices.get(i);
7761 if (sr.app == app) {
7762 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007763 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007764 }
7765 }
7766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007767 app.executingServices.clear();
7768 }
7769
7770 private final void removeDyingProviderLocked(ProcessRecord proc,
7771 ContentProviderRecord cpr) {
7772 synchronized (cpr) {
7773 cpr.launchingApp = null;
7774 cpr.notifyAll();
7775 }
7776
7777 mProvidersByClass.remove(cpr.info.name);
7778 String names[] = cpr.info.authority.split(";");
7779 for (int j = 0; j < names.length; j++) {
7780 mProvidersByName.remove(names[j]);
7781 }
7782
7783 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7784 while (cit.hasNext()) {
7785 ProcessRecord capp = cit.next();
7786 if (!capp.persistent && capp.thread != null
7787 && capp.pid != 0
7788 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007789 Slog.i(TAG, "Kill " + capp.processName
7790 + " (pid " + capp.pid + "): provider " + cpr.info.name
7791 + " in dying process " + proc.processName);
7792 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7793 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 Process.killProcess(capp.pid);
7795 }
7796 }
7797
7798 mLaunchingProviders.remove(cpr);
7799 }
7800
7801 /**
7802 * Main code for cleaning up a process when it has gone away. This is
7803 * called both as a result of the process dying, or directly when stopping
7804 * a process when running in single process mode.
7805 */
7806 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7807 boolean restarting, int index) {
7808 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007809 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 }
7811
Dianne Hackborn36124872009-10-08 16:22:03 -07007812 mProcessesToGc.remove(app);
7813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814 // Dismiss any open dialogs.
7815 if (app.crashDialog != null) {
7816 app.crashDialog.dismiss();
7817 app.crashDialog = null;
7818 }
7819 if (app.anrDialog != null) {
7820 app.anrDialog.dismiss();
7821 app.anrDialog = null;
7822 }
7823 if (app.waitDialog != null) {
7824 app.waitDialog.dismiss();
7825 app.waitDialog = null;
7826 }
7827
7828 app.crashing = false;
7829 app.notResponding = false;
7830
7831 app.resetPackageList();
7832 app.thread = null;
7833 app.forcingToForeground = null;
7834 app.foregroundServices = false;
7835
7836 killServicesLocked(app, true);
7837
7838 boolean restart = false;
7839
7840 int NL = mLaunchingProviders.size();
7841
7842 // Remove published content providers.
7843 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007844 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007845 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007846 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007847 cpr.provider = null;
7848 cpr.app = null;
7849
7850 // See if someone is waiting for this provider... in which
7851 // case we don't remove it, but just let it restart.
7852 int i = 0;
7853 if (!app.bad) {
7854 for (; i<NL; i++) {
7855 if (mLaunchingProviders.get(i) == cpr) {
7856 restart = true;
7857 break;
7858 }
7859 }
7860 } else {
7861 i = NL;
7862 }
7863
7864 if (i >= NL) {
7865 removeDyingProviderLocked(app, cpr);
7866 NL = mLaunchingProviders.size();
7867 }
7868 }
7869 app.pubProviders.clear();
7870 }
7871
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007872 // Take care of any launching providers waiting for this process.
7873 if (checkAppInLaunchingProvidersLocked(app, false)) {
7874 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007875 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007877 // Unregister from connected content providers.
7878 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007879 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 while (it.hasNext()) {
7881 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7882 cpr.clients.remove(app);
7883 }
7884 app.conProviders.clear();
7885 }
7886
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007887 // At this point there may be remaining entries in mLaunchingProviders
7888 // where we were the only one waiting, so they are no longer of use.
7889 // Look for these and clean up if found.
7890 // XXX Commented out for now. Trying to figure out a way to reproduce
7891 // the actual situation to identify what is actually going on.
7892 if (false) {
7893 for (int i=0; i<NL; i++) {
7894 ContentProviderRecord cpr = (ContentProviderRecord)
7895 mLaunchingProviders.get(i);
7896 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7897 synchronized (cpr) {
7898 cpr.launchingApp = null;
7899 cpr.notifyAll();
7900 }
7901 }
7902 }
7903 }
7904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007905 skipCurrentReceiverLocked(app);
7906
7907 // Unregister any receivers.
7908 if (app.receivers.size() > 0) {
7909 Iterator<ReceiverList> it = app.receivers.iterator();
7910 while (it.hasNext()) {
7911 removeReceiverLocked(it.next());
7912 }
7913 app.receivers.clear();
7914 }
7915
Christopher Tate181fafa2009-05-14 11:12:14 -07007916 // If the app is undergoing backup, tell the backup manager about it
7917 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007918 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007919 try {
7920 IBackupManager bm = IBackupManager.Stub.asInterface(
7921 ServiceManager.getService(Context.BACKUP_SERVICE));
7922 bm.agentDisconnected(app.info.packageName);
7923 } catch (RemoteException e) {
7924 // can't happen; backup manager is local
7925 }
7926 }
7927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007928 // If the caller is restarting this app, then leave it in its
7929 // current lists and let the caller take care of it.
7930 if (restarting) {
7931 return;
7932 }
7933
7934 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007935 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 "Removing non-persistent process during cleanup: " + app);
7937 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007938 if (mHeavyWeightProcess == app) {
7939 mHeavyWeightProcess = null;
7940 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007942 } else if (!app.removed) {
7943 // This app is persistent, so we need to keep its record around.
7944 // If it is not already on the pending app list, add it there
7945 // and start a new process for it.
7946 app.thread = null;
7947 app.forcingToForeground = null;
7948 app.foregroundServices = false;
7949 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7950 mPersistentStartingProcesses.add(app);
7951 restart = true;
7952 }
7953 }
7954 mProcessesOnHold.remove(app);
7955
The Android Open Source Project4df24232009-03-05 14:34:35 -08007956 if (app == mHomeProcess) {
7957 mHomeProcess = null;
7958 }
7959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007960 if (restart) {
7961 // We have components that still need to be running in the
7962 // process, so re-launch it.
7963 mProcessNames.put(app.processName, app.info.uid, app);
7964 startProcessLocked(app, "restart", app.processName);
7965 } else if (app.pid > 0 && app.pid != MY_PID) {
7966 // Goodbye!
7967 synchronized (mPidsSelfLocked) {
7968 mPidsSelfLocked.remove(app.pid);
7969 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
7970 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007971 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007972 }
7973 }
7974
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007975 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
7976 // Look through the content providers we are waiting to have launched,
7977 // and if any run in this process then either schedule a restart of
7978 // the process or kill the client waiting for it if this process has
7979 // gone bad.
7980 int NL = mLaunchingProviders.size();
7981 boolean restart = false;
7982 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007983 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007984 if (cpr.launchingApp == app) {
7985 if (!alwaysBad && !app.bad) {
7986 restart = true;
7987 } else {
7988 removeDyingProviderLocked(app, cpr);
7989 NL = mLaunchingProviders.size();
7990 }
7991 }
7992 }
7993 return restart;
7994 }
7995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007996 // =========================================================
7997 // SERVICES
7998 // =========================================================
7999
8000 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8001 ActivityManager.RunningServiceInfo info =
8002 new ActivityManager.RunningServiceInfo();
8003 info.service = r.name;
8004 if (r.app != null) {
8005 info.pid = r.app.pid;
8006 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008007 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008008 info.process = r.processName;
8009 info.foreground = r.isForeground;
8010 info.activeSince = r.createTime;
8011 info.started = r.startRequested;
8012 info.clientCount = r.connections.size();
8013 info.crashCount = r.crashCount;
8014 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008015 if (r.isForeground) {
8016 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8017 }
8018 if (r.startRequested) {
8019 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8020 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008021 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008022 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8023 }
8024 if (r.app != null && r.app.persistent) {
8025 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8026 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008027
8028 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8029 for (int i=0; i<connl.size(); i++) {
8030 ConnectionRecord conn = connl.get(i);
8031 if (conn.clientLabel != 0) {
8032 info.clientPackage = conn.binding.client.info.packageName;
8033 info.clientLabel = conn.clientLabel;
8034 return info;
8035 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008036 }
8037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008038 return info;
8039 }
8040
8041 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8042 int flags) {
8043 synchronized (this) {
8044 ArrayList<ActivityManager.RunningServiceInfo> res
8045 = new ArrayList<ActivityManager.RunningServiceInfo>();
8046
8047 if (mServices.size() > 0) {
8048 Iterator<ServiceRecord> it = mServices.values().iterator();
8049 while (it.hasNext() && res.size() < maxNum) {
8050 res.add(makeRunningServiceInfoLocked(it.next()));
8051 }
8052 }
8053
8054 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8055 ServiceRecord r = mRestartingServices.get(i);
8056 ActivityManager.RunningServiceInfo info =
8057 makeRunningServiceInfoLocked(r);
8058 info.restarting = r.nextRestartTime;
8059 res.add(info);
8060 }
8061
8062 return res;
8063 }
8064 }
8065
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008066 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8067 synchronized (this) {
8068 ServiceRecord r = mServices.get(name);
8069 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008070 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8071 for (int i=0; i<conn.size(); i++) {
8072 if (conn.get(i).clientIntent != null) {
8073 return conn.get(i).clientIntent;
8074 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008075 }
8076 }
8077 }
8078 }
8079 return null;
8080 }
8081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008082 private final ServiceRecord findServiceLocked(ComponentName name,
8083 IBinder token) {
8084 ServiceRecord r = mServices.get(name);
8085 return r == token ? r : null;
8086 }
8087
8088 private final class ServiceLookupResult {
8089 final ServiceRecord record;
8090 final String permission;
8091
8092 ServiceLookupResult(ServiceRecord _record, String _permission) {
8093 record = _record;
8094 permission = _permission;
8095 }
8096 };
8097
8098 private ServiceLookupResult findServiceLocked(Intent service,
8099 String resolvedType) {
8100 ServiceRecord r = null;
8101 if (service.getComponent() != null) {
8102 r = mServices.get(service.getComponent());
8103 }
8104 if (r == null) {
8105 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8106 r = mServicesByIntent.get(filter);
8107 }
8108
8109 if (r == null) {
8110 try {
8111 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008112 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113 service, resolvedType, 0);
8114 ServiceInfo sInfo =
8115 rInfo != null ? rInfo.serviceInfo : null;
8116 if (sInfo == null) {
8117 return null;
8118 }
8119
8120 ComponentName name = new ComponentName(
8121 sInfo.applicationInfo.packageName, sInfo.name);
8122 r = mServices.get(name);
8123 } catch (RemoteException ex) {
8124 // pm is in same process, this will never happen.
8125 }
8126 }
8127 if (r != null) {
8128 int callingPid = Binder.getCallingPid();
8129 int callingUid = Binder.getCallingUid();
8130 if (checkComponentPermission(r.permission,
8131 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8132 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008133 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134 + " from pid=" + callingPid
8135 + ", uid=" + callingUid
8136 + " requires " + r.permission);
8137 return new ServiceLookupResult(null, r.permission);
8138 }
8139 return new ServiceLookupResult(r, null);
8140 }
8141 return null;
8142 }
8143
8144 private class ServiceRestarter implements Runnable {
8145 private ServiceRecord mService;
8146
8147 void setService(ServiceRecord service) {
8148 mService = service;
8149 }
8150
8151 public void run() {
8152 synchronized(ActivityManagerService.this) {
8153 performServiceRestartLocked(mService);
8154 }
8155 }
8156 }
8157
8158 private ServiceLookupResult retrieveServiceLocked(Intent service,
8159 String resolvedType, int callingPid, int callingUid) {
8160 ServiceRecord r = null;
8161 if (service.getComponent() != null) {
8162 r = mServices.get(service.getComponent());
8163 }
8164 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8165 r = mServicesByIntent.get(filter);
8166 if (r == null) {
8167 try {
8168 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008169 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008170 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008171 ServiceInfo sInfo =
8172 rInfo != null ? rInfo.serviceInfo : null;
8173 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008174 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 ": not found");
8176 return null;
8177 }
8178
8179 ComponentName name = new ComponentName(
8180 sInfo.applicationInfo.packageName, sInfo.name);
8181 r = mServices.get(name);
8182 if (r == null) {
8183 filter = new Intent.FilterComparison(service.cloneFilter());
8184 ServiceRestarter res = new ServiceRestarter();
8185 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8186 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8187 synchronized (stats) {
8188 ss = stats.getServiceStatsLocked(
8189 sInfo.applicationInfo.uid, sInfo.packageName,
8190 sInfo.name);
8191 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008192 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008193 res.setService(r);
8194 mServices.put(name, r);
8195 mServicesByIntent.put(filter, r);
8196
8197 // Make sure this component isn't in the pending list.
8198 int N = mPendingServices.size();
8199 for (int i=0; i<N; i++) {
8200 ServiceRecord pr = mPendingServices.get(i);
8201 if (pr.name.equals(name)) {
8202 mPendingServices.remove(i);
8203 i--;
8204 N--;
8205 }
8206 }
8207 }
8208 } catch (RemoteException ex) {
8209 // pm is in same process, this will never happen.
8210 }
8211 }
8212 if (r != null) {
8213 if (checkComponentPermission(r.permission,
8214 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8215 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008216 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 + " from pid=" + Binder.getCallingPid()
8218 + ", uid=" + Binder.getCallingUid()
8219 + " requires " + r.permission);
8220 return new ServiceLookupResult(null, r.permission);
8221 }
8222 return new ServiceLookupResult(r, null);
8223 }
8224 return null;
8225 }
8226
8227 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8228 long now = SystemClock.uptimeMillis();
8229 if (r.executeNesting == 0 && r.app != null) {
8230 if (r.app.executingServices.size() == 0) {
8231 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8232 msg.obj = r.app;
8233 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8234 }
8235 r.app.executingServices.add(r);
8236 }
8237 r.executeNesting++;
8238 r.executingStart = now;
8239 }
8240
8241 private final void sendServiceArgsLocked(ServiceRecord r,
8242 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008243 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008244 if (N == 0) {
8245 return;
8246 }
8247
Dianne Hackborn39792d22010-08-19 18:01:52 -07008248 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008250 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008251 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8252 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008253 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008254 // If somehow we got a dummy start at the front, then
8255 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008256 continue;
8257 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008258 si.deliveredTime = SystemClock.uptimeMillis();
8259 r.deliveredStarts.add(si);
8260 si.deliveryCount++;
8261 if (si.targetPermissionUid >= 0) {
8262 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
8263 r.packageName, si.intent, si);
8264 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008265 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 bumpServiceExecutingLocked(r);
8267 if (!oomAdjusted) {
8268 oomAdjusted = true;
8269 updateOomAdjLocked(r.app);
8270 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008271 int flags = 0;
8272 if (si.deliveryCount > 0) {
8273 flags |= Service.START_FLAG_RETRY;
8274 }
8275 if (si.doneExecutingCount > 0) {
8276 flags |= Service.START_FLAG_REDELIVERY;
8277 }
8278 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008279 } catch (RemoteException e) {
8280 // Remote process gone... we'll let the normal cleanup take
8281 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008282 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008283 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008285 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008286 break;
8287 }
8288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008289 }
8290
8291 private final boolean requestServiceBindingLocked(ServiceRecord r,
8292 IntentBindRecord i, boolean rebind) {
8293 if (r.app == null || r.app.thread == null) {
8294 // If service is not currently running, can't yet bind.
8295 return false;
8296 }
8297 if ((!i.requested || rebind) && i.apps.size() > 0) {
8298 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008299 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
8300 + " in " + i + ": shouldUnbind=" + i.hasBound);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008301 bumpServiceExecutingLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008302 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8303 if (!rebind) {
8304 i.requested = true;
8305 }
8306 i.hasBound = true;
8307 i.doRebind = false;
8308 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008309 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008310 return false;
8311 }
8312 }
8313 return true;
8314 }
8315
8316 private final void requestServiceBindingsLocked(ServiceRecord r) {
8317 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8318 while (bindings.hasNext()) {
8319 IntentBindRecord i = bindings.next();
8320 if (!requestServiceBindingLocked(r, i, false)) {
8321 break;
8322 }
8323 }
8324 }
8325
8326 private final void realStartServiceLocked(ServiceRecord r,
8327 ProcessRecord app) throws RemoteException {
8328 if (app.thread == null) {
8329 throw new RemoteException();
8330 }
8331
8332 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008333 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008334
8335 app.services.add(r);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008336 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008337 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008338 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339
8340 boolean created = false;
8341 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008342 mStringBuilder.setLength(0);
8343 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008344 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008346 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 synchronized (r.stats.getBatteryStats()) {
8348 r.stats.startLaunchedLocked();
8349 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008350 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008351 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008352 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008353 created = true;
8354 } finally {
8355 if (!created) {
8356 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008357 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008358 }
8359 }
8360
8361 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008362
8363 // If the service is in the started state, and there are no
8364 // pending arguments, then fake up one so its onStartCommand() will
8365 // be called.
8366 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8367 r.lastStartId++;
8368 if (r.lastStartId < 1) {
8369 r.lastStartId = 1;
8370 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008371 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008372 }
8373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008374 sendServiceArgsLocked(r, true);
8375 }
8376
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008377 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8378 boolean allowCancel) {
8379 boolean canceled = false;
8380
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008381 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008382 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008383 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008384
8385 // Any delivered but not yet finished starts should be put back
8386 // on the pending list.
8387 final int N = r.deliveredStarts.size();
8388 if (N > 0) {
8389 for (int i=N-1; i>=0; i--) {
8390 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008391 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008392 if (si.intent == null) {
8393 // We'll generate this again if needed.
8394 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8395 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8396 r.pendingStarts.add(0, si);
8397 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8398 dur *= 2;
8399 if (minDuration < dur) minDuration = dur;
8400 if (resetTime < dur) resetTime = dur;
8401 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008402 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008403 + r.name);
8404 canceled = true;
8405 }
8406 }
8407 r.deliveredStarts.clear();
8408 }
8409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410 r.totalRestartCount++;
8411 if (r.restartDelay == 0) {
8412 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008413 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008414 } else {
8415 // If it has been a "reasonably long time" since the service
8416 // was started, then reset our restart duration back to
8417 // the beginning, so we don't infinitely increase the duration
8418 // on a service that just occasionally gets killed (which is
8419 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008420 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008421 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008422 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008423 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008424 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008425 if (r.restartDelay < minDuration) {
8426 r.restartDelay = minDuration;
8427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 }
8429 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008430
8431 r.nextRestartTime = now + r.restartDelay;
8432
8433 // Make sure that we don't end up restarting a bunch of services
8434 // all at the same time.
8435 boolean repeat;
8436 do {
8437 repeat = false;
8438 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8439 ServiceRecord r2 = mRestartingServices.get(i);
8440 if (r2 != r && r.nextRestartTime
8441 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8442 && r.nextRestartTime
8443 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8444 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8445 r.restartDelay = r.nextRestartTime - now;
8446 repeat = true;
8447 break;
8448 }
8449 }
8450 } while (repeat);
8451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 if (!mRestartingServices.contains(r)) {
8453 mRestartingServices.add(r);
8454 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008455
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008456 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008458 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008459 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008460 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008461 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008462 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008463 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008464 r.shortName, r.restartDelay);
8465
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008466 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008467 }
8468
8469 final void performServiceRestartLocked(ServiceRecord r) {
8470 if (!mRestartingServices.contains(r)) {
8471 return;
8472 }
8473 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8474 }
8475
8476 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8477 if (r.restartDelay == 0) {
8478 return false;
8479 }
8480 r.resetRestartCounter();
8481 mRestartingServices.remove(r);
8482 mHandler.removeCallbacks(r.restarter);
8483 return true;
8484 }
8485
8486 private final boolean bringUpServiceLocked(ServiceRecord r,
8487 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008488 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008489 //r.dump(" ");
8490
Dianne Hackborn36124872009-10-08 16:22:03 -07008491 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 sendServiceArgsLocked(r, false);
8493 return true;
8494 }
8495
8496 if (!whileRestarting && r.restartDelay > 0) {
8497 // If waiting for a restart, then do nothing.
8498 return true;
8499 }
8500
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008501 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008503 // We are now bringing the service up, so no longer in the
8504 // restarting state.
8505 mRestartingServices.remove(r);
8506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008507 final String appName = r.processName;
8508 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8509 if (app != null && app.thread != null) {
8510 try {
8511 realStartServiceLocked(r, app);
8512 return true;
8513 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008514 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 }
8516
8517 // If a dead object exception was thrown -- fall through to
8518 // restart the application.
8519 }
8520
Dianne Hackborn36124872009-10-08 16:22:03 -07008521 // Not running -- get it started, and enqueue this service record
8522 // to be executed when the app comes up.
8523 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8524 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008525 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008526 + r.appInfo.packageName + "/"
8527 + r.appInfo.uid + " for service "
8528 + r.intent.getIntent() + ": process is bad");
8529 bringDownServiceLocked(r, true);
8530 return false;
8531 }
8532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008533 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008534 mPendingServices.add(r);
8535 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 return true;
8538 }
8539
8540 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008541 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 //r.dump(" ");
8543
8544 // Does it still need to run?
8545 if (!force && r.startRequested) {
8546 return;
8547 }
8548 if (r.connections.size() > 0) {
8549 if (!force) {
8550 // XXX should probably keep a count of the number of auto-create
8551 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008552 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008553 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008554 ArrayList<ConnectionRecord> cr = it.next();
8555 for (int i=0; i<cr.size(); i++) {
8556 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8557 return;
8558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008559 }
8560 }
8561 }
8562
8563 // Report to all of the connections that the service is no longer
8564 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008565 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008566 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008567 ArrayList<ConnectionRecord> c = it.next();
8568 for (int i=0; i<c.size(); i++) {
8569 try {
8570 c.get(i).conn.connected(r.name, null);
8571 } catch (Exception e) {
8572 Slog.w(TAG, "Failure disconnecting service " + r.name +
8573 " to connection " + c.get(i).conn.asBinder() +
8574 " (in " + c.get(i).binding.client.processName + ")", e);
8575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008576 }
8577 }
8578 }
8579
8580 // Tell the service that it has been unbound.
8581 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8582 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8583 while (it.hasNext()) {
8584 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008585 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 + ": hasBound=" + ibr.hasBound);
8587 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8588 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008589 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
8590 + " for " + ibr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008591 bumpServiceExecutingLocked(r);
8592 updateOomAdjLocked(r.app);
8593 ibr.hasBound = false;
8594 r.app.thread.scheduleUnbindService(r,
8595 ibr.intent.getIntent());
8596 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008597 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008598 + r.shortName, e);
8599 serviceDoneExecutingLocked(r, true);
8600 }
8601 }
8602 }
8603 }
8604
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008605 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008606 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 System.identityHashCode(r), r.shortName,
8608 (r.app != null) ? r.app.pid : -1);
8609
8610 mServices.remove(r.name);
8611 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008612 r.totalRestartCount = 0;
8613 unscheduleServiceRestartLocked(r);
8614
8615 // Also make sure it is not on the pending list.
8616 int N = mPendingServices.size();
8617 for (int i=0; i<N; i++) {
8618 if (mPendingServices.get(i) == r) {
8619 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008620 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008621 i--;
8622 N--;
8623 }
8624 }
8625
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008626 r.cancelNotification();
8627 r.isForeground = false;
8628 r.foregroundId = 0;
8629 r.foregroundNoti = null;
8630
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008631 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008632 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008633 r.pendingStarts.clear();
8634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008635 if (r.app != null) {
8636 synchronized (r.stats.getBatteryStats()) {
8637 r.stats.stopLaunchedLocked();
8638 }
8639 r.app.services.remove(r);
8640 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008641 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008642 if (DEBUG_SERVICE) {
8643 RuntimeException here = new RuntimeException();
8644 here.fillInStackTrace();
8645 Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
8646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647 bumpServiceExecutingLocked(r);
8648 mStoppingServices.add(r);
8649 updateOomAdjLocked(r.app);
8650 r.app.thread.scheduleStopService(r);
8651 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008652 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 + r.shortName, e);
8654 serviceDoneExecutingLocked(r, true);
8655 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008656 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008658 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008659 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 }
8661 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008662 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008663 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008664 }
8665 }
8666
8667 ComponentName startServiceLocked(IApplicationThread caller,
8668 Intent service, String resolvedType,
8669 int callingPid, int callingUid) {
8670 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008671 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 + " type=" + resolvedType + " args=" + service.getExtras());
8673
8674 if (caller != null) {
8675 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8676 if (callerApp == null) {
8677 throw new SecurityException(
8678 "Unable to find app for caller " + caller
8679 + " (pid=" + Binder.getCallingPid()
8680 + ") when starting service " + service);
8681 }
8682 }
8683
8684 ServiceLookupResult res =
8685 retrieveServiceLocked(service, resolvedType,
8686 callingPid, callingUid);
8687 if (res == null) {
8688 return null;
8689 }
8690 if (res.record == null) {
8691 return new ComponentName("!", res.permission != null
8692 ? res.permission : "private to package");
8693 }
8694 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07008695 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
8696 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008698 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008699 }
8700 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008701 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008702 r.lastStartId++;
8703 if (r.lastStartId < 1) {
8704 r.lastStartId = 1;
8705 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008706 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
8707 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008708 r.lastActivity = SystemClock.uptimeMillis();
8709 synchronized (r.stats.getBatteryStats()) {
8710 r.stats.startRunningLocked();
8711 }
8712 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8713 return new ComponentName("!", "Service process is bad");
8714 }
8715 return r.name;
8716 }
8717 }
8718
8719 public ComponentName startService(IApplicationThread caller, Intent service,
8720 String resolvedType) {
8721 // Refuse possible leaked file descriptors
8722 if (service != null && service.hasFileDescriptors() == true) {
8723 throw new IllegalArgumentException("File descriptors passed in Intent");
8724 }
8725
8726 synchronized(this) {
8727 final int callingPid = Binder.getCallingPid();
8728 final int callingUid = Binder.getCallingUid();
8729 final long origId = Binder.clearCallingIdentity();
8730 ComponentName res = startServiceLocked(caller, service,
8731 resolvedType, callingPid, callingUid);
8732 Binder.restoreCallingIdentity(origId);
8733 return res;
8734 }
8735 }
8736
8737 ComponentName startServiceInPackage(int uid,
8738 Intent service, String resolvedType) {
8739 synchronized(this) {
8740 final long origId = Binder.clearCallingIdentity();
8741 ComponentName res = startServiceLocked(null, service,
8742 resolvedType, -1, uid);
8743 Binder.restoreCallingIdentity(origId);
8744 return res;
8745 }
8746 }
8747
8748 public int stopService(IApplicationThread caller, Intent service,
8749 String resolvedType) {
8750 // Refuse possible leaked file descriptors
8751 if (service != null && service.hasFileDescriptors() == true) {
8752 throw new IllegalArgumentException("File descriptors passed in Intent");
8753 }
8754
8755 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008756 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 + " type=" + resolvedType);
8758
8759 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8760 if (caller != null && callerApp == null) {
8761 throw new SecurityException(
8762 "Unable to find app for caller " + caller
8763 + " (pid=" + Binder.getCallingPid()
8764 + ") when stopping service " + service);
8765 }
8766
8767 // If this service is active, make sure it is stopped.
8768 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8769 if (r != null) {
8770 if (r.record != null) {
8771 synchronized (r.record.stats.getBatteryStats()) {
8772 r.record.stats.stopRunningLocked();
8773 }
8774 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008775 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008776 final long origId = Binder.clearCallingIdentity();
8777 bringDownServiceLocked(r.record, false);
8778 Binder.restoreCallingIdentity(origId);
8779 return 1;
8780 }
8781 return -1;
8782 }
8783 }
8784
8785 return 0;
8786 }
8787
8788 public IBinder peekService(Intent service, String resolvedType) {
8789 // Refuse possible leaked file descriptors
8790 if (service != null && service.hasFileDescriptors() == true) {
8791 throw new IllegalArgumentException("File descriptors passed in Intent");
8792 }
8793
8794 IBinder ret = null;
8795
8796 synchronized(this) {
8797 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8798
8799 if (r != null) {
8800 // r.record is null if findServiceLocked() failed the caller permission check
8801 if (r.record == null) {
8802 throw new SecurityException(
8803 "Permission Denial: Accessing service " + r.record.name
8804 + " from pid=" + Binder.getCallingPid()
8805 + ", uid=" + Binder.getCallingUid()
8806 + " requires " + r.permission);
8807 }
8808 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8809 if (ib != null) {
8810 ret = ib.binder;
8811 }
8812 }
8813 }
8814
8815 return ret;
8816 }
8817
8818 public boolean stopServiceToken(ComponentName className, IBinder token,
8819 int startId) {
8820 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008821 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008822 + " " + token + " startId=" + startId);
8823 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008824 if (r != null) {
8825 if (startId >= 0) {
8826 // Asked to only stop if done with all work. Note that
8827 // to avoid leaks, we will take this as dropping all
8828 // start items up to and including this one.
8829 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8830 if (si != null) {
8831 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008832 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
8833 cur.removeUriPermissionsLocked();
8834 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008835 break;
8836 }
8837 }
8838 }
8839
8840 if (r.lastStartId != startId) {
8841 return false;
8842 }
8843
8844 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008845 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008846 + " is last, but have " + r.deliveredStarts.size()
8847 + " remaining args");
8848 }
8849 }
8850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008851 synchronized (r.stats.getBatteryStats()) {
8852 r.stats.stopRunningLocked();
8853 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008854 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008855 }
8856 final long origId = Binder.clearCallingIdentity();
8857 bringDownServiceLocked(r, false);
8858 Binder.restoreCallingIdentity(origId);
8859 return true;
8860 }
8861 }
8862 return false;
8863 }
8864
8865 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008866 int id, Notification notification, boolean removeNotification) {
8867 final long origId = Binder.clearCallingIdentity();
8868 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008869 synchronized(this) {
8870 ServiceRecord r = findServiceLocked(className, token);
8871 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008872 if (id != 0) {
8873 if (notification == null) {
8874 throw new IllegalArgumentException("null notification");
8875 }
8876 if (r.foregroundId != id) {
8877 r.cancelNotification();
8878 r.foregroundId = id;
8879 }
8880 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8881 r.foregroundNoti = notification;
8882 r.isForeground = true;
8883 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008884 if (r.app != null) {
8885 updateServiceForegroundLocked(r.app, true);
8886 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008887 } else {
8888 if (r.isForeground) {
8889 r.isForeground = false;
8890 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008891 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008892 updateServiceForegroundLocked(r.app, true);
8893 }
8894 }
8895 if (removeNotification) {
8896 r.cancelNotification();
8897 r.foregroundId = 0;
8898 r.foregroundNoti = null;
8899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008900 }
8901 }
8902 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008903 } finally {
8904 Binder.restoreCallingIdentity(origId);
8905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008906 }
8907
8908 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8909 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008910 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008911 if (sr.isForeground) {
8912 anyForeground = true;
8913 break;
8914 }
8915 }
8916 if (anyForeground != proc.foregroundServices) {
8917 proc.foregroundServices = anyForeground;
8918 if (oomAdj) {
8919 updateOomAdjLocked();
8920 }
8921 }
8922 }
8923
8924 public int bindService(IApplicationThread caller, IBinder token,
8925 Intent service, String resolvedType,
8926 IServiceConnection connection, int flags) {
8927 // Refuse possible leaked file descriptors
8928 if (service != null && service.hasFileDescriptors() == true) {
8929 throw new IllegalArgumentException("File descriptors passed in Intent");
8930 }
8931
8932 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008933 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008934 + " type=" + resolvedType + " conn=" + connection.asBinder()
8935 + " flags=0x" + Integer.toHexString(flags));
8936 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8937 if (callerApp == null) {
8938 throw new SecurityException(
8939 "Unable to find app for caller " + caller
8940 + " (pid=" + Binder.getCallingPid()
8941 + ") when binding service " + service);
8942 }
8943
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008944 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008945 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008946 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008947 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008948 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008949 return 0;
8950 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008951 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008952 }
8953
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008954 int clientLabel = 0;
8955 PendingIntent clientIntent = null;
8956
8957 if (callerApp.info.uid == Process.SYSTEM_UID) {
8958 // Hacky kind of thing -- allow system stuff to tell us
8959 // what they are, so we can report this elsewhere for
8960 // others to know why certain services are running.
8961 try {
8962 clientIntent = (PendingIntent)service.getParcelableExtra(
8963 Intent.EXTRA_CLIENT_INTENT);
8964 } catch (RuntimeException e) {
8965 }
8966 if (clientIntent != null) {
8967 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
8968 if (clientLabel != 0) {
8969 // There are no useful extras in the intent, trash them.
8970 // System code calling with this stuff just needs to know
8971 // this will happen.
8972 service = service.cloneFilter();
8973 }
8974 }
8975 }
8976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008977 ServiceLookupResult res =
8978 retrieveServiceLocked(service, resolvedType,
8979 Binder.getCallingPid(), Binder.getCallingUid());
8980 if (res == null) {
8981 return 0;
8982 }
8983 if (res.record == null) {
8984 return -1;
8985 }
8986 ServiceRecord s = res.record;
8987
8988 final long origId = Binder.clearCallingIdentity();
8989
8990 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008991 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008992 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008993 }
8994
8995 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
8996 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008997 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998
8999 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009000 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9001 if (clist == null) {
9002 clist = new ArrayList<ConnectionRecord>();
9003 s.connections.put(binder, clist);
9004 }
9005 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009006 b.connections.add(c);
9007 if (activity != null) {
9008 if (activity.connections == null) {
9009 activity.connections = new HashSet<ConnectionRecord>();
9010 }
9011 activity.connections.add(c);
9012 }
9013 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009014 clist = mServiceConnections.get(binder);
9015 if (clist == null) {
9016 clist = new ArrayList<ConnectionRecord>();
9017 mServiceConnections.put(binder, clist);
9018 }
9019 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009020
9021 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9022 s.lastActivity = SystemClock.uptimeMillis();
9023 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9024 return 0;
9025 }
9026 }
9027
9028 if (s.app != null) {
9029 // This could have made the service more important.
9030 updateOomAdjLocked(s.app);
9031 }
9032
Joe Onorato8a9b2202010-02-26 18:56:32 -08009033 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009034 + ": received=" + b.intent.received
9035 + " apps=" + b.intent.apps.size()
9036 + " doRebind=" + b.intent.doRebind);
9037
9038 if (s.app != null && b.intent.received) {
9039 // Service is already running, so we can immediately
9040 // publish the connection.
9041 try {
9042 c.conn.connected(s.name, b.intent.binder);
9043 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009044 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 + " to connection " + c.conn.asBinder()
9046 + " (in " + c.binding.client.processName + ")", e);
9047 }
9048
9049 // If this is the first app connected back to this binding,
9050 // and the service had previously asked to be told when
9051 // rebound, then do so.
9052 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9053 requestServiceBindingLocked(s, b.intent, true);
9054 }
9055 } else if (!b.intent.requested) {
9056 requestServiceBindingLocked(s, b.intent, false);
9057 }
9058
9059 Binder.restoreCallingIdentity(origId);
9060 }
9061
9062 return 1;
9063 }
9064
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009065 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009066 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009067 IBinder binder = c.conn.asBinder();
9068 AppBindRecord b = c.binding;
9069 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009070 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9071 if (clist != null) {
9072 clist.remove(c);
9073 if (clist.size() == 0) {
9074 s.connections.remove(binder);
9075 }
9076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 b.connections.remove(c);
9078 if (c.activity != null && c.activity != skipAct) {
9079 if (c.activity.connections != null) {
9080 c.activity.connections.remove(c);
9081 }
9082 }
9083 if (b.client != skipApp) {
9084 b.client.connections.remove(c);
9085 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009086 clist = mServiceConnections.get(binder);
9087 if (clist != null) {
9088 clist.remove(c);
9089 if (clist.size() == 0) {
9090 mServiceConnections.remove(binder);
9091 }
9092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009093
9094 if (b.connections.size() == 0) {
9095 b.intent.apps.remove(b.client);
9096 }
9097
Joe Onorato8a9b2202010-02-26 18:56:32 -08009098 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009099 + ": shouldUnbind=" + b.intent.hasBound);
9100 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9101 && b.intent.hasBound) {
9102 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009103 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
9104 + " from " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009105 bumpServiceExecutingLocked(s);
9106 updateOomAdjLocked(s.app);
9107 b.intent.hasBound = false;
9108 // Assume the client doesn't want to know about a rebind;
9109 // we will deal with that later if it asks for one.
9110 b.intent.doRebind = false;
9111 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9112 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009113 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009114 serviceDoneExecutingLocked(s, true);
9115 }
9116 }
9117
9118 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9119 bringDownServiceLocked(s, false);
9120 }
9121 }
9122
9123 public boolean unbindService(IServiceConnection connection) {
9124 synchronized (this) {
9125 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009126 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009127 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9128 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009129 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130 + connection.asBinder());
9131 return false;
9132 }
9133
9134 final long origId = Binder.clearCallingIdentity();
9135
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009136 while (clist.size() > 0) {
9137 ConnectionRecord r = clist.get(0);
9138 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009139
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009140 if (r.binding.service.app != null) {
9141 // This could have made the service less important.
9142 updateOomAdjLocked(r.binding.service.app);
9143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009144 }
9145
9146 Binder.restoreCallingIdentity(origId);
9147 }
9148
9149 return true;
9150 }
9151
9152 public void publishService(IBinder token, Intent intent, IBinder service) {
9153 // Refuse possible leaked file descriptors
9154 if (intent != null && intent.hasFileDescriptors() == true) {
9155 throw new IllegalArgumentException("File descriptors passed in Intent");
9156 }
9157
9158 synchronized(this) {
9159 if (!(token instanceof ServiceRecord)) {
9160 throw new IllegalArgumentException("Invalid service token");
9161 }
9162 ServiceRecord r = (ServiceRecord)token;
9163
9164 final long origId = Binder.clearCallingIdentity();
9165
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009166 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009167 + " " + intent + ": " + service);
9168 if (r != null) {
9169 Intent.FilterComparison filter
9170 = new Intent.FilterComparison(intent);
9171 IntentBindRecord b = r.bindings.get(filter);
9172 if (b != null && !b.received) {
9173 b.binder = service;
9174 b.requested = true;
9175 b.received = true;
9176 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009177 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009178 = r.connections.values().iterator();
9179 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009180 ArrayList<ConnectionRecord> clist = it.next();
9181 for (int i=0; i<clist.size(); i++) {
9182 ConnectionRecord c = clist.get(i);
9183 if (!filter.equals(c.binding.intent.intent)) {
9184 if (DEBUG_SERVICE) Slog.v(
9185 TAG, "Not publishing to: " + c);
9186 if (DEBUG_SERVICE) Slog.v(
9187 TAG, "Bound intent: " + c.binding.intent.intent);
9188 if (DEBUG_SERVICE) Slog.v(
9189 TAG, "Published intent: " + intent);
9190 continue;
9191 }
9192 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9193 try {
9194 c.conn.connected(r.name, service);
9195 } catch (Exception e) {
9196 Slog.w(TAG, "Failure sending service " + r.name +
9197 " to connection " + c.conn.asBinder() +
9198 " (in " + c.binding.client.processName + ")", e);
9199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009200 }
9201 }
9202 }
9203 }
9204
9205 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9206
9207 Binder.restoreCallingIdentity(origId);
9208 }
9209 }
9210 }
9211
9212 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9213 // Refuse possible leaked file descriptors
9214 if (intent != null && intent.hasFileDescriptors() == true) {
9215 throw new IllegalArgumentException("File descriptors passed in Intent");
9216 }
9217
9218 synchronized(this) {
9219 if (!(token instanceof ServiceRecord)) {
9220 throw new IllegalArgumentException("Invalid service token");
9221 }
9222 ServiceRecord r = (ServiceRecord)token;
9223
9224 final long origId = Binder.clearCallingIdentity();
9225
9226 if (r != null) {
9227 Intent.FilterComparison filter
9228 = new Intent.FilterComparison(intent);
9229 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009230 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 + " at " + b + ": apps="
9232 + (b != null ? b.apps.size() : 0));
9233 if (b != null) {
9234 if (b.apps.size() > 0) {
9235 // Applications have already bound since the last
9236 // unbind, so just rebind right here.
9237 requestServiceBindingLocked(r, b, true);
9238 } else {
9239 // Note to tell the service the next time there is
9240 // a new client.
9241 b.doRebind = true;
9242 }
9243 }
9244
9245 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9246
9247 Binder.restoreCallingIdentity(origId);
9248 }
9249 }
9250 }
9251
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009252 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009253 synchronized(this) {
9254 if (!(token instanceof ServiceRecord)) {
9255 throw new IllegalArgumentException("Invalid service token");
9256 }
9257 ServiceRecord r = (ServiceRecord)token;
9258 boolean inStopping = mStoppingServices.contains(token);
9259 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009260 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009261 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009262 + " with incorrect token: given " + token
9263 + ", expected " + r);
9264 return;
9265 }
9266
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009267 if (type == 1) {
9268 // This is a call from a service start... take care of
9269 // book-keeping.
9270 r.callStart = true;
9271 switch (res) {
9272 case Service.START_STICKY_COMPATIBILITY:
9273 case Service.START_STICKY: {
9274 // We are done with the associated start arguments.
9275 r.findDeliveredStart(startId, true);
9276 // Don't stop if killed.
9277 r.stopIfKilled = false;
9278 break;
9279 }
9280 case Service.START_NOT_STICKY: {
9281 // We are done with the associated start arguments.
9282 r.findDeliveredStart(startId, true);
9283 if (r.lastStartId == startId) {
9284 // There is no more work, and this service
9285 // doesn't want to hang around if killed.
9286 r.stopIfKilled = true;
9287 }
9288 break;
9289 }
9290 case Service.START_REDELIVER_INTENT: {
9291 // We'll keep this item until they explicitly
9292 // call stop for it, but keep track of the fact
9293 // that it was delivered.
9294 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9295 if (si != null) {
9296 si.deliveryCount = 0;
9297 si.doneExecutingCount++;
9298 // Don't stop if killed.
9299 r.stopIfKilled = true;
9300 }
9301 break;
9302 }
9303 default:
9304 throw new IllegalArgumentException(
9305 "Unknown service start result: " + res);
9306 }
9307 if (res == Service.START_STICKY_COMPATIBILITY) {
9308 r.callStart = false;
9309 }
9310 }
9311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 final long origId = Binder.clearCallingIdentity();
9313 serviceDoneExecutingLocked(r, inStopping);
9314 Binder.restoreCallingIdentity(origId);
9315 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009316 Slog.w(TAG, "Done executing unknown service from pid "
9317 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009318 }
9319 }
9320 }
9321
9322 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009323 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9324 + ": nesting=" + r.executeNesting
9325 + ", inStopping=" + inStopping + ", app=" + r.app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 r.executeNesting--;
9327 if (r.executeNesting <= 0 && r.app != null) {
9328 r.app.executingServices.remove(r);
9329 if (r.app.executingServices.size() == 0) {
9330 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9331 }
9332 if (inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009333 if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 mStoppingServices.remove(r);
9335 }
9336 updateOomAdjLocked(r.app);
9337 }
9338 }
9339
9340 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009341 String anrMessage = null;
9342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009343 synchronized(this) {
9344 if (proc.executingServices.size() == 0 || proc.thread == null) {
9345 return;
9346 }
9347 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9348 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9349 ServiceRecord timeout = null;
9350 long nextTime = 0;
9351 while (it.hasNext()) {
9352 ServiceRecord sr = it.next();
9353 if (sr.executingStart < maxTime) {
9354 timeout = sr;
9355 break;
9356 }
9357 if (sr.executingStart > nextTime) {
9358 nextTime = sr.executingStart;
9359 }
9360 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009361 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009362 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009363 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009364 } else {
9365 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9366 msg.obj = proc;
9367 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9368 }
9369 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009370
9371 if (anrMessage != null) {
9372 appNotResponding(proc, null, null, anrMessage);
9373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009374 }
9375
9376 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009377 // BACKUP AND RESTORE
9378 // =========================================================
9379
9380 // Cause the target app to be launched if necessary and its backup agent
9381 // instantiated. The backup agent will invoke backupAgentCreated() on the
9382 // activity manager to announce its creation.
9383 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009384 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009385 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9386
9387 synchronized(this) {
9388 // !!! TODO: currently no check here that we're already bound
9389 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9390 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9391 synchronized (stats) {
9392 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9393 }
9394
9395 BackupRecord r = new BackupRecord(ss, app, backupMode);
9396 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9397 // startProcessLocked() returns existing proc's record if it's already running
9398 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009399 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009400 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009401 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009402 return false;
9403 }
9404
9405 r.app = proc;
9406 mBackupTarget = r;
9407 mBackupAppName = app.packageName;
9408
Christopher Tate6fa95972009-06-05 18:43:55 -07009409 // Try not to kill the process during backup
9410 updateOomAdjLocked(proc);
9411
Christopher Tate181fafa2009-05-14 11:12:14 -07009412 // If the process is already attached, schedule the creation of the backup agent now.
9413 // If it is not yet live, this will be done when it attaches to the framework.
9414 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009415 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009416 try {
9417 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9418 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009419 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009420 }
9421 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009422 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009423 }
9424 // Invariants: at this point, the target app process exists and the application
9425 // is either already running or in the process of coming up. mBackupTarget and
9426 // mBackupAppName describe the app, so that when it binds back to the AM we
9427 // know that it's scheduled for a backup-agent operation.
9428 }
9429
9430 return true;
9431 }
9432
9433 // A backup agent has just come up
9434 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009435 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009436 + " = " + agent);
9437
9438 synchronized(this) {
9439 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009440 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009441 return;
9442 }
9443
Christopher Tate043dadc2009-06-02 16:11:00 -07009444 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009445 try {
9446 IBackupManager bm = IBackupManager.Stub.asInterface(
9447 ServiceManager.getService(Context.BACKUP_SERVICE));
9448 bm.agentConnected(agentPackageName, agent);
9449 } catch (RemoteException e) {
9450 // can't happen; the backup manager service is local
9451 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009452 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009453 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009454 } finally {
9455 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009456 }
9457 }
9458 }
9459
9460 // done with this agent
9461 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009462 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009463 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009464 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009465 return;
9466 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009467
9468 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009469 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009470 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009471 return;
9472 }
9473
Christopher Tate181fafa2009-05-14 11:12:14 -07009474 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009475 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009476 return;
9477 }
9478
Christopher Tate6fa95972009-06-05 18:43:55 -07009479 ProcessRecord proc = mBackupTarget.app;
9480 mBackupTarget = null;
9481 mBackupAppName = null;
9482
9483 // Not backing this app up any more; reset its OOM adjustment
9484 updateOomAdjLocked(proc);
9485
Christopher Tatec7b31e32009-06-10 15:49:30 -07009486 // If the app crashed during backup, 'thread' will be null here
9487 if (proc.thread != null) {
9488 try {
9489 proc.thread.scheduleDestroyBackupAgent(appInfo);
9490 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009491 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009492 e.printStackTrace();
9493 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009494 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009495 }
9496 }
9497 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009498 // BROADCASTS
9499 // =========================================================
9500
Josh Bartel7f208742010-02-25 11:01:44 -06009501 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009502 List cur) {
9503 final ContentResolver resolver = mContext.getContentResolver();
9504 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9505 if (list == null) {
9506 return cur;
9507 }
9508 int N = list.size();
9509 for (int i=0; i<N; i++) {
9510 Intent intent = list.get(i);
9511 if (filter.match(resolver, intent, true, TAG) >= 0) {
9512 if (cur == null) {
9513 cur = new ArrayList<Intent>();
9514 }
9515 cur.add(intent);
9516 }
9517 }
9518 return cur;
9519 }
9520
9521 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009522 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009523 + mBroadcastsScheduled);
9524
9525 if (mBroadcastsScheduled) {
9526 return;
9527 }
9528 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9529 mBroadcastsScheduled = true;
9530 }
9531
9532 public Intent registerReceiver(IApplicationThread caller,
9533 IIntentReceiver receiver, IntentFilter filter, String permission) {
9534 synchronized(this) {
9535 ProcessRecord callerApp = null;
9536 if (caller != null) {
9537 callerApp = getRecordForAppLocked(caller);
9538 if (callerApp == null) {
9539 throw new SecurityException(
9540 "Unable to find app for caller " + caller
9541 + " (pid=" + Binder.getCallingPid()
9542 + ") when registering receiver " + receiver);
9543 }
9544 }
9545
9546 List allSticky = null;
9547
9548 // Look for any matching sticky broadcasts...
9549 Iterator actions = filter.actionsIterator();
9550 if (actions != null) {
9551 while (actions.hasNext()) {
9552 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009553 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554 }
9555 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009556 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009557 }
9558
9559 // The first sticky in the list is returned directly back to
9560 // the client.
9561 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9562
Joe Onorato8a9b2202010-02-26 18:56:32 -08009563 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009564 + ": " + sticky);
9565
9566 if (receiver == null) {
9567 return sticky;
9568 }
9569
9570 ReceiverList rl
9571 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9572 if (rl == null) {
9573 rl = new ReceiverList(this, callerApp,
9574 Binder.getCallingPid(),
9575 Binder.getCallingUid(), receiver);
9576 if (rl.app != null) {
9577 rl.app.receivers.add(rl);
9578 } else {
9579 try {
9580 receiver.asBinder().linkToDeath(rl, 0);
9581 } catch (RemoteException e) {
9582 return sticky;
9583 }
9584 rl.linkedToDeath = true;
9585 }
9586 mRegisteredReceivers.put(receiver.asBinder(), rl);
9587 }
9588 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9589 rl.add(bf);
9590 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009591 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009592 }
9593 mReceiverResolver.addFilter(bf);
9594
9595 // Enqueue broadcasts for all existing stickies that match
9596 // this filter.
9597 if (allSticky != null) {
9598 ArrayList receivers = new ArrayList();
9599 receivers.add(bf);
9600
9601 int N = allSticky.size();
9602 for (int i=0; i<N; i++) {
9603 Intent intent = (Intent)allSticky.get(i);
9604 BroadcastRecord r = new BroadcastRecord(intent, null,
9605 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009606 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009607 if (mParallelBroadcasts.size() == 0) {
9608 scheduleBroadcastsLocked();
9609 }
9610 mParallelBroadcasts.add(r);
9611 }
9612 }
9613
9614 return sticky;
9615 }
9616 }
9617
9618 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009619 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009620
9621 boolean doNext = false;
9622
9623 synchronized(this) {
9624 ReceiverList rl
9625 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9626 if (rl != null) {
9627 if (rl.curBroadcast != null) {
9628 BroadcastRecord r = rl.curBroadcast;
9629 doNext = finishReceiverLocked(
9630 receiver.asBinder(), r.resultCode, r.resultData,
9631 r.resultExtras, r.resultAbort, true);
9632 }
9633
9634 if (rl.app != null) {
9635 rl.app.receivers.remove(rl);
9636 }
9637 removeReceiverLocked(rl);
9638 if (rl.linkedToDeath) {
9639 rl.linkedToDeath = false;
9640 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9641 }
9642 }
9643 }
9644
9645 if (!doNext) {
9646 return;
9647 }
9648
9649 final long origId = Binder.clearCallingIdentity();
9650 processNextBroadcast(false);
9651 trimApplications();
9652 Binder.restoreCallingIdentity(origId);
9653 }
9654
9655 void removeReceiverLocked(ReceiverList rl) {
9656 mRegisteredReceivers.remove(rl.receiver.asBinder());
9657 int N = rl.size();
9658 for (int i=0; i<N; i++) {
9659 mReceiverResolver.removeFilter(rl.get(i));
9660 }
9661 }
9662
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009663 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9664 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9665 ProcessRecord r = mLruProcesses.get(i);
9666 if (r.thread != null) {
9667 try {
9668 r.thread.dispatchPackageBroadcast(cmd, packages);
9669 } catch (RemoteException ex) {
9670 }
9671 }
9672 }
9673 }
9674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009675 private final int broadcastIntentLocked(ProcessRecord callerApp,
9676 String callerPackage, Intent intent, String resolvedType,
9677 IIntentReceiver resultTo, int resultCode, String resultData,
9678 Bundle map, String requiredPermission,
9679 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9680 intent = new Intent(intent);
9681
Joe Onorato8a9b2202010-02-26 18:56:32 -08009682 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9684 + " ordered=" + ordered);
9685 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009686 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009687 }
9688
9689 // Handle special intents: if this broadcast is from the package
9690 // manager about a package being removed, we need to remove all of
9691 // its activities from the history stack.
9692 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9693 intent.getAction());
9694 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9695 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009696 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009697 || uidRemoved) {
9698 if (checkComponentPermission(
9699 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9700 callingPid, callingUid, -1)
9701 == PackageManager.PERMISSION_GRANTED) {
9702 if (uidRemoved) {
9703 final Bundle intentExtras = intent.getExtras();
9704 final int uid = intentExtras != null
9705 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9706 if (uid >= 0) {
9707 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9708 synchronized (bs) {
9709 bs.removeUidStatsLocked(uid);
9710 }
9711 }
9712 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009713 // If resources are unvailble just force stop all
9714 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009715 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009716 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9717 if (list != null && (list.length > 0)) {
9718 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009719 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009720 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009721 sendPackageBroadcastLocked(
9722 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009723 }
9724 } else {
9725 Uri data = intent.getData();
9726 String ssp;
9727 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9728 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9729 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009730 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009731 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009732 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9733 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9734 new String[] {ssp});
9735 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009736 }
9737 }
9738 }
9739 } else {
9740 String msg = "Permission Denial: " + intent.getAction()
9741 + " broadcast from " + callerPackage + " (pid=" + callingPid
9742 + ", uid=" + callingUid + ")"
9743 + " requires "
9744 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009745 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009746 throw new SecurityException(msg);
9747 }
9748 }
9749
9750 /*
9751 * If this is the time zone changed action, queue up a message that will reset the timezone
9752 * of all currently running processes. This message will get queued up before the broadcast
9753 * happens.
9754 */
9755 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9756 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9757 }
9758
Dianne Hackborn854060af2009-07-09 18:14:31 -07009759 /*
9760 * Prevent non-system code (defined here to be non-persistent
9761 * processes) from sending protected broadcasts.
9762 */
9763 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9764 || callingUid == Process.SHELL_UID || callingUid == 0) {
9765 // Always okay.
9766 } else if (callerApp == null || !callerApp.persistent) {
9767 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009768 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009769 intent.getAction())) {
9770 String msg = "Permission Denial: not allowed to send broadcast "
9771 + intent.getAction() + " from pid="
9772 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009773 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009774 throw new SecurityException(msg);
9775 }
9776 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009777 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009778 return BROADCAST_SUCCESS;
9779 }
9780 }
9781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782 // Add to the sticky list if requested.
9783 if (sticky) {
9784 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9785 callingPid, callingUid)
9786 != PackageManager.PERMISSION_GRANTED) {
9787 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9788 + callingPid + ", uid=" + callingUid
9789 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009790 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 throw new SecurityException(msg);
9792 }
9793 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009794 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009795 + " and enforce permission " + requiredPermission);
9796 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9797 }
9798 if (intent.getComponent() != null) {
9799 throw new SecurityException(
9800 "Sticky broadcasts can't target a specific component");
9801 }
9802 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9803 if (list == null) {
9804 list = new ArrayList<Intent>();
9805 mStickyBroadcasts.put(intent.getAction(), list);
9806 }
9807 int N = list.size();
9808 int i;
9809 for (i=0; i<N; i++) {
9810 if (intent.filterEquals(list.get(i))) {
9811 // This sticky already exists, replace it.
9812 list.set(i, new Intent(intent));
9813 break;
9814 }
9815 }
9816 if (i >= N) {
9817 list.add(new Intent(intent));
9818 }
9819 }
9820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 // Figure out who all will receive this broadcast.
9822 List receivers = null;
9823 List<BroadcastFilter> registeredReceivers = null;
9824 try {
9825 if (intent.getComponent() != null) {
9826 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009827 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009828 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 if (ai != null) {
9830 receivers = new ArrayList();
9831 ResolveInfo ri = new ResolveInfo();
9832 ri.activityInfo = ai;
9833 receivers.add(ri);
9834 }
9835 } else {
9836 // Need to resolve the intent to interested receivers...
9837 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9838 == 0) {
9839 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009840 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009841 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 }
Mihai Preda074edef2009-05-18 17:13:31 +02009843 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009844 }
9845 } catch (RemoteException ex) {
9846 // pm is in same process, this will never happen.
9847 }
9848
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009849 final boolean replacePending =
9850 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9851
Joe Onorato8a9b2202010-02-26 18:56:32 -08009852 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009853 + " replacePending=" + replacePending);
9854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009855 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9856 if (!ordered && NR > 0) {
9857 // If we are not serializing this broadcast, then send the
9858 // registered receivers separately so they don't wait for the
9859 // components to be launched.
9860 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9861 callerPackage, callingPid, callingUid, requiredPermission,
9862 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009863 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009864 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 TAG, "Enqueueing parallel broadcast " + r
9866 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009867 boolean replaced = false;
9868 if (replacePending) {
9869 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9870 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009871 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009872 "***** DROPPING PARALLEL: " + intent);
9873 mParallelBroadcasts.set(i, r);
9874 replaced = true;
9875 break;
9876 }
9877 }
9878 }
9879 if (!replaced) {
9880 mParallelBroadcasts.add(r);
9881 scheduleBroadcastsLocked();
9882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883 registeredReceivers = null;
9884 NR = 0;
9885 }
9886
9887 // Merge into one list.
9888 int ir = 0;
9889 if (receivers != null) {
9890 // A special case for PACKAGE_ADDED: do not allow the package
9891 // being added to see this broadcast. This prevents them from
9892 // using this as a back door to get run as soon as they are
9893 // installed. Maybe in the future we want to have a special install
9894 // broadcast or such for apps, but we'd like to deliberately make
9895 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009896 String skipPackages[] = null;
9897 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9898 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9899 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9900 Uri data = intent.getData();
9901 if (data != null) {
9902 String pkgName = data.getSchemeSpecificPart();
9903 if (pkgName != null) {
9904 skipPackages = new String[] { pkgName };
9905 }
9906 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009907 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009908 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009909 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009910 if (skipPackages != null && (skipPackages.length > 0)) {
9911 for (String skipPackage : skipPackages) {
9912 if (skipPackage != null) {
9913 int NT = receivers.size();
9914 for (int it=0; it<NT; it++) {
9915 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9916 if (curt.activityInfo.packageName.equals(skipPackage)) {
9917 receivers.remove(it);
9918 it--;
9919 NT--;
9920 }
9921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 }
9923 }
9924 }
9925
9926 int NT = receivers != null ? receivers.size() : 0;
9927 int it = 0;
9928 ResolveInfo curt = null;
9929 BroadcastFilter curr = null;
9930 while (it < NT && ir < NR) {
9931 if (curt == null) {
9932 curt = (ResolveInfo)receivers.get(it);
9933 }
9934 if (curr == null) {
9935 curr = registeredReceivers.get(ir);
9936 }
9937 if (curr.getPriority() >= curt.priority) {
9938 // Insert this broadcast record into the final list.
9939 receivers.add(it, curr);
9940 ir++;
9941 curr = null;
9942 it++;
9943 NT++;
9944 } else {
9945 // Skip to the next ResolveInfo in the final list.
9946 it++;
9947 curt = null;
9948 }
9949 }
9950 }
9951 while (ir < NR) {
9952 if (receivers == null) {
9953 receivers = new ArrayList();
9954 }
9955 receivers.add(registeredReceivers.get(ir));
9956 ir++;
9957 }
9958
9959 if ((receivers != null && receivers.size() > 0)
9960 || resultTo != null) {
9961 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9962 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009963 receivers, resultTo, resultCode, resultData, map, ordered,
9964 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009965 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009966 TAG, "Enqueueing ordered broadcast " + r
9967 + ": prev had " + mOrderedBroadcasts.size());
9968 if (DEBUG_BROADCAST) {
9969 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009970 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009972 boolean replaced = false;
9973 if (replacePending) {
9974 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9975 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009976 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009977 "***** DROPPING ORDERED: " + intent);
9978 mOrderedBroadcasts.set(i, r);
9979 replaced = true;
9980 break;
9981 }
9982 }
9983 }
9984 if (!replaced) {
9985 mOrderedBroadcasts.add(r);
9986 scheduleBroadcastsLocked();
9987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009988 }
9989
9990 return BROADCAST_SUCCESS;
9991 }
9992
9993 public final int broadcastIntent(IApplicationThread caller,
9994 Intent intent, String resolvedType, IIntentReceiver resultTo,
9995 int resultCode, String resultData, Bundle map,
9996 String requiredPermission, boolean serialized, boolean sticky) {
9997 // Refuse possible leaked file descriptors
9998 if (intent != null && intent.hasFileDescriptors() == true) {
9999 throw new IllegalArgumentException("File descriptors passed in Intent");
10000 }
10001
10002 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010003 int flags = intent.getFlags();
10004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010005 if (!mSystemReady) {
10006 // if the caller really truly claims to know what they're doing, go
10007 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010008 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10009 intent = new Intent(intent);
10010 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10011 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080010012 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010013 + " before boot completion");
10014 throw new IllegalStateException("Cannot broadcast before boot completed");
10015 }
10016 }
10017
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010018 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10019 throw new IllegalArgumentException(
10020 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10021 }
10022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010023 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10024 final int callingPid = Binder.getCallingPid();
10025 final int callingUid = Binder.getCallingUid();
10026 final long origId = Binder.clearCallingIdentity();
10027 int res = broadcastIntentLocked(callerApp,
10028 callerApp != null ? callerApp.info.packageName : null,
10029 intent, resolvedType, resultTo,
10030 resultCode, resultData, map, requiredPermission, serialized,
10031 sticky, callingPid, callingUid);
10032 Binder.restoreCallingIdentity(origId);
10033 return res;
10034 }
10035 }
10036
10037 int broadcastIntentInPackage(String packageName, int uid,
10038 Intent intent, String resolvedType, IIntentReceiver resultTo,
10039 int resultCode, String resultData, Bundle map,
10040 String requiredPermission, boolean serialized, boolean sticky) {
10041 synchronized(this) {
10042 final long origId = Binder.clearCallingIdentity();
10043 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10044 resultTo, resultCode, resultData, map, requiredPermission,
10045 serialized, sticky, -1, uid);
10046 Binder.restoreCallingIdentity(origId);
10047 return res;
10048 }
10049 }
10050
10051 public final void unbroadcastIntent(IApplicationThread caller,
10052 Intent intent) {
10053 // Refuse possible leaked file descriptors
10054 if (intent != null && intent.hasFileDescriptors() == true) {
10055 throw new IllegalArgumentException("File descriptors passed in Intent");
10056 }
10057
10058 synchronized(this) {
10059 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10060 != PackageManager.PERMISSION_GRANTED) {
10061 String msg = "Permission Denial: unbroadcastIntent() from pid="
10062 + Binder.getCallingPid()
10063 + ", uid=" + Binder.getCallingUid()
10064 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010065 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 throw new SecurityException(msg);
10067 }
10068 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10069 if (list != null) {
10070 int N = list.size();
10071 int i;
10072 for (i=0; i<N; i++) {
10073 if (intent.filterEquals(list.get(i))) {
10074 list.remove(i);
10075 break;
10076 }
10077 }
10078 }
10079 }
10080 }
10081
10082 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10083 String resultData, Bundle resultExtras, boolean resultAbort,
10084 boolean explicit) {
10085 if (mOrderedBroadcasts.size() == 0) {
10086 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010087 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010088 }
10089 return false;
10090 }
10091 BroadcastRecord r = mOrderedBroadcasts.get(0);
10092 if (r.receiver == null) {
10093 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010094 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010095 }
10096 return false;
10097 }
10098 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010099 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010100 return false;
10101 }
10102 int state = r.state;
10103 r.state = r.IDLE;
10104 if (state == r.IDLE) {
10105 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010106 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010107 }
10108 }
10109 r.receiver = null;
10110 r.intent.setComponent(null);
10111 if (r.curApp != null) {
10112 r.curApp.curReceiver = null;
10113 }
10114 if (r.curFilter != null) {
10115 r.curFilter.receiverList.curBroadcast = null;
10116 }
10117 r.curFilter = null;
10118 r.curApp = null;
10119 r.curComponent = null;
10120 r.curReceiver = null;
10121 mPendingBroadcast = null;
10122
10123 r.resultCode = resultCode;
10124 r.resultData = resultData;
10125 r.resultExtras = resultExtras;
10126 r.resultAbort = resultAbort;
10127
10128 // We will process the next receiver right now if this is finishing
10129 // an app receiver (which is always asynchronous) or after we have
10130 // come back from calling a receiver.
10131 return state == BroadcastRecord.APP_RECEIVE
10132 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10133 }
10134
10135 public void finishReceiver(IBinder who, int resultCode, String resultData,
10136 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010137 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010138
10139 // Refuse possible leaked file descriptors
10140 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10141 throw new IllegalArgumentException("File descriptors passed in Bundle");
10142 }
10143
10144 boolean doNext;
10145
10146 final long origId = Binder.clearCallingIdentity();
10147
10148 synchronized(this) {
10149 doNext = finishReceiverLocked(
10150 who, resultCode, resultData, resultExtras, resultAbort, true);
10151 }
10152
10153 if (doNext) {
10154 processNextBroadcast(false);
10155 }
10156 trimApplications();
10157
10158 Binder.restoreCallingIdentity(origId);
10159 }
10160
10161 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10162 if (r.nextReceiver > 0) {
10163 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10164 if (curReceiver instanceof BroadcastFilter) {
10165 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010166 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010167 System.identityHashCode(r),
10168 r.intent.getAction(),
10169 r.nextReceiver - 1,
10170 System.identityHashCode(bf));
10171 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010172 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010173 System.identityHashCode(r),
10174 r.intent.getAction(),
10175 r.nextReceiver - 1,
10176 ((ResolveInfo)curReceiver).toString());
10177 }
10178 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010179 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010180 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010181 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 System.identityHashCode(r),
10183 r.intent.getAction(),
10184 r.nextReceiver,
10185 "NONE");
10186 }
10187 }
10188
10189 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010190 ProcessRecord app = null;
10191 String anrMessage = null;
10192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010193 synchronized (this) {
10194 if (mOrderedBroadcasts.size() == 0) {
10195 return;
10196 }
10197 long now = SystemClock.uptimeMillis();
10198 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010199 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010200 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010201 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010202 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010203 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010204 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205 return;
10206 }
10207
Joe Onorato8a9b2202010-02-26 18:56:32 -080010208 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010209 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010210 r.anrCount++;
10211
10212 // Current receiver has passed its expiration date.
10213 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010214 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010215 return;
10216 }
10217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010218 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010219 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010220 logBroadcastReceiverDiscard(r);
10221 if (curReceiver instanceof BroadcastFilter) {
10222 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10223 if (bf.receiverList.pid != 0
10224 && bf.receiverList.pid != MY_PID) {
10225 synchronized (this.mPidsSelfLocked) {
10226 app = this.mPidsSelfLocked.get(
10227 bf.receiverList.pid);
10228 }
10229 }
10230 } else {
10231 app = r.curApp;
10232 }
10233
10234 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010235 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 }
10237
10238 if (mPendingBroadcast == r) {
10239 mPendingBroadcast = null;
10240 }
10241
10242 // Move on to the next receiver.
10243 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10244 r.resultExtras, r.resultAbort, true);
10245 scheduleBroadcastsLocked();
10246 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010247
10248 if (anrMessage != null) {
10249 appNotResponding(app, null, null, anrMessage);
10250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 }
10252
10253 private final void processCurBroadcastLocked(BroadcastRecord r,
10254 ProcessRecord app) throws RemoteException {
10255 if (app.thread == null) {
10256 throw new RemoteException();
10257 }
10258 r.receiver = app.thread.asBinder();
10259 r.curApp = app;
10260 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010261 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262
10263 // Tell the application to launch this receiver.
10264 r.intent.setComponent(r.curComponent);
10265
10266 boolean started = false;
10267 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010268 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010269 "Delivering to component " + r.curComponent
10270 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010271 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10273 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10274 started = true;
10275 } finally {
10276 if (!started) {
10277 r.receiver = null;
10278 r.curApp = null;
10279 app.curReceiver = null;
10280 }
10281 }
10282
10283 }
10284
10285 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010286 Intent intent, int resultCode, String data, Bundle extras,
10287 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010288 if (app != null && app.thread != null) {
10289 // If we have an app thread, do the call through that so it is
10290 // correctly ordered with other one-way calls.
10291 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010292 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010293 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010294 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010295 }
10296 }
10297
10298 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10299 BroadcastFilter filter, boolean ordered) {
10300 boolean skip = false;
10301 if (filter.requiredPermission != null) {
10302 int perm = checkComponentPermission(filter.requiredPermission,
10303 r.callingPid, r.callingUid, -1);
10304 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010305 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010306 + r.intent.toString()
10307 + " from " + r.callerPackage + " (pid="
10308 + r.callingPid + ", uid=" + r.callingUid + ")"
10309 + " requires " + filter.requiredPermission
10310 + " due to registered receiver " + filter);
10311 skip = true;
10312 }
10313 }
10314 if (r.requiredPermission != null) {
10315 int perm = checkComponentPermission(r.requiredPermission,
10316 filter.receiverList.pid, filter.receiverList.uid, -1);
10317 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010318 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 + r.intent.toString()
10320 + " to " + filter.receiverList.app
10321 + " (pid=" + filter.receiverList.pid
10322 + ", uid=" + filter.receiverList.uid + ")"
10323 + " requires " + r.requiredPermission
10324 + " due to sender " + r.callerPackage
10325 + " (uid " + r.callingUid + ")");
10326 skip = true;
10327 }
10328 }
10329
10330 if (!skip) {
10331 // If this is not being sent as an ordered broadcast, then we
10332 // don't want to touch the fields that keep track of the current
10333 // state of ordered broadcasts.
10334 if (ordered) {
10335 r.receiver = filter.receiverList.receiver.asBinder();
10336 r.curFilter = filter;
10337 filter.receiverList.curBroadcast = r;
10338 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010339 if (filter.receiverList.app != null) {
10340 // Bump hosting application to no longer be in background
10341 // scheduling class. Note that we can't do that if there
10342 // isn't an app... but we can only be in that case for
10343 // things that directly call the IActivityManager API, which
10344 // are already core system stuff so don't matter for this.
10345 r.curApp = filter.receiverList.app;
10346 filter.receiverList.app.curReceiver = r;
10347 updateOomAdjLocked();
10348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010349 }
10350 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010351 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010352 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010353 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010354 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010355 }
10356 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10357 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010358 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010359 if (ordered) {
10360 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10361 }
10362 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010363 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010364 if (ordered) {
10365 r.receiver = null;
10366 r.curFilter = null;
10367 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010368 if (filter.receiverList.app != null) {
10369 filter.receiverList.app.curReceiver = null;
10370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 }
10372 }
10373 }
10374 }
10375
Dianne Hackborn12527f92009-11-11 17:39:50 -080010376 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10377 if (r.callingUid < 0) {
10378 // This was from a registerReceiver() call; ignore it.
10379 return;
10380 }
10381 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10382 MAX_BROADCAST_HISTORY-1);
10383 r.finishTime = SystemClock.uptimeMillis();
10384 mBroadcastHistory[0] = r;
10385 }
10386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010387 private final void processNextBroadcast(boolean fromMsg) {
10388 synchronized(this) {
10389 BroadcastRecord r;
10390
Joe Onorato8a9b2202010-02-26 18:56:32 -080010391 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010392 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010393 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010394
10395 updateCpuStats();
10396
10397 if (fromMsg) {
10398 mBroadcastsScheduled = false;
10399 }
10400
10401 // First, deliver any non-serialized broadcasts right away.
10402 while (mParallelBroadcasts.size() > 0) {
10403 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010404 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010406 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010407 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408 for (int i=0; i<N; i++) {
10409 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010410 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010411 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010412 + target + ": " + r);
10413 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10414 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010415 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010416 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010417 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010418 }
10419
10420 // Now take care of the next serialized one...
10421
10422 // If we are waiting for a process to come up to handle the next
10423 // broadcast, then do nothing at this point. Just in case, we
10424 // check that the process we're waiting for still exists.
10425 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010426 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010427 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010428 + mPendingBroadcast.curApp);
10429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430
10431 boolean isDead;
10432 synchronized (mPidsSelfLocked) {
10433 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10434 }
10435 if (!isDead) {
10436 // It's still alive, so keep waiting
10437 return;
10438 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010439 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010440 + " died before responding to broadcast");
10441 mPendingBroadcast = null;
10442 }
10443 }
10444
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010445 boolean looped = false;
10446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010447 do {
10448 if (mOrderedBroadcasts.size() == 0) {
10449 // No more broadcasts pending, so all done!
10450 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010451 if (looped) {
10452 // If we had finished the last ordered broadcast, then
10453 // make sure all processes have correct oom and sched
10454 // adjustments.
10455 updateOomAdjLocked();
10456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457 return;
10458 }
10459 r = mOrderedBroadcasts.get(0);
10460 boolean forceReceive = false;
10461
10462 // Ensure that even if something goes awry with the timeout
10463 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010464 // and continue to make progress.
10465 //
10466 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10467 // receivers don't get executed with with timeouts. They're intended for
10468 // one time heavy lifting after system upgrades and can take
10469 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010470 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010471 if (mSystemReady && r.dispatchTime > 0) {
10472 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010473 if ((numReceivers > 0) &&
10474 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010475 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010476 + " now=" + now
10477 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010478 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 + " intent=" + r.intent
10480 + " numReceivers=" + numReceivers
10481 + " nextReceiver=" + r.nextReceiver
10482 + " state=" + r.state);
10483 broadcastTimeout(); // forcibly finish this broadcast
10484 forceReceive = true;
10485 r.state = BroadcastRecord.IDLE;
10486 }
10487 }
10488
10489 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010490 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010491 "processNextBroadcast() called when not idle (state="
10492 + r.state + ")");
10493 return;
10494 }
10495
10496 if (r.receivers == null || r.nextReceiver >= numReceivers
10497 || r.resultAbort || forceReceive) {
10498 // No more receivers for this broadcast! Send the final
10499 // result if requested...
10500 if (r.resultTo != null) {
10501 try {
10502 if (DEBUG_BROADCAST) {
10503 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010504 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010505 + " seq=" + seq + " app=" + r.callerApp);
10506 }
10507 performReceive(r.callerApp, r.resultTo,
10508 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010509 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010510 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010511 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010512 }
10513 }
10514
Joe Onorato8a9b2202010-02-26 18:56:32 -080010515 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010516 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10517
Joe Onorato8a9b2202010-02-26 18:56:32 -080010518 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010519 + r);
10520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010521 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010522 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010523 mOrderedBroadcasts.remove(0);
10524 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010525 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010526 continue;
10527 }
10528 } while (r == null);
10529
10530 // Get the next receiver...
10531 int recIdx = r.nextReceiver++;
10532
10533 // Keep track of when this receiver started, and make sure there
10534 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010535 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010536 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010537 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010538
Joe Onorato8a9b2202010-02-26 18:56:32 -080010539 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010540 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010541 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010542 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010543 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010544 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010545 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 }
10547
10548 Object nextReceiver = r.receivers.get(recIdx);
10549 if (nextReceiver instanceof BroadcastFilter) {
10550 // Simple case: this is a registered receiver who gets
10551 // a direct call.
10552 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010553 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010554 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010555 + filter + ": " + r);
10556 deliverToRegisteredReceiver(r, filter, r.ordered);
10557 if (r.receiver == null || !r.ordered) {
10558 // The receiver has already finished, so schedule to
10559 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010560 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10561 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010562 r.state = BroadcastRecord.IDLE;
10563 scheduleBroadcastsLocked();
10564 }
10565 return;
10566 }
10567
10568 // Hard case: need to instantiate the receiver, possibly
10569 // starting its application process to host it.
10570
10571 ResolveInfo info =
10572 (ResolveInfo)nextReceiver;
10573
10574 boolean skip = false;
10575 int perm = checkComponentPermission(info.activityInfo.permission,
10576 r.callingPid, r.callingUid,
10577 info.activityInfo.exported
10578 ? -1 : info.activityInfo.applicationInfo.uid);
10579 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010580 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 + r.intent.toString()
10582 + " from " + r.callerPackage + " (pid=" + r.callingPid
10583 + ", uid=" + r.callingUid + ")"
10584 + " requires " + info.activityInfo.permission
10585 + " due to receiver " + info.activityInfo.packageName
10586 + "/" + info.activityInfo.name);
10587 skip = true;
10588 }
10589 if (r.callingUid != Process.SYSTEM_UID &&
10590 r.requiredPermission != null) {
10591 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010592 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010593 checkPermission(r.requiredPermission,
10594 info.activityInfo.applicationInfo.packageName);
10595 } catch (RemoteException e) {
10596 perm = PackageManager.PERMISSION_DENIED;
10597 }
10598 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010599 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010600 + r.intent + " to "
10601 + info.activityInfo.applicationInfo.packageName
10602 + " requires " + r.requiredPermission
10603 + " due to sender " + r.callerPackage
10604 + " (uid " + r.callingUid + ")");
10605 skip = true;
10606 }
10607 }
10608 if (r.curApp != null && r.curApp.crashing) {
10609 // If the target process is crashing, just skip it.
10610 skip = true;
10611 }
10612
10613 if (skip) {
10614 r.receiver = null;
10615 r.curFilter = null;
10616 r.state = BroadcastRecord.IDLE;
10617 scheduleBroadcastsLocked();
10618 return;
10619 }
10620
10621 r.state = BroadcastRecord.APP_RECEIVE;
10622 String targetProcess = info.activityInfo.processName;
10623 r.curComponent = new ComponentName(
10624 info.activityInfo.applicationInfo.packageName,
10625 info.activityInfo.name);
10626 r.curReceiver = info.activityInfo;
10627
10628 // Is this receiver's application already running?
10629 ProcessRecord app = getProcessRecordLocked(targetProcess,
10630 info.activityInfo.applicationInfo.uid);
10631 if (app != null && app.thread != null) {
10632 try {
10633 processCurBroadcastLocked(r, app);
10634 return;
10635 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010636 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010637 + r.curComponent, e);
10638 }
10639
10640 // If a dead object exception was thrown -- fall through to
10641 // restart the application.
10642 }
10643
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010644 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010645 if ((r.curApp=startProcessLocked(targetProcess,
10646 info.activityInfo.applicationInfo, true,
10647 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010648 "broadcast", r.curComponent,
10649 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10650 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010651 // Ah, this recipient is unavailable. Finish it if necessary,
10652 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010653 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010654 + info.activityInfo.applicationInfo.packageName + "/"
10655 + info.activityInfo.applicationInfo.uid + " for broadcast "
10656 + r.intent + ": process is bad");
10657 logBroadcastReceiverDiscard(r);
10658 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10659 r.resultExtras, r.resultAbort, true);
10660 scheduleBroadcastsLocked();
10661 r.state = BroadcastRecord.IDLE;
10662 return;
10663 }
10664
10665 mPendingBroadcast = r;
10666 }
10667 }
10668
10669 // =========================================================
10670 // INSTRUMENTATION
10671 // =========================================================
10672
10673 public boolean startInstrumentation(ComponentName className,
10674 String profileFile, int flags, Bundle arguments,
10675 IInstrumentationWatcher watcher) {
10676 // Refuse possible leaked file descriptors
10677 if (arguments != null && arguments.hasFileDescriptors()) {
10678 throw new IllegalArgumentException("File descriptors passed in Bundle");
10679 }
10680
10681 synchronized(this) {
10682 InstrumentationInfo ii = null;
10683 ApplicationInfo ai = null;
10684 try {
10685 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010686 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010687 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010688 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010689 } catch (PackageManager.NameNotFoundException e) {
10690 }
10691 if (ii == null) {
10692 reportStartInstrumentationFailure(watcher, className,
10693 "Unable to find instrumentation info for: " + className);
10694 return false;
10695 }
10696 if (ai == null) {
10697 reportStartInstrumentationFailure(watcher, className,
10698 "Unable to find instrumentation target package: " + ii.targetPackage);
10699 return false;
10700 }
10701
10702 int match = mContext.getPackageManager().checkSignatures(
10703 ii.targetPackage, ii.packageName);
10704 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10705 String msg = "Permission Denial: starting instrumentation "
10706 + className + " from pid="
10707 + Binder.getCallingPid()
10708 + ", uid=" + Binder.getCallingPid()
10709 + " not allowed because package " + ii.packageName
10710 + " does not have a signature matching the target "
10711 + ii.targetPackage;
10712 reportStartInstrumentationFailure(watcher, className, msg);
10713 throw new SecurityException(msg);
10714 }
10715
10716 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010717 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010718 ProcessRecord app = addAppLocked(ai);
10719 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010720 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010721 app.instrumentationProfileFile = profileFile;
10722 app.instrumentationArguments = arguments;
10723 app.instrumentationWatcher = watcher;
10724 app.instrumentationResultClass = className;
10725 Binder.restoreCallingIdentity(origId);
10726 }
10727
10728 return true;
10729 }
10730
10731 /**
10732 * Report errors that occur while attempting to start Instrumentation. Always writes the
10733 * error to the logs, but if somebody is watching, send the report there too. This enables
10734 * the "am" command to report errors with more information.
10735 *
10736 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10737 * @param cn The component name of the instrumentation.
10738 * @param report The error report.
10739 */
10740 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10741 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010742 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010743 try {
10744 if (watcher != null) {
10745 Bundle results = new Bundle();
10746 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10747 results.putString("Error", report);
10748 watcher.instrumentationStatus(cn, -1, results);
10749 }
10750 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010751 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010752 }
10753 }
10754
10755 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10756 if (app.instrumentationWatcher != null) {
10757 try {
10758 // NOTE: IInstrumentationWatcher *must* be oneway here
10759 app.instrumentationWatcher.instrumentationFinished(
10760 app.instrumentationClass,
10761 resultCode,
10762 results);
10763 } catch (RemoteException e) {
10764 }
10765 }
10766 app.instrumentationWatcher = null;
10767 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010768 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 app.instrumentationProfileFile = null;
10770 app.instrumentationArguments = null;
10771
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010772 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010773 }
10774
10775 public void finishInstrumentation(IApplicationThread target,
10776 int resultCode, Bundle results) {
10777 // Refuse possible leaked file descriptors
10778 if (results != null && results.hasFileDescriptors()) {
10779 throw new IllegalArgumentException("File descriptors passed in Intent");
10780 }
10781
10782 synchronized(this) {
10783 ProcessRecord app = getRecordForAppLocked(target);
10784 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010785 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786 return;
10787 }
10788 final long origId = Binder.clearCallingIdentity();
10789 finishInstrumentationLocked(app, resultCode, results);
10790 Binder.restoreCallingIdentity(origId);
10791 }
10792 }
10793
10794 // =========================================================
10795 // CONFIGURATION
10796 // =========================================================
10797
10798 public ConfigurationInfo getDeviceConfigurationInfo() {
10799 ConfigurationInfo config = new ConfigurationInfo();
10800 synchronized (this) {
10801 config.reqTouchScreen = mConfiguration.touchscreen;
10802 config.reqKeyboardType = mConfiguration.keyboard;
10803 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010804 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10805 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10807 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010808 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10809 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10811 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010812 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010813 }
10814 return config;
10815 }
10816
10817 public Configuration getConfiguration() {
10818 Configuration ci;
10819 synchronized(this) {
10820 ci = new Configuration(mConfiguration);
10821 }
10822 return ci;
10823 }
10824
10825 public void updateConfiguration(Configuration values) {
10826 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10827 "updateConfiguration()");
10828
10829 synchronized(this) {
10830 if (values == null && mWindowManager != null) {
10831 // sentinel: fetch the current configuration from the window manager
10832 values = mWindowManager.computeNewConfiguration();
10833 }
10834
10835 final long origId = Binder.clearCallingIdentity();
10836 updateConfigurationLocked(values, null);
10837 Binder.restoreCallingIdentity(origId);
10838 }
10839 }
10840
10841 /**
10842 * Do either or both things: (1) change the current configuration, and (2)
10843 * make sure the given activity is running with the (now) current
10844 * configuration. Returns true if the activity has been left running, or
10845 * false if <var>starting</var> is being destroyed to match the new
10846 * configuration.
10847 */
10848 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010849 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010850 int changes = 0;
10851
10852 boolean kept = true;
10853
10854 if (values != null) {
10855 Configuration newConfig = new Configuration(mConfiguration);
10856 changes = newConfig.updateFrom(values);
10857 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010858 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010859 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010860 }
10861
Doug Zongker2bec3d42009-12-04 12:52:44 -080010862 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010863
10864 if (values.locale != null) {
10865 saveLocaleLocked(values.locale,
10866 !values.locale.equals(mConfiguration.locale),
10867 values.userSetLocale);
10868 }
10869
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010870 mConfigurationSeq++;
10871 if (mConfigurationSeq <= 0) {
10872 mConfigurationSeq = 1;
10873 }
10874 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010875 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010876 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010877
10878 AttributeCache ac = AttributeCache.instance();
10879 if (ac != null) {
10880 ac.updateConfiguration(mConfiguration);
10881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010883 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10884 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10885 msg.obj = new Configuration(mConfiguration);
10886 mHandler.sendMessage(msg);
10887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010888
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010889 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10890 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 try {
10892 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010893 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010894 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010895 app.thread.scheduleConfigurationChanged(mConfiguration);
10896 }
10897 } catch (Exception e) {
10898 }
10899 }
10900 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010901 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10902 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010903 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10904 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010905 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10906 broadcastIntentLocked(null, null,
10907 new Intent(Intent.ACTION_LOCALE_CHANGED),
10908 null, null, 0, null, null,
10909 null, false, false, MY_PID, Process.SYSTEM_UID);
10910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010911 }
10912 }
10913
10914 if (changes != 0 && starting == null) {
10915 // If the configuration changed, and the caller is not already
10916 // in the process of starting an activity, then find the top
10917 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010918 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 }
10920
10921 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010922 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 if (kept) {
10924 // If this didn't result in the starting activity being
10925 // destroyed, then we need to make sure at this point that all
10926 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010927 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010929 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010930 }
10931 }
10932
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010933 if (values != null && mWindowManager != null) {
10934 mWindowManager.setNewConfiguration(mConfiguration);
10935 }
10936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010937 return kept;
10938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010939
10940 /**
10941 * Save the locale. You must be inside a synchronized (this) block.
10942 */
10943 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10944 if(isDiff) {
10945 SystemProperties.set("user.language", l.getLanguage());
10946 SystemProperties.set("user.region", l.getCountry());
10947 }
10948
10949 if(isPersist) {
10950 SystemProperties.set("persist.sys.language", l.getLanguage());
10951 SystemProperties.set("persist.sys.country", l.getCountry());
10952 SystemProperties.set("persist.sys.localevar", l.getVariant());
10953 }
10954 }
10955
10956 // =========================================================
10957 // LIFETIME MANAGEMENT
10958 // =========================================================
10959
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010960 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
10961 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010962 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010963 // This adjustment has already been computed. If we are calling
10964 // from the top, we may have already computed our adjustment with
10965 // an earlier hidden adjustment that isn't really for us... if
10966 // so, use the new hidden adjustment.
10967 if (!recursed && app.hidden) {
10968 app.curAdj = hiddenAdj;
10969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010970 return app.curAdj;
10971 }
10972
10973 if (app.thread == null) {
10974 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010975 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976 return (app.curAdj=EMPTY_APP_ADJ);
10977 }
10978
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010979 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
10980 // The max adjustment doesn't allow this app to be anything
10981 // below foreground, so it is not worth doing work for it.
10982 app.adjType = "fixed";
10983 app.adjSeq = mAdjSeq;
10984 app.curRawAdj = app.maxAdj;
10985 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
10986 return (app.curAdj=app.maxAdj);
10987 }
10988
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010989 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010990 app.adjSource = null;
10991 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010992 app.empty = false;
10993 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010994
The Android Open Source Project4df24232009-03-05 14:34:35 -080010995 // Determine the importance of the process, starting with most
10996 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010998 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010999 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011000 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 // The last app on the list is the foreground app.
11002 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011003 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011004 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011005 } else if (app.instrumentationClass != null) {
11006 // Don't want to kill running instrumentation.
11007 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011008 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011009 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011010 } else if (app.persistentActivities > 0) {
11011 // Special persistent activities... shouldn't be used these days.
11012 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011013 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011014 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011015 } else if (app.curReceiver != null ||
11016 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11017 // An app that is currently receiving a broadcast also
11018 // counts as being in the foreground.
11019 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011020 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011021 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011022 } else if (app.executingServices.size() > 0) {
11023 // An app that is currently executing a service callback also
11024 // counts as being in the foreground.
11025 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011026 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011027 app.adjType = "exec-service";
11028 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011030 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011031 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011032 app.adjType = "foreground-service";
11033 } else if (app.forcingToForeground != null) {
11034 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011035 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011036 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011037 app.adjType = "force-foreground";
11038 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011039 } else if (app == mHeavyWeightProcess) {
11040 // We don't want to kill the current heavy-weight process.
11041 adj = HEAVY_WEIGHT_APP_ADJ;
11042 schedGroup = Process.THREAD_GROUP_DEFAULT;
11043 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011044 } else if (app == mHomeProcess) {
11045 // This process is hosting what we currently consider to be the
11046 // home app, so we don't want to let it go into the background.
11047 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011048 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011049 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011050 } else if ((N=app.activities.size()) != 0) {
11051 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011052 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011054 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011055 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011056 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011058 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011059 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011060 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011061 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011062 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011063 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 break;
11065 }
11066 }
11067 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011068 // A very not-needed process. If this is lower in the lru list,
11069 // we will push it in to the empty bucket.
11070 app.hidden = true;
11071 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011072 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011073 adj = hiddenAdj;
11074 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 }
11076
Joe Onorato8a9b2202010-02-26 18:56:32 -080011077 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011078
The Android Open Source Project4df24232009-03-05 14:34:35 -080011079 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 // there are applications dependent on our services or providers, but
11081 // this gives us a baseline and makes sure we don't get into an
11082 // infinite recursion.
11083 app.adjSeq = mAdjSeq;
11084 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011085
Christopher Tate6fa95972009-06-05 18:43:55 -070011086 if (mBackupTarget != null && app == mBackupTarget.app) {
11087 // If possible we want to avoid killing apps while they're being backed up
11088 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011089 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011090 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011091 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011092 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011093 }
11094 }
11095
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011096 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11097 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011098 final long now = SystemClock.uptimeMillis();
11099 // This process is more important if the top activity is
11100 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011101 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011102 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011103 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 if (s.startRequested) {
11105 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11106 // This service has seen some activity within
11107 // recent memory, so we will keep its process ahead
11108 // of the background processes.
11109 if (adj > SECONDARY_SERVER_ADJ) {
11110 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011111 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011112 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 }
11114 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011115 // If we have let the service slide into the background
11116 // state, still have some text describing what it is doing
11117 // even though the service no longer has an impact.
11118 if (adj > SECONDARY_SERVER_ADJ) {
11119 app.adjType = "started-bg-services";
11120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011121 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011122 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11123 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011124 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011125 = s.connections.values().iterator();
11126 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011127 ArrayList<ConnectionRecord> clist = kt.next();
11128 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11129 // XXX should compute this based on the max of
11130 // all connected clients.
11131 ConnectionRecord cr = clist.get(i);
11132 if (cr.binding.client == app) {
11133 // Binding to ourself is not interesting.
11134 continue;
11135 }
11136 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11137 ProcessRecord client = cr.binding.client;
11138 int myHiddenAdj = hiddenAdj;
11139 if (myHiddenAdj > client.hiddenAdj) {
11140 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11141 myHiddenAdj = client.hiddenAdj;
11142 } else {
11143 myHiddenAdj = VISIBLE_APP_ADJ;
11144 }
11145 }
11146 int clientAdj = computeOomAdjLocked(
11147 client, myHiddenAdj, TOP_APP, true);
11148 if (adj > clientAdj) {
11149 adj = clientAdj >= VISIBLE_APP_ADJ
11150 ? clientAdj : VISIBLE_APP_ADJ;
11151 if (!client.hidden) {
11152 app.hidden = false;
11153 }
11154 app.adjType = "service";
11155 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11156 .REASON_SERVICE_IN_USE;
11157 app.adjSource = cr.binding.client;
11158 app.adjTarget = s.name;
11159 }
11160 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11161 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11162 schedGroup = Process.THREAD_GROUP_DEFAULT;
11163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 }
11165 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011166 ActivityRecord a = cr.activity;
11167 //if (a != null) {
11168 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11169 //}
11170 if (a != null && adj > FOREGROUND_APP_ADJ &&
11171 (a.state == ActivityState.RESUMED
11172 || a.state == ActivityState.PAUSING)) {
11173 adj = FOREGROUND_APP_ADJ;
11174 schedGroup = Process.THREAD_GROUP_DEFAULT;
11175 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011176 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011177 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11178 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011179 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011180 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011182 }
11183 }
11184 }
11185 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011186
11187 // Finally, f this process has active services running in it, we
11188 // would like to avoid killing it unless it would prevent the current
11189 // application from running. By default we put the process in
11190 // with the rest of the background processes; as we scan through
11191 // its services we may bump it up from there.
11192 if (adj > hiddenAdj) {
11193 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011194 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011195 app.adjType = "bg-services";
11196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011197 }
11198
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011199 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11200 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011201 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011202 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11203 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011204 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011205 if (cpr.clients.size() != 0) {
11206 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11207 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11208 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011209 if (client == app) {
11210 // Being our own client is not interesting.
11211 continue;
11212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011213 int myHiddenAdj = hiddenAdj;
11214 if (myHiddenAdj > client.hiddenAdj) {
11215 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11216 myHiddenAdj = client.hiddenAdj;
11217 } else {
11218 myHiddenAdj = FOREGROUND_APP_ADJ;
11219 }
11220 }
11221 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011222 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011223 if (adj > clientAdj) {
11224 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011225 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011226 if (!client.hidden) {
11227 app.hidden = false;
11228 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011229 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011230 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11231 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011232 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011233 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011234 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011235 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11236 schedGroup = Process.THREAD_GROUP_DEFAULT;
11237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011238 }
11239 }
11240 // If the provider has external (non-framework) process
11241 // dependencies, ensure that its adjustment is at least
11242 // FOREGROUND_APP_ADJ.
11243 if (cpr.externals != 0) {
11244 if (adj > FOREGROUND_APP_ADJ) {
11245 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011246 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011247 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011248 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011249 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250 }
11251 }
11252 }
11253 }
11254
11255 app.curRawAdj = adj;
11256
Joe Onorato8a9b2202010-02-26 18:56:32 -080011257 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011258 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11259 if (adj > app.maxAdj) {
11260 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011261 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011262 schedGroup = Process.THREAD_GROUP_DEFAULT;
11263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 }
11265
11266 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011267 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 return adj;
11270 }
11271
11272 /**
11273 * Ask a given process to GC right now.
11274 */
11275 final void performAppGcLocked(ProcessRecord app) {
11276 try {
11277 app.lastRequestedGc = SystemClock.uptimeMillis();
11278 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011279 if (app.reportLowMemory) {
11280 app.reportLowMemory = false;
11281 app.thread.scheduleLowMemory();
11282 } else {
11283 app.thread.processInBackground();
11284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 }
11286 } catch (Exception e) {
11287 // whatever.
11288 }
11289 }
11290
11291 /**
11292 * Returns true if things are idle enough to perform GCs.
11293 */
Josh Bartel7f208742010-02-25 11:01:44 -060011294 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 return mParallelBroadcasts.size() == 0
11296 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011297 && (mSleeping || (mMainStack.mResumedActivity != null &&
11298 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011299 }
11300
11301 /**
11302 * Perform GCs on all processes that are waiting for it, but only
11303 * if things are idle.
11304 */
11305 final void performAppGcsLocked() {
11306 final int N = mProcessesToGc.size();
11307 if (N <= 0) {
11308 return;
11309 }
Josh Bartel7f208742010-02-25 11:01:44 -060011310 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011311 while (mProcessesToGc.size() > 0) {
11312 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011313 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011314 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11315 <= SystemClock.uptimeMillis()) {
11316 // To avoid spamming the system, we will GC processes one
11317 // at a time, waiting a few seconds between each.
11318 performAppGcLocked(proc);
11319 scheduleAppGcsLocked();
11320 return;
11321 } else {
11322 // It hasn't been long enough since we last GCed this
11323 // process... put it in the list to wait for its time.
11324 addProcessToGcListLocked(proc);
11325 break;
11326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011327 }
11328 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011329
11330 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011331 }
11332 }
11333
11334 /**
11335 * If all looks good, perform GCs on all processes waiting for them.
11336 */
11337 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011338 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 performAppGcsLocked();
11340 return;
11341 }
11342 // Still not idle, wait some more.
11343 scheduleAppGcsLocked();
11344 }
11345
11346 /**
11347 * Schedule the execution of all pending app GCs.
11348 */
11349 final void scheduleAppGcsLocked() {
11350 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011351
11352 if (mProcessesToGc.size() > 0) {
11353 // Schedule a GC for the time to the next process.
11354 ProcessRecord proc = mProcessesToGc.get(0);
11355 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11356
11357 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11358 long now = SystemClock.uptimeMillis();
11359 if (when < (now+GC_TIMEOUT)) {
11360 when = now + GC_TIMEOUT;
11361 }
11362 mHandler.sendMessageAtTime(msg, when);
11363 }
11364 }
11365
11366 /**
11367 * Add a process to the array of processes waiting to be GCed. Keeps the
11368 * list in sorted order by the last GC time. The process can't already be
11369 * on the list.
11370 */
11371 final void addProcessToGcListLocked(ProcessRecord proc) {
11372 boolean added = false;
11373 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11374 if (mProcessesToGc.get(i).lastRequestedGc <
11375 proc.lastRequestedGc) {
11376 added = true;
11377 mProcessesToGc.add(i+1, proc);
11378 break;
11379 }
11380 }
11381 if (!added) {
11382 mProcessesToGc.add(0, proc);
11383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 }
11385
11386 /**
11387 * Set up to ask a process to GC itself. This will either do it
11388 * immediately, or put it on the list of processes to gc the next
11389 * time things are idle.
11390 */
11391 final void scheduleAppGcLocked(ProcessRecord app) {
11392 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011393 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011394 return;
11395 }
11396 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011397 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011398 scheduleAppGcsLocked();
11399 }
11400 }
11401
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011402 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11403 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11404 if (mLastWakeLockCheckTime == 0) {
11405 doKills = false;
11406 }
11407 if (stats.isScreenOn()) {
11408 doKills = false;
11409 }
11410 final long curRealtime = SystemClock.elapsedRealtime();
11411 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11412 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011413 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011414 doKills = false;
11415 }
11416 int i = mLruProcesses.size();
11417 while (i > 0) {
11418 i--;
11419 ProcessRecord app = mLruProcesses.get(i);
11420 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11421 long wtime;
11422 synchronized (stats) {
11423 wtime = stats.getProcessWakeTime(app.info.uid,
11424 app.pid, curRealtime);
11425 }
11426 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011427 if (false) {
11428 StringBuilder sb = new StringBuilder(128);
11429 sb.append("Wake for ");
11430 app.toShortString(sb);
11431 sb.append(": over ");
11432 TimeUtils.formatDuration(timeSince, sb);
11433 sb.append(" used ");
11434 TimeUtils.formatDuration(timeUsed, sb);
11435 sb.append(" (");
11436 sb.append((timeUsed*100)/timeSince);
11437 sb.append("%)");
11438 Slog.i(TAG, sb.toString());
11439 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011440 // If a process has held a wake lock for more
11441 // than 50% of the time during this period,
11442 // that sounds pad. Kill!
11443 if (doKills && timeSince > 0
11444 && ((timeUsed*100)/timeSince) >= 50) {
11445 Slog.i(TAG, "Excessive wake lock in " + app.processName
11446 + " (pid " + app.pid + "): held " + timeUsed
11447 + " during " + timeSince);
11448 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11449 app.processName, app.setAdj, "excessive wake lock");
11450 Process.killProcessQuiet(app.pid);
11451 } else {
11452 app.lastWakeTime = wtime;
11453 }
11454 }
11455 }
11456 }
11457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011458 private final boolean updateOomAdjLocked(
11459 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11460 app.hiddenAdj = hiddenAdj;
11461
11462 if (app.thread == null) {
11463 return true;
11464 }
11465
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011466 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011468 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011469 if (app.curRawAdj != app.setRawAdj) {
11470 if (app.curRawAdj > FOREGROUND_APP_ADJ
11471 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11472 // If this app is transitioning from foreground to
11473 // non-foreground, have it do a gc.
11474 scheduleAppGcLocked(app);
11475 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11476 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11477 // Likewise do a gc when an app is moving in to the
11478 // background (such as a service stopping).
11479 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011480 // And note its current wake lock time.
11481 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11482 synchronized (stats) {
11483 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11484 app.pid, SystemClock.elapsedRealtime());
11485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011486 }
11487 app.setRawAdj = app.curRawAdj;
11488 }
11489 if (adj != app.setAdj) {
11490 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011491 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011492 TAG, "Set app " + app.processName +
11493 " oom adj to " + adj);
11494 app.setAdj = adj;
11495 } else {
11496 return false;
11497 }
11498 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011499 if (app.setSchedGroup != app.curSchedGroup) {
11500 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011501 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011502 "Setting process group of " + app.processName
11503 + " to " + app.curSchedGroup);
11504 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011505 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011506 try {
11507 Process.setProcessGroup(app.pid, app.curSchedGroup);
11508 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011509 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011510 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011511 e.printStackTrace();
11512 } finally {
11513 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011514 }
11515 }
11516 if (false) {
11517 if (app.thread != null) {
11518 try {
11519 app.thread.setSchedulingGroup(app.curSchedGroup);
11520 } catch (RemoteException e) {
11521 }
11522 }
11523 }
11524 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011525 }
11526
11527 return true;
11528 }
11529
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011530 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011531 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011533 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011535 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 }
11537 }
11538 return resumedActivity;
11539 }
11540
11541 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011542 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011543 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11544 int curAdj = app.curAdj;
11545 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11546 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11547
11548 mAdjSeq++;
11549
11550 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11551 if (res) {
11552 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11553 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11554 if (nowHidden != wasHidden) {
11555 // Changed to/from hidden state, so apps after it in the LRU
11556 // list may also be changed.
11557 updateOomAdjLocked();
11558 }
11559 }
11560 return res;
11561 }
11562
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011563 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011564 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011565 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11567
11568 if (false) {
11569 RuntimeException e = new RuntimeException();
11570 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011571 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 }
11573
11574 mAdjSeq++;
11575
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011576 // Let's determine how many processes we have running vs.
11577 // how many slots we have for background processes; we may want
11578 // to put multiple processes in a slot of there are enough of
11579 // them.
11580 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11581 int factor = (mLruProcesses.size()-4)/numSlots;
11582 if (factor < 1) factor = 1;
11583 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011584 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011586 // First try updating the OOM adjustment for each of the
11587 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011588 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011589 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11590 while (i > 0) {
11591 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011592 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011593 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011595 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011596 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011597 step++;
11598 if (step >= factor) {
11599 step = 0;
11600 curHiddenAdj++;
11601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011603 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011604 if (!app.killedBackground) {
11605 numHidden++;
11606 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011607 Slog.i(TAG, "No longer want " + app.processName
11608 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011609 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11610 app.processName, app.setAdj, "too many background");
11611 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011612 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011613 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011614 }
11615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 } else {
11617 didOomAdj = false;
11618 }
11619 }
11620
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011621 // If we return false, we will fall back on killing processes to
11622 // have a fixed limit. Do this if a limit has been requested; else
11623 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011624 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11625 }
11626
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011627 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 synchronized (this) {
11629 int i;
11630
11631 // First remove any unused application processes whose package
11632 // has been removed.
11633 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11634 final ProcessRecord app = mRemovedProcesses.get(i);
11635 if (app.activities.size() == 0
11636 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011637 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011638 TAG, "Exiting empty application process "
11639 + app.processName + " ("
11640 + (app.thread != null ? app.thread.asBinder() : null)
11641 + ")\n");
11642 if (app.pid > 0 && app.pid != MY_PID) {
11643 Process.killProcess(app.pid);
11644 } else {
11645 try {
11646 app.thread.scheduleExit();
11647 } catch (Exception e) {
11648 // Ignore exceptions.
11649 }
11650 }
11651 cleanUpApplicationRecordLocked(app, false, -1);
11652 mRemovedProcesses.remove(i);
11653
11654 if (app.persistent) {
11655 if (app.persistent) {
11656 addAppLocked(app.info);
11657 }
11658 }
11659 }
11660 }
11661
11662 // Now try updating the OOM adjustment for each of the
11663 // application processes based on their current state.
11664 // If the setOomAdj() API is not supported, then go with our
11665 // back-up plan...
11666 if (!updateOomAdjLocked()) {
11667
11668 // Count how many processes are running services.
11669 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011670 for (i=mLruProcesses.size()-1; i>=0; i--) {
11671 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672
11673 if (app.persistent || app.services.size() != 0
11674 || app.curReceiver != null
11675 || app.persistentActivities > 0) {
11676 // Don't count processes holding services against our
11677 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011678 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011679 TAG, "Not trimming app " + app + " with services: "
11680 + app.services);
11681 numServiceProcs++;
11682 }
11683 }
11684
11685 int curMaxProcs = mProcessLimit;
11686 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11687 if (mAlwaysFinishActivities) {
11688 curMaxProcs = 1;
11689 }
11690 curMaxProcs += numServiceProcs;
11691
11692 // Quit as many processes as we can to get down to the desired
11693 // process count. First remove any processes that no longer
11694 // have activites running in them.
11695 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011696 i<mLruProcesses.size()
11697 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011698 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011699 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011700 // Quit an application only if it is not currently
11701 // running any activities.
11702 if (!app.persistent && app.activities.size() == 0
11703 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011704 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011705 TAG, "Exiting empty application process "
11706 + app.processName + " ("
11707 + (app.thread != null ? app.thread.asBinder() : null)
11708 + ")\n");
11709 if (app.pid > 0 && app.pid != MY_PID) {
11710 Process.killProcess(app.pid);
11711 } else {
11712 try {
11713 app.thread.scheduleExit();
11714 } catch (Exception e) {
11715 // Ignore exceptions.
11716 }
11717 }
11718 // todo: For now we assume the application is not buggy
11719 // or evil, and will quit as a result of our request.
11720 // Eventually we need to drive this off of the death
11721 // notification, and kill the process if it takes too long.
11722 cleanUpApplicationRecordLocked(app, false, i);
11723 i--;
11724 }
11725 }
11726
11727 // If we still have too many processes, now from the least
11728 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011729 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011730 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 " of " + curMaxProcs + " processes");
11732 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011733 i<mLruProcesses.size()
11734 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011735 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011736 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 // Quit the application only if we have a state saved for
11738 // all of its activities.
11739 boolean canQuit = !app.persistent && app.curReceiver == null
11740 && app.services.size() == 0
11741 && app.persistentActivities == 0;
11742 int NUMA = app.activities.size();
11743 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011744 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011745 TAG, "Looking to quit " + app.processName);
11746 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011747 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011748 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011749 TAG, " " + r.intent.getComponent().flattenToShortString()
11750 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11751 canQuit = (r.haveState || !r.stateNotNeeded)
11752 && !r.visible && r.stopped;
11753 }
11754 if (canQuit) {
11755 // Finish all of the activities, and then the app itself.
11756 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011757 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011758 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011759 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011760 }
11761 r.resultTo = null;
11762 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011763 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011764 + app.processName + " ("
11765 + (app.thread != null ? app.thread.asBinder() : null)
11766 + ")\n");
11767 if (app.pid > 0 && app.pid != MY_PID) {
11768 Process.killProcess(app.pid);
11769 } else {
11770 try {
11771 app.thread.scheduleExit();
11772 } catch (Exception e) {
11773 // Ignore exceptions.
11774 }
11775 }
11776 // todo: For now we assume the application is not buggy
11777 // or evil, and will quit as a result of our request.
11778 // Eventually we need to drive this off of the death
11779 // notification, and kill the process if it takes too long.
11780 cleanUpApplicationRecordLocked(app, false, i);
11781 i--;
11782 //dump();
11783 }
11784 }
11785
11786 }
11787
11788 int curMaxActivities = MAX_ACTIVITIES;
11789 if (mAlwaysFinishActivities) {
11790 curMaxActivities = 1;
11791 }
11792
11793 // Finally, if there are too many activities now running, try to
11794 // finish as many as we can to get back down to the limit.
11795 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011796 i<mMainStack.mLRUActivities.size()
11797 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011799 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011800 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011801
11802 // We can finish this one if we have its icicle saved and
11803 // it is not persistent.
11804 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11805 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011806 final int origSize = mMainStack.mLRUActivities.size();
11807 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808
11809 // This will remove it from the LRU list, so keep
11810 // our index at the same value. Note that this check to
11811 // see if the size changes is just paranoia -- if
11812 // something unexpected happens, we don't want to end up
11813 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011814 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011815 i--;
11816 }
11817 }
11818 }
11819 }
11820 }
11821
11822 /** This method sends the specified signal to each of the persistent apps */
11823 public void signalPersistentProcesses(int sig) throws RemoteException {
11824 if (sig != Process.SIGNAL_USR1) {
11825 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11826 }
11827
11828 synchronized (this) {
11829 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11830 != PackageManager.PERMISSION_GRANTED) {
11831 throw new SecurityException("Requires permission "
11832 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11833 }
11834
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011835 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11836 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011837 if (r.thread != null && r.persistent) {
11838 Process.sendSignal(r.pid, sig);
11839 }
11840 }
11841 }
11842 }
11843
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011844 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011845 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011846
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011847 try {
11848 synchronized (this) {
11849 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11850 // its own permission.
11851 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11852 != PackageManager.PERMISSION_GRANTED) {
11853 throw new SecurityException("Requires permission "
11854 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011855 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011856
11857 if (start && fd == null) {
11858 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011859 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011860
11861 ProcessRecord proc = null;
11862 try {
11863 int pid = Integer.parseInt(process);
11864 synchronized (mPidsSelfLocked) {
11865 proc = mPidsSelfLocked.get(pid);
11866 }
11867 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011868 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011869
11870 if (proc == null) {
11871 HashMap<String, SparseArray<ProcessRecord>> all
11872 = mProcessNames.getMap();
11873 SparseArray<ProcessRecord> procs = all.get(process);
11874 if (procs != null && procs.size() > 0) {
11875 proc = procs.valueAt(0);
11876 }
11877 }
11878
11879 if (proc == null || proc.thread == null) {
11880 throw new IllegalArgumentException("Unknown process: " + process);
11881 }
11882
11883 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11884 if (isSecure) {
11885 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11886 throw new SecurityException("Process not debuggable: " + proc);
11887 }
11888 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011889
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011890 proc.thread.profilerControl(start, path, fd);
11891 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011892 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011893 }
11894 } catch (RemoteException e) {
11895 throw new IllegalStateException("Process disappeared");
11896 } finally {
11897 if (fd != null) {
11898 try {
11899 fd.close();
11900 } catch (IOException e) {
11901 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011902 }
11903 }
11904 }
11905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011906 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11907 public void monitor() {
11908 synchronized (this) { }
11909 }
11910}