blob: 30dc5ea84ec3b8d7479bc7611ec52f270a5c5fe6 [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) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001358 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1359 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1360 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 }
1362 }
1363 }
1364
1365 private ActivityManagerService() {
1366 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1367 if (v != null && Integer.getInteger(v) != 0) {
1368 mSimpleProcessManagement = true;
1369 }
1370 v = System.getenv("ANDROID_DEBUG_APP");
1371 if (v != null) {
1372 mSimpleProcessManagement = true;
1373 }
1374
Joe Onorato8a9b2202010-02-26 18:56:32 -08001375 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 File dataDir = Environment.getDataDirectory();
1378 File systemDir = new File(dataDir, "system");
1379 systemDir.mkdirs();
1380 mBatteryStatsService = new BatteryStatsService(new File(
1381 systemDir, "batterystats.bin").toString());
1382 mBatteryStatsService.getActiveStatistics().readLocked();
1383 mBatteryStatsService.getActiveStatistics().writeLocked();
1384
1385 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001386 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387
Jack Palevichb90d28c2009-07-22 15:35:24 -07001388 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1389 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1390
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001391 mConfiguration.setToDefaults();
1392 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 mProcessStats.init();
1394
1395 // Add ourself to the Watchdog monitors.
1396 Watchdog.getInstance().addMonitor(this);
1397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 mProcessStatsThread = new Thread("ProcessStats") {
1399 public void run() {
1400 while (true) {
1401 try {
1402 try {
1403 synchronized(this) {
1404 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001405 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001407 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 // + ", write delay=" + nextWriteDelay);
1409 if (nextWriteDelay < nextCpuDelay) {
1410 nextCpuDelay = nextWriteDelay;
1411 }
1412 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001413 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 this.wait(nextCpuDelay);
1415 }
1416 }
1417 } catch (InterruptedException e) {
1418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 updateCpuStatsNow();
1420 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001421 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422 }
1423 }
1424 }
1425 };
1426 mProcessStatsThread.start();
1427 }
1428
1429 @Override
1430 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1431 throws RemoteException {
1432 try {
1433 return super.onTransact(code, data, reply, flags);
1434 } catch (RuntimeException e) {
1435 // The activity manager only throws security exceptions, so let's
1436 // log all others.
1437 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001438 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 }
1440 throw e;
1441 }
1442 }
1443
1444 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001445 final long now = SystemClock.uptimeMillis();
1446 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1447 return;
1448 }
1449 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1450 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 mProcessStatsThread.notify();
1452 }
1453 }
1454 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 void updateCpuStatsNow() {
1457 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001458 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 final long now = SystemClock.uptimeMillis();
1460 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001463 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1464 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 haveNewCpuStats = true;
1466 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001467 //Slog.i(TAG, mProcessStats.printCurrentState());
1468 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 // + mProcessStats.getTotalCpuPercent() + "%");
1470
Joe Onorato8a9b2202010-02-26 18:56:32 -08001471 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 if ("true".equals(SystemProperties.get("events.cpu"))) {
1473 int user = mProcessStats.getLastUserTime();
1474 int system = mProcessStats.getLastSystemTime();
1475 int iowait = mProcessStats.getLastIoWaitTime();
1476 int irq = mProcessStats.getLastIrqTime();
1477 int softIrq = mProcessStats.getLastSoftIrqTime();
1478 int idle = mProcessStats.getLastIdleTime();
1479
1480 int total = user + system + iowait + irq + softIrq + idle;
1481 if (total == 0) total = 1;
1482
Doug Zongker2bec3d42009-12-04 12:52:44 -08001483 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 ((user+system+iowait+irq+softIrq) * 100) / total,
1485 (user * 100) / total,
1486 (system * 100) / total,
1487 (iowait * 100) / total,
1488 (irq * 100) / total,
1489 (softIrq * 100) / total);
1490 }
1491 }
1492
Amith Yamasanie43530a2009-08-21 13:11:37 -07001493 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001494 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001495 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 synchronized(mPidsSelfLocked) {
1497 if (haveNewCpuStats) {
1498 if (mBatteryStatsService.isOnBattery()) {
1499 final int N = mProcessStats.countWorkingStats();
1500 for (int i=0; i<N; i++) {
1501 ProcessStats.Stats st
1502 = mProcessStats.getWorkingStats(i);
1503 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1504 if (pr != null) {
1505 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1506 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001507 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001508 } else {
1509 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001510 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001511 if (ps != null) {
1512 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001513 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001514 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 }
1516 }
1517 }
1518 }
1519 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1522 mLastWriteTime = now;
1523 mBatteryStatsService.getActiveStatistics().writeLocked();
1524 }
1525 }
1526 }
1527 }
1528
1529 /**
1530 * Initialize the application bind args. These are passed to each
1531 * process when the bindApplication() IPC is sent to the process. They're
1532 * lazily setup to make sure the services are running when they're asked for.
1533 */
1534 private HashMap<String, IBinder> getCommonServicesLocked() {
1535 if (mAppBindArgs == null) {
1536 mAppBindArgs = new HashMap<String, IBinder>();
1537
1538 // Setup the application init args
1539 mAppBindArgs.put("package", ServiceManager.getService("package"));
1540 mAppBindArgs.put("window", ServiceManager.getService("window"));
1541 mAppBindArgs.put(Context.ALARM_SERVICE,
1542 ServiceManager.getService(Context.ALARM_SERVICE));
1543 }
1544 return mAppBindArgs;
1545 }
1546
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001547 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 if (mFocusedActivity != r) {
1549 mFocusedActivity = r;
1550 mWindowManager.setFocusedApp(r, true);
1551 }
1552 }
1553
Dianne Hackborn906497c2010-05-10 15:57:38 -07001554 private final void updateLruProcessInternalLocked(ProcessRecord app,
1555 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001557 int lrui = mLruProcesses.indexOf(app);
1558 if (lrui >= 0) mLruProcesses.remove(lrui);
1559
1560 int i = mLruProcesses.size()-1;
1561 int skipTop = 0;
1562
Dianne Hackborn906497c2010-05-10 15:57:38 -07001563 app.lruSeq = mLruSeq;
1564
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001565 // compute the new weight for this process.
1566 if (updateActivityTime) {
1567 app.lastActivityTime = SystemClock.uptimeMillis();
1568 }
1569 if (app.activities.size() > 0) {
1570 // If this process has activities, we more strongly want to keep
1571 // it around.
1572 app.lruWeight = app.lastActivityTime;
1573 } else if (app.pubProviders.size() > 0) {
1574 // If this process contains content providers, we want to keep
1575 // it a little more strongly.
1576 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1577 // Also don't let it kick out the first few "real" hidden processes.
1578 skipTop = MIN_HIDDEN_APPS;
1579 } else {
1580 // If this process doesn't have activities, we less strongly
1581 // want to keep it around, and generally want to avoid getting
1582 // in front of any very recently used activities.
1583 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1584 // Also don't let it kick out the first few "real" hidden processes.
1585 skipTop = MIN_HIDDEN_APPS;
1586 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001587
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001588 while (i >= 0) {
1589 ProcessRecord p = mLruProcesses.get(i);
1590 // If this app shouldn't be in front of the first N background
1591 // apps, then skip over that many that are currently hidden.
1592 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1593 skipTop--;
1594 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001595 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001596 mLruProcesses.add(i+1, app);
1597 break;
1598 }
1599 i--;
1600 }
1601 if (i < 0) {
1602 mLruProcesses.add(0, app);
1603 }
1604
Dianne Hackborn906497c2010-05-10 15:57:38 -07001605 // If the app is currently using a content provider or service,
1606 // bump those processes as well.
1607 if (app.connections.size() > 0) {
1608 for (ConnectionRecord cr : app.connections) {
1609 if (cr.binding != null && cr.binding.service != null
1610 && cr.binding.service.app != null
1611 && cr.binding.service.app.lruSeq != mLruSeq) {
1612 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1613 updateActivityTime, i+1);
1614 }
1615 }
1616 }
1617 if (app.conProviders.size() > 0) {
1618 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1619 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1620 updateLruProcessInternalLocked(cpr.app, oomAdj,
1621 updateActivityTime, i+1);
1622 }
1623 }
1624 }
1625
Joe Onorato8a9b2202010-02-26 18:56:32 -08001626 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 if (oomAdj) {
1628 updateOomAdjLocked();
1629 }
1630 }
1631
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001632 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001633 boolean oomAdj, boolean updateActivityTime) {
1634 mLruSeq++;
1635 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1636 }
1637
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001638 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 String processName, int uid) {
1640 if (uid == Process.SYSTEM_UID) {
1641 // The system gets to run in any process. If there are multiple
1642 // processes with the same uid, just pick the first (this
1643 // should never happen).
1644 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1645 processName);
1646 return procs != null ? procs.valueAt(0) : null;
1647 }
1648 ProcessRecord proc = mProcessNames.get(processName, uid);
1649 return proc;
1650 }
1651
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001652 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001653 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001654 try {
1655 if (pm.performDexOpt(packageName)) {
1656 mDidDexOpt = true;
1657 }
1658 } catch (RemoteException e) {
1659 }
1660 }
1661
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001662 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 int transit = mWindowManager.getPendingAppTransition();
1664 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1665 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1666 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1667 }
1668
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001669 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001671 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1673 // We don't have to do anything more if:
1674 // (1) There is an existing application record; and
1675 // (2) The caller doesn't think it is dead, OR there is no thread
1676 // object attached to it so we know it couldn't have crashed; and
1677 // (3) There is a pid assigned to it, so it is either starting or
1678 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001679 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 + " app=" + app + " knownToBeDead=" + knownToBeDead
1681 + " thread=" + (app != null ? app.thread : null)
1682 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001683 if (app != null && app.pid > 0) {
1684 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001685 // We already have the app running, or are waiting for it to
1686 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001687 return app;
1688 } else {
1689 // An application record is attached to a previous process,
1690 // clean it up now.
1691 handleAppDiedLocked(app, true);
1692 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 String hostingNameStr = hostingName != null
1696 ? hostingName.flattenToShortString() : null;
1697
1698 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1699 // If we are in the background, then check to see if this process
1700 // is bad. If so, we will just silently fail.
1701 if (mBadProcesses.get(info.processName, info.uid) != null) {
1702 return null;
1703 }
1704 } else {
1705 // When the user is explicitly starting a process, then clear its
1706 // crash count so that we won't make it bad until they see at
1707 // least one crash dialog again, and make the process good again
1708 // if it had been bad.
1709 mProcessCrashTimes.remove(info.processName, info.uid);
1710 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001711 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 info.processName);
1713 mBadProcesses.remove(info.processName, info.uid);
1714 if (app != null) {
1715 app.bad = false;
1716 }
1717 }
1718 }
1719
1720 if (app == null) {
1721 app = newProcessRecordLocked(null, info, processName);
1722 mProcessNames.put(processName, info.uid, app);
1723 } else {
1724 // If this is a new package in the process, add the package to the list
1725 app.addPackage(info.packageName);
1726 }
1727
1728 // If the system is not ready yet, then hold off on starting this
1729 // process until it is.
1730 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001731 && !isAllowedWhileBooting(info)
1732 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 if (!mProcessesOnHold.contains(app)) {
1734 mProcessesOnHold.add(app);
1735 }
1736 return app;
1737 }
1738
1739 startProcessLocked(app, hostingType, hostingNameStr);
1740 return (app.pid != 0) ? app : null;
1741 }
1742
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001743 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1744 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1745 }
1746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 private final void startProcessLocked(ProcessRecord app,
1748 String hostingType, String hostingNameStr) {
1749 if (app.pid > 0 && app.pid != MY_PID) {
1750 synchronized (mPidsSelfLocked) {
1751 mPidsSelfLocked.remove(app.pid);
1752 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1753 }
1754 app.pid = 0;
1755 }
1756
1757 mProcessesOnHold.remove(app);
1758
1759 updateCpuStats();
1760
1761 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1762 mProcDeaths[0] = 0;
1763
1764 try {
1765 int uid = app.info.uid;
1766 int[] gids = null;
1767 try {
1768 gids = mContext.getPackageManager().getPackageGids(
1769 app.info.packageName);
1770 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001771 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 }
1773 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1774 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1775 && mTopComponent != null
1776 && app.processName.equals(mTopComponent.getPackageName())) {
1777 uid = 0;
1778 }
1779 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1780 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1781 uid = 0;
1782 }
1783 }
1784 int debugFlags = 0;
1785 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1786 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1787 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001788 // Run the app in safe mode if its manifest requests so or the
1789 // system is booted in safe mode.
1790 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1791 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001792 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1795 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1796 }
1797 if ("1".equals(SystemProperties.get("debug.assert"))) {
1798 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1799 }
1800 int pid = Process.start("android.app.ActivityThread",
1801 mSimpleProcessManagement ? app.processName : null, uid, uid,
1802 gids, debugFlags, null);
1803 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1804 synchronized (bs) {
1805 if (bs.isOnBattery()) {
1806 app.batteryStats.incStartsLocked();
1807 }
1808 }
1809
Doug Zongker2bec3d42009-12-04 12:52:44 -08001810 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 app.processName, hostingType,
1812 hostingNameStr != null ? hostingNameStr : "");
1813
1814 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001815 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 }
1817
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001818 StringBuilder buf = mStringBuilder;
1819 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 buf.append("Start proc ");
1821 buf.append(app.processName);
1822 buf.append(" for ");
1823 buf.append(hostingType);
1824 if (hostingNameStr != null) {
1825 buf.append(" ");
1826 buf.append(hostingNameStr);
1827 }
1828 buf.append(": pid=");
1829 buf.append(pid);
1830 buf.append(" uid=");
1831 buf.append(uid);
1832 buf.append(" gids={");
1833 if (gids != null) {
1834 for (int gi=0; gi<gids.length; gi++) {
1835 if (gi != 0) buf.append(", ");
1836 buf.append(gids[gi]);
1837
1838 }
1839 }
1840 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001841 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842 if (pid == 0 || pid == MY_PID) {
1843 // Processes are being emulated with threads.
1844 app.pid = MY_PID;
1845 app.removed = false;
1846 mStartingProcesses.add(app);
1847 } else if (pid > 0) {
1848 app.pid = pid;
1849 app.removed = false;
1850 synchronized (mPidsSelfLocked) {
1851 this.mPidsSelfLocked.put(pid, app);
1852 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1853 msg.obj = app;
1854 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1855 }
1856 } else {
1857 app.pid = 0;
1858 RuntimeException e = new RuntimeException(
1859 "Failure starting process " + app.processName
1860 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001861 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 }
1863 } catch (RuntimeException e) {
1864 // XXX do better error recovery.
1865 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001866 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 }
1868 }
1869
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001870 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 if (resumed) {
1872 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1873 } else {
1874 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1875 }
1876 }
1877
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001878 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001879 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1880 && mTopAction == null) {
1881 // We are running in factory test mode, but unable to find
1882 // the factory test app, so just sit around displaying the
1883 // error message and don't try to start anything.
1884 return false;
1885 }
1886 Intent intent = new Intent(
1887 mTopAction,
1888 mTopData != null ? Uri.parse(mTopData) : null);
1889 intent.setComponent(mTopComponent);
1890 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1891 intent.addCategory(Intent.CATEGORY_HOME);
1892 }
1893 ActivityInfo aInfo =
1894 intent.resolveActivityInfo(mContext.getPackageManager(),
1895 STOCK_PM_FLAGS);
1896 if (aInfo != null) {
1897 intent.setComponent(new ComponentName(
1898 aInfo.applicationInfo.packageName, aInfo.name));
1899 // Don't do this if the home app is currently being
1900 // instrumented.
1901 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1902 aInfo.applicationInfo.uid);
1903 if (app == null || app.instrumentationClass == null) {
1904 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001905 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001906 null, null, 0, 0, 0, false, false);
1907 }
1908 }
1909
1910
1911 return true;
1912 }
1913
1914 /**
1915 * Starts the "new version setup screen" if appropriate.
1916 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001917 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001918 // Only do this once per boot.
1919 if (mCheckedForSetup) {
1920 return;
1921 }
1922
1923 // We will show this screen if the current one is a different
1924 // version than the last one shown, and we are not running in
1925 // low-level factory test mode.
1926 final ContentResolver resolver = mContext.getContentResolver();
1927 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1928 Settings.Secure.getInt(resolver,
1929 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1930 mCheckedForSetup = true;
1931
1932 // See if we should be showing the platform update setup UI.
1933 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1934 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1935 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1936
1937 // We don't allow third party apps to replace this.
1938 ResolveInfo ri = null;
1939 for (int i=0; ris != null && i<ris.size(); i++) {
1940 if ((ris.get(i).activityInfo.applicationInfo.flags
1941 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1942 ri = ris.get(i);
1943 break;
1944 }
1945 }
1946
1947 if (ri != null) {
1948 String vers = ri.activityInfo.metaData != null
1949 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1950 : null;
1951 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1952 vers = ri.activityInfo.applicationInfo.metaData.getString(
1953 Intent.METADATA_SETUP_VERSION);
1954 }
1955 String lastVers = Settings.Secure.getString(
1956 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1957 if (vers != null && !vers.equals(lastVers)) {
1958 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1959 intent.setComponent(new ComponentName(
1960 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001961 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001962 null, null, 0, 0, 0, false, false);
1963 }
1964 }
1965 }
1966 }
1967
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001968 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001969 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001970
1971 final int identHash = System.identityHashCode(r);
1972 updateUsageStats(r, true);
1973
1974 int i = mWatchers.beginBroadcast();
1975 while (i > 0) {
1976 i--;
1977 IActivityWatcher w = mWatchers.getBroadcastItem(i);
1978 if (w != null) {
1979 try {
1980 w.activityResuming(identHash);
1981 } catch (RemoteException e) {
1982 }
1983 }
1984 }
1985 mWatchers.finishBroadcast();
1986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001987
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001988 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001989 final int N = mPendingActivityLaunches.size();
1990 if (N <= 0) {
1991 return;
1992 }
1993 for (int i=0; i<N; i++) {
1994 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001995 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001996 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
1997 doResume && i == (N-1));
1998 }
1999 mPendingActivityLaunches.clear();
2000 }
2001
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002002 public final int startActivity(IApplicationThread caller,
2003 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2004 int grantedMode, IBinder resultTo,
2005 String resultWho, int requestCode, boolean onlyIfNeeded,
2006 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002007 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002008 grantedUriPermissions, grantedMode, resultTo, resultWho,
2009 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002010 }
2011
2012 public final WaitResult startActivityAndWait(IApplicationThread caller,
2013 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2014 int grantedMode, IBinder resultTo,
2015 String resultWho, int requestCode, boolean onlyIfNeeded,
2016 boolean debug) {
2017 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002018 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002019 grantedUriPermissions, grantedMode, resultTo, resultWho,
2020 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002021 return res;
2022 }
2023
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002024 public final int startActivityWithConfig(IApplicationThread caller,
2025 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2026 int grantedMode, IBinder resultTo,
2027 String resultWho, int requestCode, boolean onlyIfNeeded,
2028 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002029 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002030 grantedUriPermissions, grantedMode, resultTo, resultWho,
2031 requestCode, onlyIfNeeded, debug, null, config);
2032 }
2033
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002034 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002035 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002036 IBinder resultTo, String resultWho, int requestCode,
2037 int flagsMask, int flagsValues) {
2038 // Refuse possible leaked file descriptors
2039 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2040 throw new IllegalArgumentException("File descriptors passed in Intent");
2041 }
2042
2043 IIntentSender sender = intent.getTarget();
2044 if (!(sender instanceof PendingIntentRecord)) {
2045 throw new IllegalArgumentException("Bad PendingIntent object");
2046 }
2047
2048 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002049
2050 synchronized (this) {
2051 // If this is coming from the currently resumed activity, it is
2052 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002053 if (mMainStack.mResumedActivity != null
2054 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002055 Binder.getCallingUid()) {
2056 mAppSwitchesAllowedTime = 0;
2057 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002058 }
2059
2060 return pir.sendInner(0, fillInIntent, resolvedType,
2061 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2062 }
2063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 public boolean startNextMatchingActivity(IBinder callingActivity,
2065 Intent intent) {
2066 // Refuse possible leaked file descriptors
2067 if (intent != null && intent.hasFileDescriptors() == true) {
2068 throw new IllegalArgumentException("File descriptors passed in Intent");
2069 }
2070
2071 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002072 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 if (index < 0) {
2074 return false;
2075 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002076 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 if (r.app == null || r.app.thread == null) {
2078 // The caller is not running... d'oh!
2079 return false;
2080 }
2081 intent = new Intent(intent);
2082 // The caller is not allowed to change the data.
2083 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2084 // And we are resetting to find the next component...
2085 intent.setComponent(null);
2086
2087 ActivityInfo aInfo = null;
2088 try {
2089 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002090 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002092 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093
2094 // Look for the original activity in the list...
2095 final int N = resolves != null ? resolves.size() : 0;
2096 for (int i=0; i<N; i++) {
2097 ResolveInfo rInfo = resolves.get(i);
2098 if (rInfo.activityInfo.packageName.equals(r.packageName)
2099 && rInfo.activityInfo.name.equals(r.info.name)) {
2100 // We found the current one... the next matching is
2101 // after it.
2102 i++;
2103 if (i<N) {
2104 aInfo = resolves.get(i).activityInfo;
2105 }
2106 break;
2107 }
2108 }
2109 } catch (RemoteException e) {
2110 }
2111
2112 if (aInfo == null) {
2113 // Nobody who is next!
2114 return false;
2115 }
2116
2117 intent.setComponent(new ComponentName(
2118 aInfo.applicationInfo.packageName, aInfo.name));
2119 intent.setFlags(intent.getFlags()&~(
2120 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2121 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2122 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2123 Intent.FLAG_ACTIVITY_NEW_TASK));
2124
2125 // Okay now we need to start the new activity, replacing the
2126 // currently running activity. This is a little tricky because
2127 // we want to start the new one as if the current one is finished,
2128 // but not finish the current one first so that there is no flicker.
2129 // And thus...
2130 final boolean wasFinishing = r.finishing;
2131 r.finishing = true;
2132
2133 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002134 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 final String resultWho = r.resultWho;
2136 final int requestCode = r.requestCode;
2137 r.resultTo = null;
2138 if (resultTo != null) {
2139 resultTo.removeResultsLocked(r, resultWho, requestCode);
2140 }
2141
2142 final long origId = Binder.clearCallingIdentity();
2143 // XXX we are not dealing with propagating grantedUriPermissions...
2144 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002145 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002147 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 Binder.restoreCallingIdentity(origId);
2149
2150 r.finishing = wasFinishing;
2151 if (res != START_SUCCESS) {
2152 return false;
2153 }
2154 return true;
2155 }
2156 }
2157
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002158 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 Intent intent, String resolvedType, IBinder resultTo,
2160 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002161
2162 // This is so super not safe, that only the system (or okay root)
2163 // can do it.
2164 final int callingUid = Binder.getCallingUid();
2165 if (callingUid != 0 && callingUid != Process.myUid()) {
2166 throw new SecurityException(
2167 "startActivityInPackage only available to the system");
2168 }
2169
The Android Open Source Project4df24232009-03-05 14:34:35 -08002170 final boolean componentSpecified = intent.getComponent() != null;
2171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 // Don't modify the client's object!
2173 intent = new Intent(intent);
2174
2175 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 ActivityInfo aInfo;
2177 try {
2178 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002179 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002181 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 aInfo = rInfo != null ? rInfo.activityInfo : null;
2183 } catch (RemoteException e) {
2184 aInfo = null;
2185 }
2186
2187 if (aInfo != null) {
2188 // Store the found target back into the intent, because now that
2189 // we have it we never want to do this again. For example, if the
2190 // user navigates back to this point in the history, we should
2191 // always restart the exact same activity.
2192 intent.setComponent(new ComponentName(
2193 aInfo.applicationInfo.packageName, aInfo.name));
2194 }
2195
2196 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002197 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002199 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 }
2201 }
2202
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002203 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002204 // Remove any existing entries that are the same kind of task.
2205 int N = mRecentTasks.size();
2206 for (int i=0; i<N; i++) {
2207 TaskRecord tr = mRecentTasks.get(i);
2208 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2209 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2210 mRecentTasks.remove(i);
2211 i--;
2212 N--;
2213 if (task.intent == null) {
2214 // If the new recent task we are adding is not fully
2215 // specified, then replace it with the existing recent task.
2216 task = tr;
2217 }
2218 }
2219 }
2220 if (N >= MAX_RECENT_TASKS) {
2221 mRecentTasks.remove(N-1);
2222 }
2223 mRecentTasks.add(0, task);
2224 }
2225
2226 public void setRequestedOrientation(IBinder token,
2227 int requestedOrientation) {
2228 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002229 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230 if (index < 0) {
2231 return;
2232 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002233 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 final long origId = Binder.clearCallingIdentity();
2235 mWindowManager.setAppOrientation(r, requestedOrientation);
2236 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002237 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002238 r.mayFreezeScreenLocked(r.app) ? r : null);
2239 if (config != null) {
2240 r.frozenBeforeDestroy = true;
2241 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002242 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 }
2244 }
2245 Binder.restoreCallingIdentity(origId);
2246 }
2247 }
2248
2249 public int getRequestedOrientation(IBinder token) {
2250 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002251 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 if (index < 0) {
2253 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2254 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002255 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 return mWindowManager.getAppOrientation(r);
2257 }
2258 }
2259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260 /**
2261 * This is the internal entry point for handling Activity.finish().
2262 *
2263 * @param token The Binder token referencing the Activity we want to finish.
2264 * @param resultCode Result code, if any, from this Activity.
2265 * @param resultData Result data (Intent), if any, from this Activity.
2266 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002267 * @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 -08002268 */
2269 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2270 // Refuse possible leaked file descriptors
2271 if (resultData != null && resultData.hasFileDescriptors() == true) {
2272 throw new IllegalArgumentException("File descriptors passed in Intent");
2273 }
2274
2275 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002276 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002278 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 if (next != null) {
2280 // ask watcher if this is allowed
2281 boolean resumeOK = true;
2282 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002283 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002285 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286 }
2287
2288 if (!resumeOK) {
2289 return false;
2290 }
2291 }
2292 }
2293 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002294 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 resultData, "app-request");
2296 Binder.restoreCallingIdentity(origId);
2297 return res;
2298 }
2299 }
2300
Dianne Hackborn860755f2010-06-03 18:47:52 -07002301 public final void finishHeavyWeightApp() {
2302 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2303 != PackageManager.PERMISSION_GRANTED) {
2304 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2305 + Binder.getCallingPid()
2306 + ", uid=" + Binder.getCallingUid()
2307 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2308 Slog.w(TAG, msg);
2309 throw new SecurityException(msg);
2310 }
2311
2312 synchronized(this) {
2313 if (mHeavyWeightProcess == null) {
2314 return;
2315 }
2316
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002317 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002318 mHeavyWeightProcess.activities);
2319 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002320 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002321 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002322 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002323 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002324 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002325 null, "finish-heavy");
2326 }
2327 }
2328 }
2329
2330 mHeavyWeightProcess = null;
2331 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2332 }
2333 }
2334
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002335 public void crashApplication(int uid, int initialPid, String packageName,
2336 String message) {
2337 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2338 != PackageManager.PERMISSION_GRANTED) {
2339 String msg = "Permission Denial: crashApplication() from pid="
2340 + Binder.getCallingPid()
2341 + ", uid=" + Binder.getCallingUid()
2342 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2343 Slog.w(TAG, msg);
2344 throw new SecurityException(msg);
2345 }
2346
2347 synchronized(this) {
2348 ProcessRecord proc = null;
2349
2350 // Figure out which process to kill. We don't trust that initialPid
2351 // still has any relation to current pids, so must scan through the
2352 // list.
2353 synchronized (mPidsSelfLocked) {
2354 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2355 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2356 if (p.info.uid != uid) {
2357 continue;
2358 }
2359 if (p.pid == initialPid) {
2360 proc = p;
2361 break;
2362 }
2363 for (String str : p.pkgList) {
2364 if (str.equals(packageName)) {
2365 proc = p;
2366 }
2367 }
2368 }
2369 }
2370
2371 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002372 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002373 + " initialPid=" + initialPid
2374 + " packageName=" + packageName);
2375 return;
2376 }
2377
2378 if (proc.thread != null) {
2379 long ident = Binder.clearCallingIdentity();
2380 try {
2381 proc.thread.scheduleCrash(message);
2382 } catch (RemoteException e) {
2383 }
2384 Binder.restoreCallingIdentity(ident);
2385 }
2386 }
2387 }
2388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002389 public final void finishSubActivity(IBinder token, String resultWho,
2390 int requestCode) {
2391 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002392 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393 if (index < 0) {
2394 return;
2395 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002396 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397
2398 final long origId = Binder.clearCallingIdentity();
2399
2400 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002401 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2402 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002403 if (r.resultTo == self && r.requestCode == requestCode) {
2404 if ((r.resultWho == null && resultWho == null) ||
2405 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002406 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002407 Activity.RESULT_CANCELED, null, "request-sub");
2408 }
2409 }
2410 }
2411
2412 Binder.restoreCallingIdentity(origId);
2413 }
2414 }
2415
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002416 public boolean willActivityBeVisible(IBinder token) {
2417 synchronized(this) {
2418 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002419 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2420 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002421 if (r == token) {
2422 return true;
2423 }
2424 if (r.fullscreen && !r.finishing) {
2425 return false;
2426 }
2427 }
2428 return true;
2429 }
2430 }
2431
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002432 public void overridePendingTransition(IBinder token, String packageName,
2433 int enterAnim, int exitAnim) {
2434 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002435 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002436 if (index < 0) {
2437 return;
2438 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002439 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002440
2441 final long origId = Binder.clearCallingIdentity();
2442
2443 if (self.state == ActivityState.RESUMED
2444 || self.state == ActivityState.PAUSING) {
2445 mWindowManager.overridePendingAppTransition(packageName,
2446 enterAnim, exitAnim);
2447 }
2448
2449 Binder.restoreCallingIdentity(origId);
2450 }
2451 }
2452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002453 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 * Main function for removing an existing process from the activity manager
2455 * as a result of that process going away. Clears out all connections
2456 * to the process.
2457 */
2458 private final void handleAppDiedLocked(ProcessRecord app,
2459 boolean restarting) {
2460 cleanUpApplicationRecordLocked(app, restarting, -1);
2461 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002462 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002463 }
2464
2465 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002466 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2467 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2468 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002469 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002470 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2471 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002472 }
2473
2474 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002475 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476
2477 boolean atTop = true;
2478 boolean hasVisibleActivities = false;
2479
2480 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002481 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002482 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002483 TAG, "Removing app " + app + " from history with " + i + " entries");
2484 while (i > 0) {
2485 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002486 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002487 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002488 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2489 if (r.app == app) {
2490 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002491 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 TAG, "Removing this entry! frozen=" + r.haveState
2493 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002494 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495
2496 r.inHistory = false;
2497 mWindowManager.removeAppToken(r);
2498 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002499 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002501 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502
2503 } else {
2504 // We have the current state for this activity, so
2505 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002506 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 TAG, "Keeping entry, setting app to null");
2508 if (r.visible) {
2509 hasVisibleActivities = true;
2510 }
2511 r.app = null;
2512 r.nowVisible = false;
2513 if (!r.haveState) {
2514 r.icicle = null;
2515 }
2516 }
2517
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002519 r.state = ActivityState.STOPPED;
2520 }
2521 atTop = false;
2522 }
2523
2524 app.activities.clear();
2525
2526 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002527 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 + " running instrumentation " + app.instrumentationClass);
2529 Bundle info = new Bundle();
2530 info.putString("shortMsg", "Process crashed.");
2531 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2532 }
2533
2534 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002535 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002536 // If there was nothing to resume, and we are not already
2537 // restarting this process, but there is a visible activity that
2538 // is hosted by the process... then make sure all visible
2539 // activities are running, taking care of restarting this
2540 // process.
2541 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002542 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 }
2544 }
2545 }
2546 }
2547
2548 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2549 IBinder threadBinder = thread.asBinder();
2550
2551 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002552 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2553 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2555 return i;
2556 }
2557 }
2558 return -1;
2559 }
2560
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002561 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 IApplicationThread thread) {
2563 if (thread == null) {
2564 return null;
2565 }
2566
2567 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002568 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 }
2570
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002571 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002572 IApplicationThread thread) {
2573
2574 mProcDeaths[0]++;
2575
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002576 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2577 synchronized (stats) {
2578 stats.noteProcessDiedLocked(app.info.uid, pid);
2579 }
2580
Magnus Edlund7bb25812010-02-24 15:45:06 +01002581 // Clean up already done if the process has been re-started.
2582 if (app.pid == pid && app.thread != null &&
2583 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002584 if (!app.killedBackground) {
2585 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2586 + ") has died.");
2587 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002588 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002589 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 TAG, "Dying app: " + app + ", pid: " + pid
2591 + ", thread: " + thread.asBinder());
2592 boolean doLowMem = app.instrumentationClass == null;
2593 handleAppDiedLocked(app, false);
2594
2595 if (doLowMem) {
2596 // If there are no longer any background processes running,
2597 // and the app that died was not running instrumentation,
2598 // then tell everyone we are now low on memory.
2599 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002600 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2601 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002602 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2603 haveBg = true;
2604 break;
2605 }
2606 }
2607
2608 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002609 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002610 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002611 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002612 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2613 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002614 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002615 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2616 // The low memory report is overriding any current
2617 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002618 // heavy/important/visible/foreground processes first.
2619 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002620 rec.lastRequestedGc = 0;
2621 } else {
2622 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002624 rec.reportLowMemory = true;
2625 rec.lastLowMemory = now;
2626 mProcessesToGc.remove(rec);
2627 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 }
2629 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002630 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 }
2632 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002633 } else if (app.pid != pid) {
2634 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002635 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002636 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002637 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002638 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002639 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 + thread.asBinder());
2641 }
2642 }
2643
Dan Egnor42471dd2010-01-07 17:25:22 -08002644 /**
2645 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002646 * @param clearTraces causes the dump file to be erased prior to the new
2647 * traces being written, if true; when false, the new traces will be
2648 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002649 * @param firstPids of dalvik VM processes to dump stack traces for first
2650 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002651 * @return file containing stack traces, or null if no dump file is configured
2652 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002653 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2654 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002655 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2656 if (tracesPath == null || tracesPath.length() == 0) {
2657 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002659
2660 File tracesFile = new File(tracesPath);
2661 try {
2662 File tracesDir = tracesFile.getParentFile();
2663 if (!tracesDir.exists()) tracesFile.mkdirs();
2664 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2665
Christopher Tate6ee412d2010-05-28 12:01:56 -07002666 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002667 tracesFile.createNewFile();
2668 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2669 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002670 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002671 return null;
2672 }
2673
2674 // Use a FileObserver to detect when traces finish writing.
2675 // The order of traces is considered important to maintain for legibility.
2676 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2677 public synchronized void onEvent(int event, String path) { notify(); }
2678 };
2679
2680 try {
2681 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002682
2683 // First collect all of the stacks of the most important pids.
2684 try {
2685 int num = firstPids.size();
2686 for (int i = 0; i < num; i++) {
2687 synchronized (observer) {
2688 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2689 observer.wait(200); // Wait for write-close, give up after 200msec
2690 }
2691 }
2692 } catch (InterruptedException e) {
2693 Log.wtf(TAG, e);
2694 }
2695
2696 // Next measure CPU usage.
2697 if (processStats != null) {
2698 processStats.init();
2699 System.gc();
2700 processStats.update();
2701 try {
2702 synchronized (processStats) {
2703 processStats.wait(500); // measure over 1/2 second.
2704 }
2705 } catch (InterruptedException e) {
2706 }
2707 processStats.update();
2708
2709 // We'll take the stack crawls of just the top apps using CPU.
2710 final int N = processStats.countWorkingStats();
2711 int numProcs = 0;
2712 for (int i=0; i<N && numProcs<5; i++) {
2713 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2714 if (lastPids.indexOfKey(stats.pid) >= 0) {
2715 numProcs++;
2716 try {
2717 synchronized (observer) {
2718 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2719 observer.wait(200); // Wait for write-close, give up after 200msec
2720 }
2721 } catch (InterruptedException e) {
2722 Log.wtf(TAG, e);
2723 }
2724
2725 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002726 }
2727 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002728
2729 return tracesFile;
2730
Dan Egnor42471dd2010-01-07 17:25:22 -08002731 } finally {
2732 observer.stopWatching();
2733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 }
2735
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002736 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2737 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002738 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2739 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2740
2741 long anrTime = SystemClock.uptimeMillis();
2742 if (MONITOR_CPU_USAGE) {
2743 updateCpuStatsNow();
2744 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002745
2746 synchronized (this) {
2747 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2748 if (mShuttingDown) {
2749 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2750 return;
2751 } else if (app.notResponding) {
2752 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2753 return;
2754 } else if (app.crashing) {
2755 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2756 return;
2757 }
2758
2759 // In case we come through here for the same app before completing
2760 // this one, mark as anring now so we will bail out.
2761 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002762
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002763 // Log the ANR to the event log.
2764 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2765 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002766
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002767 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002768 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002769
2770 int parentPid = app.pid;
2771 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002772 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002773
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002774 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002775
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002776 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2777 ProcessRecord r = mLruProcesses.get(i);
2778 if (r != null && r.thread != null) {
2779 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002780 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2781 if (r.persistent) {
2782 firstPids.add(pid);
2783 } else {
2784 lastPids.put(pid, Boolean.TRUE);
2785 }
2786 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002788 }
2789 }
2790
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002791 final ProcessStats processStats = new ProcessStats(true);
2792
2793 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002794
2795 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002796 StringBuilder info = mStringBuilder;
2797 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002798 info.append("ANR in ").append(app.processName);
2799 if (activity != null && activity.shortComponentName != null) {
2800 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002801 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002802 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002804 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002805 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002806 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002807 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809
Dan Egnor42471dd2010-01-07 17:25:22 -08002810 String cpuInfo = null;
2811 if (MONITOR_CPU_USAGE) {
2812 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002813 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002814 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002815 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002816 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002817 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002818 }
2819
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002820 info.append(processStats.printCurrentState(anrTime));
2821
Joe Onorato8a9b2202010-02-26 18:56:32 -08002822 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002823 if (tracesFile == null) {
2824 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2825 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2826 }
2827
2828 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2829
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002830 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002832 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2833 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002834 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002835 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2836 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837 }
2838 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002839 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002840 }
2841 }
2842
Dan Egnor42471dd2010-01-07 17:25:22 -08002843 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2844 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2845 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002846
2847 synchronized (this) {
2848 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2849 Process.killProcess(app.pid);
2850 return;
2851 }
2852
2853 // Set the app's notResponding state, and look up the errorReportReceiver
2854 makeAppNotRespondingLocked(app,
2855 activity != null ? activity.shortComponentName : null,
2856 annotation != null ? "ANR " + annotation : "ANR",
2857 info.toString());
2858
2859 // Bring up the infamous App Not Responding dialog
2860 Message msg = Message.obtain();
2861 HashMap map = new HashMap();
2862 msg.what = SHOW_NOT_RESPONDING_MSG;
2863 msg.obj = map;
2864 map.put("app", app);
2865 if (activity != null) {
2866 map.put("activity", activity);
2867 }
2868
2869 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002870 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 }
2872
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002873 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 app.persistentActivities--;
2875 if (app.persistentActivities > 0) {
2876 // Still more of 'em...
2877 return;
2878 }
2879 if (app.persistent) {
2880 // Ah, but the application itself is persistent. Whatever!
2881 return;
2882 }
2883
2884 // App is no longer persistent... make sure it and the ones
2885 // following it in the LRU list have the correc oom_adj.
2886 updateOomAdjLocked();
2887 }
2888
2889 public void setPersistent(IBinder token, boolean isPersistent) {
2890 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2891 != PackageManager.PERMISSION_GRANTED) {
2892 String msg = "Permission Denial: setPersistent() from pid="
2893 + Binder.getCallingPid()
2894 + ", uid=" + Binder.getCallingUid()
2895 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002896 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 throw new SecurityException(msg);
2898 }
2899
2900 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002901 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002902 if (index < 0) {
2903 return;
2904 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002905 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 ProcessRecord app = r.app;
2907
Joe Onorato8a9b2202010-02-26 18:56:32 -08002908 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002909 TAG, "Setting persistence " + isPersistent + ": " + r);
2910
2911 if (isPersistent) {
2912 if (r.persistent) {
2913 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002914 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915 return;
2916 }
2917 r.persistent = true;
2918 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002919 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 if (app.persistentActivities > 1) {
2921 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002922 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 return;
2924 }
2925 if (app.persistent) {
2926 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002927 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 return;
2929 }
2930
2931 // App is now persistent... make sure it and the ones
2932 // following it now have the correct oom_adj.
2933 final long origId = Binder.clearCallingIdentity();
2934 updateOomAdjLocked();
2935 Binder.restoreCallingIdentity(origId);
2936
2937 } else {
2938 if (!r.persistent) {
2939 // Okay okay, I heard you already!
2940 return;
2941 }
2942 r.persistent = false;
2943 final long origId = Binder.clearCallingIdentity();
2944 decPersistentCountLocked(app);
2945 Binder.restoreCallingIdentity(origId);
2946
2947 }
2948 }
2949 }
2950
2951 public boolean clearApplicationUserData(final String packageName,
2952 final IPackageDataObserver observer) {
2953 int uid = Binder.getCallingUid();
2954 int pid = Binder.getCallingPid();
2955 long callingId = Binder.clearCallingIdentity();
2956 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002957 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 int pkgUid = -1;
2959 synchronized(this) {
2960 try {
2961 pkgUid = pm.getPackageUid(packageName);
2962 } catch (RemoteException e) {
2963 }
2964 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002965 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002966 return false;
2967 }
2968 if (uid == pkgUid || checkComponentPermission(
2969 android.Manifest.permission.CLEAR_APP_USER_DATA,
2970 pid, uid, -1)
2971 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08002972 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 } else {
2974 throw new SecurityException(pid+" does not have permission:"+
2975 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
2976 "for process:"+packageName);
2977 }
2978 }
2979
2980 try {
2981 //clear application user data
2982 pm.clearApplicationUserData(packageName, observer);
2983 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
2984 Uri.fromParts("package", packageName, null));
2985 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06002986 synchronized (this) {
2987 broadcastIntentLocked(null, null, intent,
2988 null, null, 0, null, null, null,
2989 false, false, MY_PID, Process.SYSTEM_UID);
2990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 } catch (RemoteException e) {
2992 }
2993 } finally {
2994 Binder.restoreCallingIdentity(callingId);
2995 }
2996 return true;
2997 }
2998
Dianne Hackborn03abb812010-01-04 18:43:19 -08002999 public void killBackgroundProcesses(final String packageName) {
3000 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3001 != PackageManager.PERMISSION_GRANTED &&
3002 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3003 != PackageManager.PERMISSION_GRANTED) {
3004 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 + Binder.getCallingPid()
3006 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003007 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003008 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 throw new SecurityException(msg);
3010 }
3011
3012 long callingId = Binder.clearCallingIdentity();
3013 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003014 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 int pkgUid = -1;
3016 synchronized(this) {
3017 try {
3018 pkgUid = pm.getPackageUid(packageName);
3019 } catch (RemoteException e) {
3020 }
3021 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003022 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 return;
3024 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003025 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003026 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003027 }
3028 } finally {
3029 Binder.restoreCallingIdentity(callingId);
3030 }
3031 }
3032
3033 public void forceStopPackage(final String packageName) {
3034 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3035 != PackageManager.PERMISSION_GRANTED) {
3036 String msg = "Permission Denial: forceStopPackage() from pid="
3037 + Binder.getCallingPid()
3038 + ", uid=" + Binder.getCallingUid()
3039 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003040 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003041 throw new SecurityException(msg);
3042 }
3043
3044 long callingId = Binder.clearCallingIdentity();
3045 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003046 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003047 int pkgUid = -1;
3048 synchronized(this) {
3049 try {
3050 pkgUid = pm.getPackageUid(packageName);
3051 } catch (RemoteException e) {
3052 }
3053 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003054 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003055 return;
3056 }
3057 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003058 }
3059 } finally {
3060 Binder.restoreCallingIdentity(callingId);
3061 }
3062 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003063
3064 /*
3065 * The pkg name and uid have to be specified.
3066 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3067 */
3068 public void killApplicationWithUid(String pkg, int uid) {
3069 if (pkg == null) {
3070 return;
3071 }
3072 // Make sure the uid is valid.
3073 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003074 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003075 return;
3076 }
3077 int callerUid = Binder.getCallingUid();
3078 // Only the system server can kill an application
3079 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003080 // Post an aysnc message to kill the application
3081 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3082 msg.arg1 = uid;
3083 msg.arg2 = 0;
3084 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003085 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003086 } else {
3087 throw new SecurityException(callerUid + " cannot kill pkg: " +
3088 pkg);
3089 }
3090 }
3091
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003092 public void closeSystemDialogs(String reason) {
3093 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3094 if (reason != null) {
3095 intent.putExtra("reason", reason);
3096 }
3097
3098 final int uid = Binder.getCallingUid();
3099 final long origId = Binder.clearCallingIdentity();
3100 synchronized (this) {
3101 int i = mWatchers.beginBroadcast();
3102 while (i > 0) {
3103 i--;
3104 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3105 if (w != null) {
3106 try {
3107 w.closingSystemDialogs(reason);
3108 } catch (RemoteException e) {
3109 }
3110 }
3111 }
3112 mWatchers.finishBroadcast();
3113
Dianne Hackbornffa42482009-09-23 22:20:11 -07003114 mWindowManager.closeSystemDialogs(reason);
3115
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003116 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3117 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003118 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003119 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003120 Activity.RESULT_CANCELED, null, "close-sys");
3121 }
3122 }
3123
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003124 broadcastIntentLocked(null, null, intent, null,
3125 null, 0, null, null, null, false, false, -1, uid);
3126 }
3127 Binder.restoreCallingIdentity(origId);
3128 }
3129
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003130 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003131 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003132 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3133 for (int i=pids.length-1; i>=0; i--) {
3134 infos[i] = new Debug.MemoryInfo();
3135 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003136 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003137 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003138 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003139
3140 public void killApplicationProcess(String processName, int uid) {
3141 if (processName == null) {
3142 return;
3143 }
3144
3145 int callerUid = Binder.getCallingUid();
3146 // Only the system server can kill an application
3147 if (callerUid == Process.SYSTEM_UID) {
3148 synchronized (this) {
3149 ProcessRecord app = getProcessRecordLocked(processName, uid);
3150 if (app != null) {
3151 try {
3152 app.thread.scheduleSuicide();
3153 } catch (RemoteException e) {
3154 // If the other end already died, then our work here is done.
3155 }
3156 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003157 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003158 + processName + " / " + uid);
3159 }
3160 }
3161 } else {
3162 throw new SecurityException(callerUid + " cannot kill app process: " +
3163 processName);
3164 }
3165 }
3166
Dianne Hackborn03abb812010-01-04 18:43:19 -08003167 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003168 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3170 Uri.fromParts("package", packageName, null));
3171 intent.putExtra(Intent.EXTRA_UID, uid);
3172 broadcastIntentLocked(null, null, intent,
3173 null, null, 0, null, null, null,
3174 false, false, MY_PID, Process.SYSTEM_UID);
3175 }
3176
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003177 private final boolean killPackageProcessesLocked(String packageName, int uid,
3178 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003179 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180
Dianne Hackborn03abb812010-01-04 18:43:19 -08003181 // Remove all processes this package may have touched: all with the
3182 // same UID (except for the system or root user), and all whose name
3183 // matches the package name.
3184 final String procNamePrefix = packageName + ":";
3185 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3186 final int NA = apps.size();
3187 for (int ia=0; ia<NA; ia++) {
3188 ProcessRecord app = apps.valueAt(ia);
3189 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003190 if (doit) {
3191 procs.add(app);
3192 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003193 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3194 || app.processName.equals(packageName)
3195 || app.processName.startsWith(procNamePrefix)) {
3196 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003197 if (!doit) {
3198 return true;
3199 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003200 app.removed = true;
3201 procs.add(app);
3202 }
3203 }
3204 }
3205 }
3206
3207 int N = procs.size();
3208 for (int i=0; i<N; i++) {
3209 removeProcessLocked(procs.get(i), callerWillRestart);
3210 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003211 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003212 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003213
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003214 private final boolean forceStopPackageLocked(String name, int uid,
3215 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003216 int i, N;
3217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 if (uid < 0) {
3219 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003220 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003221 } catch (RemoteException e) {
3222 }
3223 }
3224
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003225 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003226 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003227
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003228 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3229 while (badApps.hasNext()) {
3230 SparseArray<Long> ba = badApps.next();
3231 if (ba.get(uid) != null) {
3232 badApps.remove();
3233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 }
3235 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003236
3237 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3238 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003240 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3241 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003243 if (!doit) {
3244 return true;
3245 }
3246 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003247 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 if (r.app != null) {
3249 r.app.removed = true;
3250 }
3251 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003252 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 }
3254 }
3255
3256 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3257 for (ServiceRecord service : mServices.values()) {
3258 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003259 if (!doit) {
3260 return true;
3261 }
3262 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003263 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 if (service.app != null) {
3265 service.app.removed = true;
3266 }
3267 service.app = null;
3268 services.add(service);
3269 }
3270 }
3271
3272 N = services.size();
3273 for (i=0; i<N; i++) {
3274 bringDownServiceLocked(services.get(i), true);
3275 }
3276
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003277 if (doit) {
3278 if (purgeCache) {
3279 AttributeCache ac = AttributeCache.instance();
3280 if (ac != null) {
3281 ac.removePackage(name);
3282 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003283 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003284 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003285 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003286
3287 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 }
3289
3290 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3291 final String name = app.processName;
3292 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003293 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 TAG, "Force removing process " + app + " (" + name
3295 + "/" + uid + ")");
3296
3297 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003298 if (mHeavyWeightProcess == app) {
3299 mHeavyWeightProcess = null;
3300 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003302 boolean needRestart = false;
3303 if (app.pid > 0 && app.pid != MY_PID) {
3304 int pid = app.pid;
3305 synchronized (mPidsSelfLocked) {
3306 mPidsSelfLocked.remove(pid);
3307 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3308 }
3309 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003310 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 Process.killProcess(pid);
3312
3313 if (app.persistent) {
3314 if (!callerWillRestart) {
3315 addAppLocked(app.info);
3316 } else {
3317 needRestart = true;
3318 }
3319 }
3320 } else {
3321 mRemovedProcesses.add(app);
3322 }
3323
3324 return needRestart;
3325 }
3326
3327 private final void processStartTimedOutLocked(ProcessRecord app) {
3328 final int pid = app.pid;
3329 boolean gone = false;
3330 synchronized (mPidsSelfLocked) {
3331 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3332 if (knownApp != null && knownApp.thread == null) {
3333 mPidsSelfLocked.remove(pid);
3334 gone = true;
3335 }
3336 }
3337
3338 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003339 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003340 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003341 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003343 if (mHeavyWeightProcess == app) {
3344 mHeavyWeightProcess = null;
3345 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3346 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003347 // Take care of any launching providers waiting for this process.
3348 checkAppInLaunchingProvidersLocked(app, true);
3349 // Take care of any services that are waiting for the process.
3350 for (int i=0; i<mPendingServices.size(); i++) {
3351 ServiceRecord sr = mPendingServices.get(i);
3352 if (app.info.uid == sr.appInfo.uid
3353 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003354 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003355 mPendingServices.remove(i);
3356 i--;
3357 bringDownServiceLocked(sr, true);
3358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003360 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003361 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003362 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003363 try {
3364 IBackupManager bm = IBackupManager.Stub.asInterface(
3365 ServiceManager.getService(Context.BACKUP_SERVICE));
3366 bm.agentDisconnected(app.info.packageName);
3367 } catch (RemoteException e) {
3368 // Can't happen; the backup manager is local
3369 }
3370 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003371 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003372 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003373 mPendingBroadcast = null;
3374 scheduleBroadcastsLocked();
3375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003376 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003377 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003378 }
3379 }
3380
3381 private final boolean attachApplicationLocked(IApplicationThread thread,
3382 int pid) {
3383
3384 // Find the application record that is being attached... either via
3385 // the pid if we are running in multiple processes, or just pull the
3386 // next app record if we are emulating process with anonymous threads.
3387 ProcessRecord app;
3388 if (pid != MY_PID && pid >= 0) {
3389 synchronized (mPidsSelfLocked) {
3390 app = mPidsSelfLocked.get(pid);
3391 }
3392 } else if (mStartingProcesses.size() > 0) {
3393 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003394 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 } else {
3396 app = null;
3397 }
3398
3399 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003400 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003402 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003403 if (pid > 0 && pid != MY_PID) {
3404 Process.killProcess(pid);
3405 } else {
3406 try {
3407 thread.scheduleExit();
3408 } catch (Exception e) {
3409 // Ignore exceptions.
3410 }
3411 }
3412 return false;
3413 }
3414
3415 // If this application record is still attached to a previous
3416 // process, clean it up now.
3417 if (app.thread != null) {
3418 handleAppDiedLocked(app, true);
3419 }
3420
3421 // Tell the process all about itself.
3422
Joe Onorato8a9b2202010-02-26 18:56:32 -08003423 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 TAG, "Binding process pid " + pid + " to record " + app);
3425
3426 String processName = app.processName;
3427 try {
3428 thread.asBinder().linkToDeath(new AppDeathRecipient(
3429 app, pid, thread), 0);
3430 } catch (RemoteException e) {
3431 app.resetPackageList();
3432 startProcessLocked(app, "link fail", processName);
3433 return false;
3434 }
3435
Doug Zongker2bec3d42009-12-04 12:52:44 -08003436 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437
3438 app.thread = thread;
3439 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003440 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3441 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003442 app.forcingToForeground = null;
3443 app.foregroundServices = false;
3444 app.debugging = false;
3445
3446 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3447
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003448 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3449 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003451 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003452 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003453 }
3454
Joe Onorato8a9b2202010-02-26 18:56:32 -08003455 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 TAG, "New app record " + app
3457 + " thread=" + thread.asBinder() + " pid=" + pid);
3458 try {
3459 int testMode = IApplicationThread.DEBUG_OFF;
3460 if (mDebugApp != null && mDebugApp.equals(processName)) {
3461 testMode = mWaitForDebugger
3462 ? IApplicationThread.DEBUG_WAIT
3463 : IApplicationThread.DEBUG_ON;
3464 app.debugging = true;
3465 if (mDebugTransient) {
3466 mDebugApp = mOrigDebugApp;
3467 mWaitForDebugger = mOrigWaitForDebugger;
3468 }
3469 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003470
Christopher Tate181fafa2009-05-14 11:12:14 -07003471 // If the app is being launched for restore or full backup, set it up specially
3472 boolean isRestrictedBackupMode = false;
3473 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3474 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3475 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3476 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003477
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003478 ensurePackageDexOpt(app.instrumentationInfo != null
3479 ? app.instrumentationInfo.packageName
3480 : app.info.packageName);
3481 if (app.instrumentationClass != null) {
3482 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003483 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003484 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003485 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003486 thread.bindApplication(processName, app.instrumentationInfo != null
3487 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 app.instrumentationClass, app.instrumentationProfileFile,
3489 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003490 isRestrictedBackupMode || !normalMode,
3491 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003492 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003493 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 } catch (Exception e) {
3495 // todo: Yikes! What should we do? For now we will try to
3496 // start another process, but that could easily get us in
3497 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003498 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499
3500 app.resetPackageList();
3501 startProcessLocked(app, "bind fail", processName);
3502 return false;
3503 }
3504
3505 // Remove this record from the list of starting applications.
3506 mPersistentStartingProcesses.remove(app);
3507 mProcessesOnHold.remove(app);
3508
3509 boolean badApp = false;
3510 boolean didSomething = false;
3511
3512 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003513 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003514 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3516 && processName.equals(hr.processName)) {
3517 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003518 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 didSomething = true;
3520 }
3521 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003522 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 + hr.intent.getComponent().flattenToShortString(), e);
3524 badApp = true;
3525 }
3526 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003527 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 }
3529 }
3530
3531 // Find any services that should be running in this process...
3532 if (!badApp && mPendingServices.size() > 0) {
3533 ServiceRecord sr = null;
3534 try {
3535 for (int i=0; i<mPendingServices.size(); i++) {
3536 sr = mPendingServices.get(i);
3537 if (app.info.uid != sr.appInfo.uid
3538 || !processName.equals(sr.processName)) {
3539 continue;
3540 }
3541
3542 mPendingServices.remove(i);
3543 i--;
3544 realStartServiceLocked(sr, app);
3545 didSomething = true;
3546 }
3547 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003548 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003549 + sr.shortName, e);
3550 badApp = true;
3551 }
3552 }
3553
3554 // Check if the next broadcast receiver is in this process...
3555 BroadcastRecord br = mPendingBroadcast;
3556 if (!badApp && br != null && br.curApp == app) {
3557 try {
3558 mPendingBroadcast = null;
3559 processCurBroadcastLocked(br, app);
3560 didSomething = true;
3561 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003562 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563 + br.curComponent.flattenToShortString(), e);
3564 badApp = true;
3565 logBroadcastReceiverDiscard(br);
3566 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3567 br.resultExtras, br.resultAbort, true);
3568 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003569 // We need to reset the state if we fails to start the receiver.
3570 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003571 }
3572 }
3573
Christopher Tate181fafa2009-05-14 11:12:14 -07003574 // Check whether the next backup agent is in this process...
3575 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003576 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003577 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003578 try {
3579 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3580 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003581 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003582 e.printStackTrace();
3583 }
3584 }
3585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 if (badApp) {
3587 // todo: Also need to kill application to deal with all
3588 // kinds of exceptions.
3589 handleAppDiedLocked(app, false);
3590 return false;
3591 }
3592
3593 if (!didSomething) {
3594 updateOomAdjLocked();
3595 }
3596
3597 return true;
3598 }
3599
3600 public final void attachApplication(IApplicationThread thread) {
3601 synchronized (this) {
3602 int callingPid = Binder.getCallingPid();
3603 final long origId = Binder.clearCallingIdentity();
3604 attachApplicationLocked(thread, callingPid);
3605 Binder.restoreCallingIdentity(origId);
3606 }
3607 }
3608
Dianne Hackborne88846e2009-09-30 21:34:25 -07003609 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003611 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003612 Binder.restoreCallingIdentity(origId);
3613 }
3614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003616 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003617 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 mWindowManager.enableScreenAfterBoot();
3619 }
3620
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003621 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003622 IntentFilter pkgFilter = new IntentFilter();
3623 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3624 pkgFilter.addDataScheme("package");
3625 mContext.registerReceiver(new BroadcastReceiver() {
3626 @Override
3627 public void onReceive(Context context, Intent intent) {
3628 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3629 if (pkgs != null) {
3630 for (String pkg : pkgs) {
3631 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3632 setResultCode(Activity.RESULT_OK);
3633 return;
3634 }
3635 }
3636 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003637 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003638 }, pkgFilter);
3639
3640 synchronized (this) {
3641 // Ensure that any processes we had put on hold are now started
3642 // up.
3643 final int NP = mProcessesOnHold.size();
3644 if (NP > 0) {
3645 ArrayList<ProcessRecord> procs =
3646 new ArrayList<ProcessRecord>(mProcessesOnHold);
3647 for (int ip=0; ip<NP; ip++) {
3648 this.startProcessLocked(procs.get(ip), "on-hold", null);
3649 }
3650 }
3651
3652 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003653 // Start looking for apps that are abusing wake locks.
3654 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
3655 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003656 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003657 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003658 broadcastIntentLocked(null, null,
3659 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3660 null, null, 0, null, null,
3661 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3662 false, false, MY_PID, Process.SYSTEM_UID);
3663 }
3664 }
3665 }
3666
3667 final void ensureBootCompleted() {
3668 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003669 boolean enableScreen;
3670 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003671 booting = mBooting;
3672 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003673 enableScreen = !mBooted;
3674 mBooted = true;
3675 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003676
3677 if (booting) {
3678 finishBooting();
3679 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003680
3681 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003682 enableScreenAfterBoot();
3683 }
3684 }
3685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 public final void activityPaused(IBinder token, Bundle icicle) {
3687 // Refuse possible leaked file descriptors
3688 if (icicle != null && icicle.hasFileDescriptors()) {
3689 throw new IllegalArgumentException("File descriptors passed in Bundle");
3690 }
3691
3692 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003693 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 Binder.restoreCallingIdentity(origId);
3695 }
3696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 public final void activityStopped(IBinder token, Bitmap thumbnail,
3698 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003699 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003700 TAG, "Activity stopped: token=" + token);
3701
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003702 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003703
3704 final long origId = Binder.clearCallingIdentity();
3705
3706 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003707 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003709 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 r.thumbnail = thumbnail;
3711 r.description = description;
3712 r.stopped = true;
3713 r.state = ActivityState.STOPPED;
3714 if (!r.finishing) {
3715 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003716 r.stack.destroyActivityLocked(r, true);
3717 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 }
3719 }
3720 }
3721 }
3722
3723 if (r != null) {
3724 sendPendingThumbnail(r, null, null, null, false);
3725 }
3726
3727 trimApplications();
3728
3729 Binder.restoreCallingIdentity(origId);
3730 }
3731
3732 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003733 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003734 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003735 }
3736
3737 public String getCallingPackage(IBinder token) {
3738 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003739 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003740 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 }
3742 }
3743
3744 public ComponentName getCallingActivity(IBinder token) {
3745 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003746 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003747 return r != null ? r.intent.getComponent() : null;
3748 }
3749 }
3750
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003751 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003752 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003753 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003754 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 if (r != null) {
3756 return r.resultTo;
3757 }
3758 }
3759 return null;
3760 }
3761
3762 public ComponentName getActivityClassForToken(IBinder token) {
3763 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003764 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003766 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 return r.intent.getComponent();
3768 }
3769 return null;
3770 }
3771 }
3772
3773 public String getPackageForToken(IBinder token) {
3774 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003775 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003777 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 return r.packageName;
3779 }
3780 return null;
3781 }
3782 }
3783
3784 public IIntentSender getIntentSender(int type,
3785 String packageName, IBinder token, String resultWho,
3786 int requestCode, Intent intent, String resolvedType, int flags) {
3787 // Refuse possible leaked file descriptors
3788 if (intent != null && intent.hasFileDescriptors() == true) {
3789 throw new IllegalArgumentException("File descriptors passed in Intent");
3790 }
3791
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003792 if (type == INTENT_SENDER_BROADCAST) {
3793 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3794 throw new IllegalArgumentException(
3795 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3796 }
3797 }
3798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 synchronized(this) {
3800 int callingUid = Binder.getCallingUid();
3801 try {
3802 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3803 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003804 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 .getPackageUid(packageName);
3806 if (uid != Binder.getCallingUid()) {
3807 String msg = "Permission Denial: getIntentSender() from pid="
3808 + Binder.getCallingPid()
3809 + ", uid=" + Binder.getCallingUid()
3810 + ", (need uid=" + uid + ")"
3811 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003812 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 throw new SecurityException(msg);
3814 }
3815 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003816
3817 return getIntentSenderLocked(type, packageName, callingUid,
3818 token, resultWho, requestCode, intent, resolvedType, flags);
3819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 } catch (RemoteException e) {
3821 throw new SecurityException(e);
3822 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003823 }
3824 }
3825
3826 IIntentSender getIntentSenderLocked(int type,
3827 String packageName, int callingUid, IBinder token, String resultWho,
3828 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003829 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003830 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003831 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003832 if (index < 0) {
3833 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003834 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003835 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003836 if (activity.finishing) {
3837 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003839 }
3840
3841 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3842 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3843 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3844 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3845 |PendingIntent.FLAG_UPDATE_CURRENT);
3846
3847 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3848 type, packageName, activity, resultWho,
3849 requestCode, intent, resolvedType, flags);
3850 WeakReference<PendingIntentRecord> ref;
3851 ref = mIntentSenderRecords.get(key);
3852 PendingIntentRecord rec = ref != null ? ref.get() : null;
3853 if (rec != null) {
3854 if (!cancelCurrent) {
3855 if (updateCurrent) {
3856 rec.key.requestIntent.replaceExtras(intent);
3857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003858 return rec;
3859 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003860 rec.canceled = true;
3861 mIntentSenderRecords.remove(key);
3862 }
3863 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 return rec;
3865 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003866 rec = new PendingIntentRecord(this, key, callingUid);
3867 mIntentSenderRecords.put(key, rec.ref);
3868 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3869 if (activity.pendingResults == null) {
3870 activity.pendingResults
3871 = new HashSet<WeakReference<PendingIntentRecord>>();
3872 }
3873 activity.pendingResults.add(rec.ref);
3874 }
3875 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876 }
3877
3878 public void cancelIntentSender(IIntentSender sender) {
3879 if (!(sender instanceof PendingIntentRecord)) {
3880 return;
3881 }
3882 synchronized(this) {
3883 PendingIntentRecord rec = (PendingIntentRecord)sender;
3884 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003885 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 .getPackageUid(rec.key.packageName);
3887 if (uid != Binder.getCallingUid()) {
3888 String msg = "Permission Denial: cancelIntentSender() from pid="
3889 + Binder.getCallingPid()
3890 + ", uid=" + Binder.getCallingUid()
3891 + " is not allowed to cancel packges "
3892 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003893 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 throw new SecurityException(msg);
3895 }
3896 } catch (RemoteException e) {
3897 throw new SecurityException(e);
3898 }
3899 cancelIntentSenderLocked(rec, true);
3900 }
3901 }
3902
3903 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3904 rec.canceled = true;
3905 mIntentSenderRecords.remove(rec.key);
3906 if (cleanActivity && rec.key.activity != null) {
3907 rec.key.activity.pendingResults.remove(rec.ref);
3908 }
3909 }
3910
3911 public String getPackageForIntentSender(IIntentSender pendingResult) {
3912 if (!(pendingResult instanceof PendingIntentRecord)) {
3913 return null;
3914 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003915 try {
3916 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3917 return res.key.packageName;
3918 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919 }
3920 return null;
3921 }
3922
3923 public void setProcessLimit(int max) {
3924 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3925 "setProcessLimit()");
3926 mProcessLimit = max;
3927 }
3928
3929 public int getProcessLimit() {
3930 return mProcessLimit;
3931 }
3932
3933 void foregroundTokenDied(ForegroundToken token) {
3934 synchronized (ActivityManagerService.this) {
3935 synchronized (mPidsSelfLocked) {
3936 ForegroundToken cur
3937 = mForegroundProcesses.get(token.pid);
3938 if (cur != token) {
3939 return;
3940 }
3941 mForegroundProcesses.remove(token.pid);
3942 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3943 if (pr == null) {
3944 return;
3945 }
3946 pr.forcingToForeground = null;
3947 pr.foregroundServices = false;
3948 }
3949 updateOomAdjLocked();
3950 }
3951 }
3952
3953 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3954 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3955 "setProcessForeground()");
3956 synchronized(this) {
3957 boolean changed = false;
3958
3959 synchronized (mPidsSelfLocked) {
3960 ProcessRecord pr = mPidsSelfLocked.get(pid);
3961 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003962 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 return;
3964 }
3965 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3966 if (oldToken != null) {
3967 oldToken.token.unlinkToDeath(oldToken, 0);
3968 mForegroundProcesses.remove(pid);
3969 pr.forcingToForeground = null;
3970 changed = true;
3971 }
3972 if (isForeground && token != null) {
3973 ForegroundToken newToken = new ForegroundToken() {
3974 public void binderDied() {
3975 foregroundTokenDied(this);
3976 }
3977 };
3978 newToken.pid = pid;
3979 newToken.token = token;
3980 try {
3981 token.linkToDeath(newToken, 0);
3982 mForegroundProcesses.put(pid, newToken);
3983 pr.forcingToForeground = token;
3984 changed = true;
3985 } catch (RemoteException e) {
3986 // If the process died while doing this, we will later
3987 // do the cleanup with the process death link.
3988 }
3989 }
3990 }
3991
3992 if (changed) {
3993 updateOomAdjLocked();
3994 }
3995 }
3996 }
3997
3998 // =========================================================
3999 // PERMISSIONS
4000 // =========================================================
4001
4002 static class PermissionController extends IPermissionController.Stub {
4003 ActivityManagerService mActivityManagerService;
4004 PermissionController(ActivityManagerService activityManagerService) {
4005 mActivityManagerService = activityManagerService;
4006 }
4007
4008 public boolean checkPermission(String permission, int pid, int uid) {
4009 return mActivityManagerService.checkPermission(permission, pid,
4010 uid) == PackageManager.PERMISSION_GRANTED;
4011 }
4012 }
4013
4014 /**
4015 * This can be called with or without the global lock held.
4016 */
4017 int checkComponentPermission(String permission, int pid, int uid,
4018 int reqUid) {
4019 // We might be performing an operation on behalf of an indirect binder
4020 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4021 // client identity accordingly before proceeding.
4022 Identity tlsIdentity = sCallerIdentity.get();
4023 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004024 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004025 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4026 uid = tlsIdentity.uid;
4027 pid = tlsIdentity.pid;
4028 }
4029
4030 // Root, system server and our own process get to do everything.
4031 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4032 !Process.supportsProcesses()) {
4033 return PackageManager.PERMISSION_GRANTED;
4034 }
4035 // If the target requires a specific UID, always fail for others.
4036 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004037 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 return PackageManager.PERMISSION_DENIED;
4039 }
4040 if (permission == null) {
4041 return PackageManager.PERMISSION_GRANTED;
4042 }
4043 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004044 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004045 .checkUidPermission(permission, uid);
4046 } catch (RemoteException e) {
4047 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004048 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 }
4050 return PackageManager.PERMISSION_DENIED;
4051 }
4052
4053 /**
4054 * As the only public entry point for permissions checking, this method
4055 * can enforce the semantic that requesting a check on a null global
4056 * permission is automatically denied. (Internally a null permission
4057 * string is used when calling {@link #checkComponentPermission} in cases
4058 * when only uid-based security is needed.)
4059 *
4060 * This can be called with or without the global lock held.
4061 */
4062 public int checkPermission(String permission, int pid, int uid) {
4063 if (permission == null) {
4064 return PackageManager.PERMISSION_DENIED;
4065 }
4066 return checkComponentPermission(permission, pid, uid, -1);
4067 }
4068
4069 /**
4070 * Binder IPC calls go through the public entry point.
4071 * This can be called with or without the global lock held.
4072 */
4073 int checkCallingPermission(String permission) {
4074 return checkPermission(permission,
4075 Binder.getCallingPid(),
4076 Binder.getCallingUid());
4077 }
4078
4079 /**
4080 * This can be called with or without the global lock held.
4081 */
4082 void enforceCallingPermission(String permission, String func) {
4083 if (checkCallingPermission(permission)
4084 == PackageManager.PERMISSION_GRANTED) {
4085 return;
4086 }
4087
4088 String msg = "Permission Denial: " + func + " from pid="
4089 + Binder.getCallingPid()
4090 + ", uid=" + Binder.getCallingUid()
4091 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004092 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 throw new SecurityException(msg);
4094 }
4095
4096 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4097 ProviderInfo pi, int uid, int modeFlags) {
4098 try {
4099 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4100 if ((pi.readPermission != null) &&
4101 (pm.checkUidPermission(pi.readPermission, uid)
4102 != PackageManager.PERMISSION_GRANTED)) {
4103 return false;
4104 }
4105 }
4106 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4107 if ((pi.writePermission != null) &&
4108 (pm.checkUidPermission(pi.writePermission, uid)
4109 != PackageManager.PERMISSION_GRANTED)) {
4110 return false;
4111 }
4112 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004113 if (!pi.exported && pi.applicationInfo.uid != uid) {
4114 return false;
4115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 return true;
4117 } catch (RemoteException e) {
4118 return false;
4119 }
4120 }
4121
4122 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4123 int modeFlags) {
4124 // Root gets to do everything.
4125 if (uid == 0 || !Process.supportsProcesses()) {
4126 return true;
4127 }
4128 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4129 if (perms == null) return false;
4130 UriPermission perm = perms.get(uri);
4131 if (perm == null) return false;
4132 return (modeFlags&perm.modeFlags) == modeFlags;
4133 }
4134
4135 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4136 // Another redirected-binder-call permissions check as in
4137 // {@link checkComponentPermission}.
4138 Identity tlsIdentity = sCallerIdentity.get();
4139 if (tlsIdentity != null) {
4140 uid = tlsIdentity.uid;
4141 pid = tlsIdentity.pid;
4142 }
4143
4144 // Our own process gets to do everything.
4145 if (pid == MY_PID) {
4146 return PackageManager.PERMISSION_GRANTED;
4147 }
4148 synchronized(this) {
4149 return checkUriPermissionLocked(uri, uid, modeFlags)
4150 ? PackageManager.PERMISSION_GRANTED
4151 : PackageManager.PERMISSION_DENIED;
4152 }
4153 }
4154
Dianne Hackborn39792d22010-08-19 18:01:52 -07004155 /**
4156 * Check if the targetPkg can be granted permission to access uri by
4157 * the callingUid using the given modeFlags. Throws a security exception
4158 * if callingUid is not allowed to do this. Returns the uid of the target
4159 * if the URI permission grant should be performed; returns -1 if it is not
4160 * needed (for example targetPkg already has permission to access the URI).
4161 */
4162 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4163 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004164 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4165 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4166 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004167 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 }
4169
Joe Onorato8a9b2202010-02-26 18:56:32 -08004170 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004171 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004172
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004173 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174
4175 // If this is not a content: uri, we can't do anything with it.
4176 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004177 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004178 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004179 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 }
4181
4182 String name = uri.getAuthority();
4183 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004184 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004185 if (cpr != null) {
4186 pi = cpr.info;
4187 } else {
4188 try {
4189 pi = pm.resolveContentProvider(name,
4190 PackageManager.GET_URI_PERMISSION_PATTERNS);
4191 } catch (RemoteException ex) {
4192 }
4193 }
4194 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004195 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004196 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 }
4198
4199 int targetUid;
4200 try {
4201 targetUid = pm.getPackageUid(targetPkg);
4202 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004203 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004204 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004205 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206 }
4207 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004208 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004209 }
4210
4211 // First... does the target actually need this permission?
4212 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4213 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004214 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004215 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004216 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 }
4218
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004219 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004220 if (!pi.grantUriPermissions) {
4221 throw new SecurityException("Provider " + pi.packageName
4222 + "/" + pi.name
4223 + " does not allow granting of Uri permissions (uri "
4224 + uri + ")");
4225 }
4226 if (pi.uriPermissionPatterns != null) {
4227 final int N = pi.uriPermissionPatterns.length;
4228 boolean allowed = false;
4229 for (int i=0; i<N; i++) {
4230 if (pi.uriPermissionPatterns[i] != null
4231 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4232 allowed = true;
4233 break;
4234 }
4235 }
4236 if (!allowed) {
4237 throw new SecurityException("Provider " + pi.packageName
4238 + "/" + pi.name
4239 + " does not allow granting of permission to path of Uri "
4240 + uri);
4241 }
4242 }
4243
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004244 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 // this uri?
4246 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4247 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4248 throw new SecurityException("Uid " + callingUid
4249 + " does not have permission to uri " + uri);
4250 }
4251 }
4252
Dianne Hackborn39792d22010-08-19 18:01:52 -07004253 return targetUid;
4254 }
4255
4256 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4257 Uri uri, int modeFlags, UriPermissionOwner owner) {
4258 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4259 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4260 if (modeFlags == 0) {
4261 return;
4262 }
4263
4264 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 // to the uri, and the target doesn't. Let's now give this to
4266 // the target.
4267
Joe Onorato8a9b2202010-02-26 18:56:32 -08004268 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004269 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 HashMap<Uri, UriPermission> targetUris
4272 = mGrantedUriPermissions.get(targetUid);
4273 if (targetUris == null) {
4274 targetUris = new HashMap<Uri, UriPermission>();
4275 mGrantedUriPermissions.put(targetUid, targetUris);
4276 }
4277
4278 UriPermission perm = targetUris.get(uri);
4279 if (perm == null) {
4280 perm = new UriPermission(targetUid, uri);
4281 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004284 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004285 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 perm.globalModeFlags |= modeFlags;
4287 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004288 perm.readOwners.add(owner);
4289 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004291 perm.writeOwners.add(owner);
4292 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 }
4294 }
4295
Dianne Hackborn39792d22010-08-19 18:01:52 -07004296 void grantUriPermissionLocked(int callingUid,
4297 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4298 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4299 if (targetUid < 0) {
4300 return;
4301 }
4302
4303 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4304 }
4305
4306 /**
4307 * Like checkGrantUriPermissionLocked, but takes an Intent.
4308 */
4309 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4310 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004311 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004312 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004313 + " from " + intent + "; flags=0x"
4314 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004317 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 }
4319 Uri data = intent.getData();
4320 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004321 return -1;
4322 }
4323 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4324 intent.getFlags());
4325 }
4326
4327 /**
4328 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4329 */
4330 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4331 String targetPkg, Intent intent, UriPermissionOwner owner) {
4332 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4333 intent.getFlags(), owner);
4334 }
4335
4336 void grantUriPermissionFromIntentLocked(int callingUid,
4337 String targetPkg, Intent intent, UriPermissionOwner owner) {
4338 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4339 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 return;
4341 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004342
4343 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 }
4345
4346 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4347 Uri uri, int modeFlags) {
4348 synchronized(this) {
4349 final ProcessRecord r = getRecordForAppLocked(caller);
4350 if (r == null) {
4351 throw new SecurityException("Unable to find app for caller "
4352 + caller
4353 + " when granting permission to uri " + uri);
4354 }
4355 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004356 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 }
4358 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004359 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 }
4361
4362 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4363 null);
4364 }
4365 }
4366
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004367 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4369 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4370 HashMap<Uri, UriPermission> perms
4371 = mGrantedUriPermissions.get(perm.uid);
4372 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004373 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004374 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004375 perms.remove(perm.uri);
4376 if (perms.size() == 0) {
4377 mGrantedUriPermissions.remove(perm.uid);
4378 }
4379 }
4380 }
4381 }
4382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4384 int modeFlags) {
4385 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4386 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4387 if (modeFlags == 0) {
4388 return;
4389 }
4390
Joe Onorato8a9b2202010-02-26 18:56:32 -08004391 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004392 "Revoking all granted permissions to " + uri);
4393
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004394 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395
4396 final String authority = uri.getAuthority();
4397 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004398 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399 if (cpr != null) {
4400 pi = cpr.info;
4401 } else {
4402 try {
4403 pi = pm.resolveContentProvider(authority,
4404 PackageManager.GET_URI_PERMISSION_PATTERNS);
4405 } catch (RemoteException ex) {
4406 }
4407 }
4408 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004409 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 return;
4411 }
4412
4413 // Does the caller have this permission on the URI?
4414 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4415 // Right now, if you are not the original owner of the permission,
4416 // you are not allowed to revoke it.
4417 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4418 throw new SecurityException("Uid " + callingUid
4419 + " does not have permission to uri " + uri);
4420 //}
4421 }
4422
4423 // Go through all of the permissions and remove any that match.
4424 final List<String> SEGMENTS = uri.getPathSegments();
4425 if (SEGMENTS != null) {
4426 final int NS = SEGMENTS.size();
4427 int N = mGrantedUriPermissions.size();
4428 for (int i=0; i<N; i++) {
4429 HashMap<Uri, UriPermission> perms
4430 = mGrantedUriPermissions.valueAt(i);
4431 Iterator<UriPermission> it = perms.values().iterator();
4432 toploop:
4433 while (it.hasNext()) {
4434 UriPermission perm = it.next();
4435 Uri targetUri = perm.uri;
4436 if (!authority.equals(targetUri.getAuthority())) {
4437 continue;
4438 }
4439 List<String> targetSegments = targetUri.getPathSegments();
4440 if (targetSegments == null) {
4441 continue;
4442 }
4443 if (targetSegments.size() < NS) {
4444 continue;
4445 }
4446 for (int j=0; j<NS; j++) {
4447 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4448 continue toploop;
4449 }
4450 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004451 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004452 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 perm.clearModes(modeFlags);
4454 if (perm.modeFlags == 0) {
4455 it.remove();
4456 }
4457 }
4458 if (perms.size() == 0) {
4459 mGrantedUriPermissions.remove(
4460 mGrantedUriPermissions.keyAt(i));
4461 N--;
4462 i--;
4463 }
4464 }
4465 }
4466 }
4467
4468 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4469 int modeFlags) {
4470 synchronized(this) {
4471 final ProcessRecord r = getRecordForAppLocked(caller);
4472 if (r == null) {
4473 throw new SecurityException("Unable to find app for caller "
4474 + caller
4475 + " when revoking permission to uri " + uri);
4476 }
4477 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004478 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 return;
4480 }
4481
4482 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4483 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4484 if (modeFlags == 0) {
4485 return;
4486 }
4487
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004488 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489
4490 final String authority = uri.getAuthority();
4491 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004492 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 if (cpr != null) {
4494 pi = cpr.info;
4495 } else {
4496 try {
4497 pi = pm.resolveContentProvider(authority,
4498 PackageManager.GET_URI_PERMISSION_PATTERNS);
4499 } catch (RemoteException ex) {
4500 }
4501 }
4502 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004503 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504 return;
4505 }
4506
4507 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4508 }
4509 }
4510
Dianne Hackborn7e269642010-08-25 19:50:20 -07004511 @Override
4512 public IBinder newUriPermissionOwner(String name) {
4513 synchronized(this) {
4514 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4515 return owner.getExternalTokenLocked();
4516 }
4517 }
4518
4519 @Override
4520 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4521 Uri uri, int modeFlags) {
4522 synchronized(this) {
4523 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4524 if (owner == null) {
4525 throw new IllegalArgumentException("Unknown owner: " + token);
4526 }
4527 if (fromUid != Binder.getCallingUid()) {
4528 if (Binder.getCallingUid() != Process.myUid()) {
4529 // Only system code can grant URI permissions on behalf
4530 // of other users.
4531 throw new SecurityException("nice try");
4532 }
4533 }
4534 if (targetPkg == null) {
4535 throw new IllegalArgumentException("null target");
4536 }
4537 if (uri == null) {
4538 throw new IllegalArgumentException("null uri");
4539 }
4540
4541 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4542 }
4543 }
4544
4545 @Override
4546 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4547 synchronized(this) {
4548 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4549 if (owner == null) {
4550 throw new IllegalArgumentException("Unknown owner: " + token);
4551 }
4552
4553 if (uri == null) {
4554 owner.removeUriPermissionsLocked(mode);
4555 } else {
4556 owner.removeUriPermissionLocked(uri, mode);
4557 }
4558 }
4559 }
4560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4562 synchronized (this) {
4563 ProcessRecord app =
4564 who != null ? getRecordForAppLocked(who) : null;
4565 if (app == null) return;
4566
4567 Message msg = Message.obtain();
4568 msg.what = WAIT_FOR_DEBUGGER_MSG;
4569 msg.obj = app;
4570 msg.arg1 = waiting ? 1 : 0;
4571 mHandler.sendMessage(msg);
4572 }
4573 }
4574
4575 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4576 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004577 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004578 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004579 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004580 }
4581
4582 // =========================================================
4583 // TASK MANAGEMENT
4584 // =========================================================
4585
4586 public List getTasks(int maxNum, int flags,
4587 IThumbnailReceiver receiver) {
4588 ArrayList list = new ArrayList();
4589
4590 PendingThumbnailsRecord pending = null;
4591 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004592 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593
4594 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004595 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004596 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4597 + ", receiver=" + receiver);
4598
4599 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4600 != PackageManager.PERMISSION_GRANTED) {
4601 if (receiver != null) {
4602 // If the caller wants to wait for pending thumbnails,
4603 // it ain't gonna get them.
4604 try {
4605 receiver.finished();
4606 } catch (RemoteException ex) {
4607 }
4608 }
4609 String msg = "Permission Denial: getTasks() from pid="
4610 + Binder.getCallingPid()
4611 + ", uid=" + Binder.getCallingUid()
4612 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004613 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 throw new SecurityException(msg);
4615 }
4616
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004617 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004618 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004619 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004620 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004621 CharSequence topDescription = null;
4622 TaskRecord curTask = null;
4623 int numActivities = 0;
4624 int numRunning = 0;
4625 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004626 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004628 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629
4630 // Initialize state for next task if needed.
4631 if (top == null ||
4632 (top.state == ActivityState.INITIALIZING
4633 && top.task == r.task)) {
4634 top = r;
4635 topDescription = r.description;
4636 curTask = r.task;
4637 numActivities = numRunning = 0;
4638 }
4639
4640 // Add 'r' into the current task.
4641 numActivities++;
4642 if (r.app != null && r.app.thread != null) {
4643 numRunning++;
4644 }
4645 if (topDescription == null) {
4646 topDescription = r.description;
4647 }
4648
Joe Onorato8a9b2202010-02-26 18:56:32 -08004649 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 TAG, r.intent.getComponent().flattenToShortString()
4651 + ": task=" + r.task);
4652
4653 // If the next one is a different task, generate a new
4654 // TaskInfo entry for what we have.
4655 if (next == null || next.task != curTask) {
4656 ActivityManager.RunningTaskInfo ci
4657 = new ActivityManager.RunningTaskInfo();
4658 ci.id = curTask.taskId;
4659 ci.baseActivity = r.intent.getComponent();
4660 ci.topActivity = top.intent.getComponent();
4661 ci.thumbnail = top.thumbnail;
4662 ci.description = topDescription;
4663 ci.numActivities = numActivities;
4664 ci.numRunning = numRunning;
4665 //System.out.println(
4666 // "#" + maxNum + ": " + " descr=" + ci.description);
4667 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004668 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004669 TAG, "State=" + top.state + "Idle=" + top.idle
4670 + " app=" + top.app
4671 + " thr=" + (top.app != null ? top.app.thread : null));
4672 if (top.state == ActivityState.RESUMED
4673 || top.state == ActivityState.PAUSING) {
4674 if (top.idle && top.app != null
4675 && top.app.thread != null) {
4676 topRecord = top;
4677 topThumbnail = top.app.thread;
4678 } else {
4679 top.thumbnailNeeded = true;
4680 }
4681 }
4682 if (pending == null) {
4683 pending = new PendingThumbnailsRecord(receiver);
4684 }
4685 pending.pendingRecords.add(top);
4686 }
4687 list.add(ci);
4688 maxNum--;
4689 top = null;
4690 }
4691 }
4692
4693 if (pending != null) {
4694 mPendingThumbnails.add(pending);
4695 }
4696 }
4697
Joe Onorato8a9b2202010-02-26 18:56:32 -08004698 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004699
4700 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004701 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 try {
4703 topThumbnail.requestThumbnail(topRecord);
4704 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004705 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004706 sendPendingThumbnail(null, topRecord, null, null, true);
4707 }
4708 }
4709
4710 if (pending == null && receiver != null) {
4711 // In this case all thumbnails were available and the client
4712 // is being asked to be told when the remaining ones come in...
4713 // which is unusually, since the top-most currently running
4714 // activity should never have a canned thumbnail! Oh well.
4715 try {
4716 receiver.finished();
4717 } catch (RemoteException ex) {
4718 }
4719 }
4720
4721 return list;
4722 }
4723
4724 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4725 int flags) {
4726 synchronized (this) {
4727 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4728 "getRecentTasks()");
4729
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004730 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 final int N = mRecentTasks.size();
4733 ArrayList<ActivityManager.RecentTaskInfo> res
4734 = new ArrayList<ActivityManager.RecentTaskInfo>(
4735 maxNum < N ? maxNum : N);
4736 for (int i=0; i<N && maxNum > 0; i++) {
4737 TaskRecord tr = mRecentTasks.get(i);
4738 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4739 || (tr.intent == null)
4740 || ((tr.intent.getFlags()
4741 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4742 ActivityManager.RecentTaskInfo rti
4743 = new ActivityManager.RecentTaskInfo();
4744 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4745 rti.baseIntent = new Intent(
4746 tr.intent != null ? tr.intent : tr.affinityIntent);
4747 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004748
4749 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4750 // Check whether this activity is currently available.
4751 try {
4752 if (rti.origActivity != null) {
4753 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4754 continue;
4755 }
4756 } else if (rti.baseIntent != null) {
4757 if (pm.queryIntentActivities(rti.baseIntent,
4758 null, 0) == null) {
4759 continue;
4760 }
4761 }
4762 } catch (RemoteException e) {
4763 // Will never happen.
4764 }
4765 }
4766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 res.add(rti);
4768 maxNum--;
4769 }
4770 }
4771 return res;
4772 }
4773 }
4774
4775 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4776 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004777 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004778 TaskRecord jt = startTask;
4779
4780 // First look backwards
4781 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004782 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 if (r.task != jt) {
4784 jt = r.task;
4785 if (affinity.equals(jt.affinity)) {
4786 return j;
4787 }
4788 }
4789 }
4790
4791 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004792 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 jt = startTask;
4794 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004795 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 if (r.task != jt) {
4797 if (affinity.equals(jt.affinity)) {
4798 return j;
4799 }
4800 jt = r.task;
4801 }
4802 }
4803
4804 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004805 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 return N-1;
4807 }
4808
4809 return -1;
4810 }
4811
4812 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004813 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 */
4815 public void moveTaskToFront(int task) {
4816 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4817 "moveTaskToFront()");
4818
4819 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004820 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4821 Binder.getCallingUid(), "Task to front")) {
4822 return;
4823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824 final long origId = Binder.clearCallingIdentity();
4825 try {
4826 int N = mRecentTasks.size();
4827 for (int i=0; i<N; i++) {
4828 TaskRecord tr = mRecentTasks.get(i);
4829 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004830 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004831 return;
4832 }
4833 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004834 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4835 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004836 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004837 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 return;
4839 }
4840 }
4841 } finally {
4842 Binder.restoreCallingIdentity(origId);
4843 }
4844 }
4845 }
4846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 public void moveTaskToBack(int task) {
4848 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4849 "moveTaskToBack()");
4850
4851 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004852 if (mMainStack.mResumedActivity != null
4853 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004854 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4855 Binder.getCallingUid(), "Task to back")) {
4856 return;
4857 }
4858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004859 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004860 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004861 Binder.restoreCallingIdentity(origId);
4862 }
4863 }
4864
4865 /**
4866 * Moves an activity, and all of the other activities within the same task, to the bottom
4867 * of the history stack. The activity's order within the task is unchanged.
4868 *
4869 * @param token A reference to the activity we wish to move
4870 * @param nonRoot If false then this only works if the activity is the root
4871 * of a task; if true it will work for any activity in a task.
4872 * @return Returns true if the move completed, false if not.
4873 */
4874 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4875 synchronized(this) {
4876 final long origId = Binder.clearCallingIdentity();
4877 int taskId = getTaskForActivityLocked(token, !nonRoot);
4878 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004879 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 }
4881 Binder.restoreCallingIdentity(origId);
4882 }
4883 return false;
4884 }
4885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 public void moveTaskBackwards(int task) {
4887 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4888 "moveTaskBackwards()");
4889
4890 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004891 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4892 Binder.getCallingUid(), "Task backwards")) {
4893 return;
4894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 final long origId = Binder.clearCallingIdentity();
4896 moveTaskBackwardsLocked(task);
4897 Binder.restoreCallingIdentity(origId);
4898 }
4899 }
4900
4901 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004902 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004903 }
4904
4905 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4906 synchronized(this) {
4907 return getTaskForActivityLocked(token, onlyRoot);
4908 }
4909 }
4910
4911 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004912 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004913 TaskRecord lastTask = null;
4914 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004915 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004916 if (r == token) {
4917 if (!onlyRoot || lastTask != r.task) {
4918 return r.task.taskId;
4919 }
4920 return -1;
4921 }
4922 lastTask = r.task;
4923 }
4924
4925 return -1;
4926 }
4927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 public void finishOtherInstances(IBinder token, ComponentName className) {
4929 synchronized(this) {
4930 final long origId = Binder.clearCallingIdentity();
4931
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004932 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 TaskRecord lastTask = null;
4934 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004935 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 if (r.realActivity.equals(className)
4937 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004938 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 null, "others")) {
4940 i--;
4941 N--;
4942 }
4943 }
4944 lastTask = r.task;
4945 }
4946
4947 Binder.restoreCallingIdentity(origId);
4948 }
4949 }
4950
4951 // =========================================================
4952 // THUMBNAILS
4953 // =========================================================
4954
4955 public void reportThumbnail(IBinder token,
4956 Bitmap thumbnail, CharSequence description) {
4957 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4958 final long origId = Binder.clearCallingIdentity();
4959 sendPendingThumbnail(null, token, thumbnail, description, true);
4960 Binder.restoreCallingIdentity(origId);
4961 }
4962
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004963 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 Bitmap thumbnail, CharSequence description, boolean always) {
4965 TaskRecord task = null;
4966 ArrayList receivers = null;
4967
4968 //System.out.println("Send pending thumbnail: " + r);
4969
4970 synchronized(this) {
4971 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004972 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004973 if (index < 0) {
4974 return;
4975 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004976 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 }
4978 if (thumbnail == null) {
4979 thumbnail = r.thumbnail;
4980 description = r.description;
4981 }
4982 if (thumbnail == null && !always) {
4983 // If there is no thumbnail, and this entry is not actually
4984 // going away, then abort for now and pick up the next
4985 // thumbnail we get.
4986 return;
4987 }
4988 task = r.task;
4989
4990 int N = mPendingThumbnails.size();
4991 int i=0;
4992 while (i<N) {
4993 PendingThumbnailsRecord pr =
4994 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4995 //System.out.println("Looking in " + pr.pendingRecords);
4996 if (pr.pendingRecords.remove(r)) {
4997 if (receivers == null) {
4998 receivers = new ArrayList();
4999 }
5000 receivers.add(pr);
5001 if (pr.pendingRecords.size() == 0) {
5002 pr.finished = true;
5003 mPendingThumbnails.remove(i);
5004 N--;
5005 continue;
5006 }
5007 }
5008 i++;
5009 }
5010 }
5011
5012 if (receivers != null) {
5013 final int N = receivers.size();
5014 for (int i=0; i<N; i++) {
5015 try {
5016 PendingThumbnailsRecord pr =
5017 (PendingThumbnailsRecord)receivers.get(i);
5018 pr.receiver.newThumbnail(
5019 task != null ? task.taskId : -1, thumbnail, description);
5020 if (pr.finished) {
5021 pr.receiver.finished();
5022 }
5023 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005024 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 }
5026 }
5027 }
5028 }
5029
5030 // =========================================================
5031 // CONTENT PROVIDERS
5032 // =========================================================
5033
5034 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5035 List providers = null;
5036 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005037 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005039 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005040 } catch (RemoteException ex) {
5041 }
5042 if (providers != null) {
5043 final int N = providers.size();
5044 for (int i=0; i<N; i++) {
5045 ProviderInfo cpi =
5046 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005047 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005048 if (cpr == null) {
5049 cpr = new ContentProviderRecord(cpi, app.info);
5050 mProvidersByClass.put(cpi.name, cpr);
5051 }
5052 app.pubProviders.put(cpi.name, cpr);
5053 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005054 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 }
5056 }
5057 return providers;
5058 }
5059
5060 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005061 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5063 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5064 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5065 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005066 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 return null;
5068 }
5069 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5070 cpi.exported ? -1 : cpi.applicationInfo.uid)
5071 == PackageManager.PERMISSION_GRANTED) {
5072 return null;
5073 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005074
5075 PathPermission[] pps = cpi.pathPermissions;
5076 if (pps != null) {
5077 int i = pps.length;
5078 while (i > 0) {
5079 i--;
5080 PathPermission pp = pps[i];
5081 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5082 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005083 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005084 return null;
5085 }
5086 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5087 cpi.exported ? -1 : cpi.applicationInfo.uid)
5088 == PackageManager.PERMISSION_GRANTED) {
5089 return null;
5090 }
5091 }
5092 }
5093
Dianne Hackbornb424b632010-08-18 15:59:05 -07005094 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5095 if (perms != null) {
5096 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5097 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5098 return null;
5099 }
5100 }
5101 }
5102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 String msg = "Permission Denial: opening provider " + cpi.name
5104 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5105 + ", uid=" + callingUid + ") requires "
5106 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005107 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005108 return msg;
5109 }
5110
5111 private final ContentProviderHolder getContentProviderImpl(
5112 IApplicationThread caller, String name) {
5113 ContentProviderRecord cpr;
5114 ProviderInfo cpi = null;
5115
5116 synchronized(this) {
5117 ProcessRecord r = null;
5118 if (caller != null) {
5119 r = getRecordForAppLocked(caller);
5120 if (r == null) {
5121 throw new SecurityException(
5122 "Unable to find app for caller " + caller
5123 + " (pid=" + Binder.getCallingPid()
5124 + ") when getting content provider " + name);
5125 }
5126 }
5127
5128 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005129 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 if (cpr != null) {
5131 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005132 String msg;
5133 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5134 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135 }
5136
5137 if (r != null && cpr.canRunHere(r)) {
5138 // This provider has been published or is in the process
5139 // of being published... but it is also allowed to run
5140 // in the caller's process, so don't make a connection
5141 // and just let the caller instantiate its own instance.
5142 if (cpr.provider != null) {
5143 // don't give caller the provider object, it needs
5144 // to make its own.
5145 cpr = new ContentProviderRecord(cpr);
5146 }
5147 return cpr;
5148 }
5149
5150 final long origId = Binder.clearCallingIdentity();
5151
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005152 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 // return it right away.
5154 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005155 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005156 "Adding provider requested by "
5157 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005158 + cpr.info.processName);
5159 Integer cnt = r.conProviders.get(cpr);
5160 if (cnt == null) {
5161 r.conProviders.put(cpr, new Integer(1));
5162 } else {
5163 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005166 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5167 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005168 // make sure to count it as being accessed and thus
5169 // back up on the LRU list. This is good because
5170 // content providers are often expensive to start.
5171 updateLruProcessLocked(cpr.app, false, true);
5172 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005173 } else {
5174 cpr.externals++;
5175 }
5176
5177 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005178 updateOomAdjLocked(cpr.app);
5179 }
5180
5181 Binder.restoreCallingIdentity(origId);
5182
5183 } else {
5184 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005185 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005186 resolveContentProvider(name,
5187 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005188 } catch (RemoteException ex) {
5189 }
5190 if (cpi == null) {
5191 return null;
5192 }
5193
Dianne Hackbornb424b632010-08-18 15:59:05 -07005194 String msg;
5195 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5196 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 }
5198
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005199 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5200 && !cpi.processName.equals("system")) {
5201 // If this content provider does not run in the system
5202 // process, and the system is not yet ready to run other
5203 // processes, then fail fast instead of hanging.
5204 throw new IllegalArgumentException(
5205 "Attempt to launch content provider before system ready");
5206 }
5207
Dianne Hackborn860755f2010-06-03 18:47:52 -07005208 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005209 final boolean firstClass = cpr == null;
5210 if (firstClass) {
5211 try {
5212 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005213 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 getApplicationInfo(
5215 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005216 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005217 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005218 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005219 + cpi.name);
5220 return null;
5221 }
5222 cpr = new ContentProviderRecord(cpi, ai);
5223 } catch (RemoteException ex) {
5224 // pm is in same process, this will never happen.
5225 }
5226 }
5227
5228 if (r != null && cpr.canRunHere(r)) {
5229 // If this is a multiprocess provider, then just return its
5230 // info and allow the caller to instantiate it. Only do
5231 // this if the provider is the same user as the caller's
5232 // process, or can run as root (so can be in any process).
5233 return cpr;
5234 }
5235
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005236 if (DEBUG_PROVIDER) {
5237 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005238 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005239 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 }
5241
5242 // This is single process, and our app is now connecting to it.
5243 // See if we are already in the process of launching this
5244 // provider.
5245 final int N = mLaunchingProviders.size();
5246 int i;
5247 for (i=0; i<N; i++) {
5248 if (mLaunchingProviders.get(i) == cpr) {
5249 break;
5250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 }
5252
5253 // If the provider is not already being launched, then get it
5254 // started.
5255 if (i >= N) {
5256 final long origId = Binder.clearCallingIdentity();
5257 ProcessRecord proc = startProcessLocked(cpi.processName,
5258 cpr.appInfo, false, 0, "content provider",
5259 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005260 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005262 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 + cpi.applicationInfo.packageName + "/"
5264 + cpi.applicationInfo.uid + " for provider "
5265 + name + ": process is bad");
5266 return null;
5267 }
5268 cpr.launchingApp = proc;
5269 mLaunchingProviders.add(cpr);
5270 Binder.restoreCallingIdentity(origId);
5271 }
5272
5273 // Make sure the provider is published (the same provider class
5274 // may be published under multiple names).
5275 if (firstClass) {
5276 mProvidersByClass.put(cpi.name, cpr);
5277 }
5278 mProvidersByName.put(name, cpr);
5279
5280 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005281 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005282 "Adding provider requested by "
5283 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005284 + cpr.info.processName);
5285 Integer cnt = r.conProviders.get(cpr);
5286 if (cnt == null) {
5287 r.conProviders.put(cpr, new Integer(1));
5288 } else {
5289 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005291 cpr.clients.add(r);
5292 } else {
5293 cpr.externals++;
5294 }
5295 }
5296 }
5297
5298 // Wait for the provider to be published...
5299 synchronized (cpr) {
5300 while (cpr.provider == null) {
5301 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005302 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 + cpi.applicationInfo.packageName + "/"
5304 + cpi.applicationInfo.uid + " for provider "
5305 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005306 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 cpi.applicationInfo.packageName,
5308 cpi.applicationInfo.uid, name);
5309 return null;
5310 }
5311 try {
5312 cpr.wait();
5313 } catch (InterruptedException ex) {
5314 }
5315 }
5316 }
5317 return cpr;
5318 }
5319
5320 public final ContentProviderHolder getContentProvider(
5321 IApplicationThread caller, String name) {
5322 if (caller == null) {
5323 String msg = "null IApplicationThread when getting content provider "
5324 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005325 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 throw new SecurityException(msg);
5327 }
5328
5329 return getContentProviderImpl(caller, name);
5330 }
5331
5332 private ContentProviderHolder getContentProviderExternal(String name) {
5333 return getContentProviderImpl(null, name);
5334 }
5335
5336 /**
5337 * Drop a content provider from a ProcessRecord's bookkeeping
5338 * @param cpr
5339 */
5340 public void removeContentProvider(IApplicationThread caller, String name) {
5341 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005342 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005344 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005345 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005346 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 return;
5348 }
5349 final ProcessRecord r = getRecordForAppLocked(caller);
5350 if (r == null) {
5351 throw new SecurityException(
5352 "Unable to find app for caller " + caller +
5353 " when removing content provider " + name);
5354 }
5355 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005356 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005357 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005358 + r.info.processName + " from process "
5359 + localCpr.appInfo.processName);
5360 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005361 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005362 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005363 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 return;
5365 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005366 Integer cnt = r.conProviders.get(localCpr);
5367 if (cnt == null || cnt.intValue() <= 1) {
5368 localCpr.clients.remove(r);
5369 r.conProviders.remove(localCpr);
5370 } else {
5371 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373 }
5374 updateOomAdjLocked();
5375 }
5376 }
5377
5378 private void removeContentProviderExternal(String name) {
5379 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005380 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005381 if(cpr == null) {
5382 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005383 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005384 return;
5385 }
5386
5387 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005388 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005389 localCpr.externals--;
5390 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005391 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005392 }
5393 updateOomAdjLocked();
5394 }
5395 }
5396
5397 public final void publishContentProviders(IApplicationThread caller,
5398 List<ContentProviderHolder> providers) {
5399 if (providers == null) {
5400 return;
5401 }
5402
5403 synchronized(this) {
5404 final ProcessRecord r = getRecordForAppLocked(caller);
5405 if (r == null) {
5406 throw new SecurityException(
5407 "Unable to find app for caller " + caller
5408 + " (pid=" + Binder.getCallingPid()
5409 + ") when publishing content providers");
5410 }
5411
5412 final long origId = Binder.clearCallingIdentity();
5413
5414 final int N = providers.size();
5415 for (int i=0; i<N; i++) {
5416 ContentProviderHolder src = providers.get(i);
5417 if (src == null || src.info == null || src.provider == null) {
5418 continue;
5419 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005420 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 if (dst != null) {
5422 mProvidersByClass.put(dst.info.name, dst);
5423 String names[] = dst.info.authority.split(";");
5424 for (int j = 0; j < names.length; j++) {
5425 mProvidersByName.put(names[j], dst);
5426 }
5427
5428 int NL = mLaunchingProviders.size();
5429 int j;
5430 for (j=0; j<NL; j++) {
5431 if (mLaunchingProviders.get(j) == dst) {
5432 mLaunchingProviders.remove(j);
5433 j--;
5434 NL--;
5435 }
5436 }
5437 synchronized (dst) {
5438 dst.provider = src.provider;
5439 dst.app = r;
5440 dst.notifyAll();
5441 }
5442 updateOomAdjLocked(r);
5443 }
5444 }
5445
5446 Binder.restoreCallingIdentity(origId);
5447 }
5448 }
5449
5450 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005451 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005452 synchronized (mSelf) {
5453 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5454 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005455 if (providers != null) {
5456 for (int i=providers.size()-1; i>=0; i--) {
5457 ProviderInfo pi = (ProviderInfo)providers.get(i);
5458 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5459 Slog.w(TAG, "Not installing system proc provider " + pi.name
5460 + ": not system .apk");
5461 providers.remove(i);
5462 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005463 }
5464 }
5465 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005466 if (providers != null) {
5467 mSystemThread.installSystemProviders(providers);
5468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 }
5470
5471 // =========================================================
5472 // GLOBAL MANAGEMENT
5473 // =========================================================
5474
5475 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5476 ApplicationInfo info, String customProcess) {
5477 String proc = customProcess != null ? customProcess : info.processName;
5478 BatteryStatsImpl.Uid.Proc ps = null;
5479 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5480 synchronized (stats) {
5481 ps = stats.getProcessStatsLocked(info.uid, proc);
5482 }
5483 return new ProcessRecord(ps, thread, info, proc);
5484 }
5485
5486 final ProcessRecord addAppLocked(ApplicationInfo info) {
5487 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5488
5489 if (app == null) {
5490 app = newProcessRecordLocked(null, info, null);
5491 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005492 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005493 }
5494
5495 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5496 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5497 app.persistent = true;
5498 app.maxAdj = CORE_SERVER_ADJ;
5499 }
5500 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5501 mPersistentStartingProcesses.add(app);
5502 startProcessLocked(app, "added application", app.processName);
5503 }
5504
5505 return app;
5506 }
5507
5508 public void unhandledBack() {
5509 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5510 "unhandledBack()");
5511
5512 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005513 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005514 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005515 TAG, "Performing unhandledBack(): stack size = " + count);
5516 if (count > 1) {
5517 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005518 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5520 Binder.restoreCallingIdentity(origId);
5521 }
5522 }
5523 }
5524
5525 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5526 String name = uri.getAuthority();
5527 ContentProviderHolder cph = getContentProviderExternal(name);
5528 ParcelFileDescriptor pfd = null;
5529 if (cph != null) {
5530 // We record the binder invoker's uid in thread-local storage before
5531 // going to the content provider to open the file. Later, in the code
5532 // that handles all permissions checks, we look for this uid and use
5533 // that rather than the Activity Manager's own uid. The effect is that
5534 // we do the check against the caller's permissions even though it looks
5535 // to the content provider like the Activity Manager itself is making
5536 // the request.
5537 sCallerIdentity.set(new Identity(
5538 Binder.getCallingPid(), Binder.getCallingUid()));
5539 try {
5540 pfd = cph.provider.openFile(uri, "r");
5541 } catch (FileNotFoundException e) {
5542 // do nothing; pfd will be returned null
5543 } finally {
5544 // Ensure that whatever happens, we clean up the identity state
5545 sCallerIdentity.remove();
5546 }
5547
5548 // We've got the fd now, so we're done with the provider.
5549 removeContentProviderExternal(name);
5550 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005551 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005552 }
5553 return pfd;
5554 }
5555
5556 public void goingToSleep() {
5557 synchronized(this) {
5558 mSleeping = true;
5559 mWindowManager.setEventDispatching(false);
5560
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005561 if (mMainStack.mResumedActivity != null) {
5562 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005564 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005566
5567 // Initialize the wake times of all processes.
5568 checkExcessiveWakeLocksLocked(false);
5569 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5570 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5571 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005572 }
5573 }
5574
Dianne Hackborn55280a92009-05-07 15:53:46 -07005575 public boolean shutdown(int timeout) {
5576 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5577 != PackageManager.PERMISSION_GRANTED) {
5578 throw new SecurityException("Requires permission "
5579 + android.Manifest.permission.SHUTDOWN);
5580 }
5581
5582 boolean timedout = false;
5583
5584 synchronized(this) {
5585 mShuttingDown = true;
5586 mWindowManager.setEventDispatching(false);
5587
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005588 if (mMainStack.mResumedActivity != null) {
5589 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005590 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005591 while (mMainStack.mResumedActivity != null
5592 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005593 long delay = endTime - System.currentTimeMillis();
5594 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005595 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005596 timedout = true;
5597 break;
5598 }
5599 try {
5600 this.wait();
5601 } catch (InterruptedException e) {
5602 }
5603 }
5604 }
5605 }
5606
5607 mUsageStatsService.shutdown();
5608 mBatteryStatsService.shutdown();
5609
5610 return timedout;
5611 }
5612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 public void wakingUp() {
5614 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005615 if (mMainStack.mGoingToSleep.isHeld()) {
5616 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 }
5618 mWindowManager.setEventDispatching(true);
5619 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005620 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005621 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 }
5623 }
5624
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005625 public void stopAppSwitches() {
5626 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5627 != PackageManager.PERMISSION_GRANTED) {
5628 throw new SecurityException("Requires permission "
5629 + android.Manifest.permission.STOP_APP_SWITCHES);
5630 }
5631
5632 synchronized(this) {
5633 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5634 + APP_SWITCH_DELAY_TIME;
5635 mDidAppSwitch = false;
5636 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5637 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5638 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5639 }
5640 }
5641
5642 public void resumeAppSwitches() {
5643 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5644 != PackageManager.PERMISSION_GRANTED) {
5645 throw new SecurityException("Requires permission "
5646 + android.Manifest.permission.STOP_APP_SWITCHES);
5647 }
5648
5649 synchronized(this) {
5650 // Note that we don't execute any pending app switches... we will
5651 // let those wait until either the timeout, or the next start
5652 // activity request.
5653 mAppSwitchesAllowedTime = 0;
5654 }
5655 }
5656
5657 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5658 String name) {
5659 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5660 return true;
5661 }
5662
5663 final int perm = checkComponentPermission(
5664 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5665 callingUid, -1);
5666 if (perm == PackageManager.PERMISSION_GRANTED) {
5667 return true;
5668 }
5669
Joe Onorato8a9b2202010-02-26 18:56:32 -08005670 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005671 return false;
5672 }
5673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 public void setDebugApp(String packageName, boolean waitForDebugger,
5675 boolean persistent) {
5676 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5677 "setDebugApp()");
5678
5679 // Note that this is not really thread safe if there are multiple
5680 // callers into it at the same time, but that's not a situation we
5681 // care about.
5682 if (persistent) {
5683 final ContentResolver resolver = mContext.getContentResolver();
5684 Settings.System.putString(
5685 resolver, Settings.System.DEBUG_APP,
5686 packageName);
5687 Settings.System.putInt(
5688 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5689 waitForDebugger ? 1 : 0);
5690 }
5691
5692 synchronized (this) {
5693 if (!persistent) {
5694 mOrigDebugApp = mDebugApp;
5695 mOrigWaitForDebugger = mWaitForDebugger;
5696 }
5697 mDebugApp = packageName;
5698 mWaitForDebugger = waitForDebugger;
5699 mDebugTransient = !persistent;
5700 if (packageName != null) {
5701 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005702 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005703 Binder.restoreCallingIdentity(origId);
5704 }
5705 }
5706 }
5707
5708 public void setAlwaysFinish(boolean enabled) {
5709 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5710 "setAlwaysFinish()");
5711
5712 Settings.System.putInt(
5713 mContext.getContentResolver(),
5714 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5715
5716 synchronized (this) {
5717 mAlwaysFinishActivities = enabled;
5718 }
5719 }
5720
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005721 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005722 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005723 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005725 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 }
5727 }
5728
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005729 public boolean isUserAMonkey() {
5730 // For now the fact that there is a controller implies
5731 // we have a monkey.
5732 synchronized (this) {
5733 return mController != null;
5734 }
5735 }
5736
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005737 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005738 synchronized (this) {
5739 mWatchers.register(watcher);
5740 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005741 }
5742
5743 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005744 synchronized (this) {
5745 mWatchers.unregister(watcher);
5746 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005747 }
5748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005749 public final void enterSafeMode() {
5750 synchronized(this) {
5751 // It only makes sense to do this before the system is ready
5752 // and started launching other packages.
5753 if (!mSystemReady) {
5754 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005755 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005756 } catch (RemoteException e) {
5757 }
5758
5759 View v = LayoutInflater.from(mContext).inflate(
5760 com.android.internal.R.layout.safe_mode, null);
5761 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5762 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5763 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5764 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5765 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5766 lp.format = v.getBackground().getOpacity();
5767 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5768 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5769 ((WindowManager)mContext.getSystemService(
5770 Context.WINDOW_SERVICE)).addView(v, lp);
5771 }
5772 }
5773 }
5774
5775 public void noteWakeupAlarm(IIntentSender sender) {
5776 if (!(sender instanceof PendingIntentRecord)) {
5777 return;
5778 }
5779 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5780 synchronized (stats) {
5781 if (mBatteryStatsService.isOnBattery()) {
5782 mBatteryStatsService.enforceCallingPermission();
5783 PendingIntentRecord rec = (PendingIntentRecord)sender;
5784 int MY_UID = Binder.getCallingUid();
5785 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5786 BatteryStatsImpl.Uid.Pkg pkg =
5787 stats.getPackageStatsLocked(uid, rec.key.packageName);
5788 pkg.incWakeupsLocked();
5789 }
5790 }
5791 }
5792
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005793 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005794 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005795 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005796 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005797 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005798 // XXX Note: don't acquire main activity lock here, because the window
5799 // manager calls in with its locks held.
5800
5801 boolean killed = false;
5802 synchronized (mPidsSelfLocked) {
5803 int[] types = new int[pids.length];
5804 int worstType = 0;
5805 for (int i=0; i<pids.length; i++) {
5806 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5807 if (proc != null) {
5808 int type = proc.setAdj;
5809 types[i] = type;
5810 if (type > worstType) {
5811 worstType = type;
5812 }
5813 }
5814 }
5815
5816 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5817 // then constrain it so we will kill all hidden procs.
5818 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5819 worstType = HIDDEN_APP_MIN_ADJ;
5820 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005821 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 for (int i=0; i<pids.length; i++) {
5823 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5824 if (proc == null) {
5825 continue;
5826 }
5827 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005828 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005829 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005830 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5831 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005833 proc.killedBackground = true;
5834 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005835 }
5836 }
5837 }
5838 return killed;
5839 }
5840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005841 public final void startRunning(String pkg, String cls, String action,
5842 String data) {
5843 synchronized(this) {
5844 if (mStartRunning) {
5845 return;
5846 }
5847 mStartRunning = true;
5848 mTopComponent = pkg != null && cls != null
5849 ? new ComponentName(pkg, cls) : null;
5850 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5851 mTopData = data;
5852 if (!mSystemReady) {
5853 return;
5854 }
5855 }
5856
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005857 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 }
5859
5860 private void retrieveSettings() {
5861 final ContentResolver resolver = mContext.getContentResolver();
5862 String debugApp = Settings.System.getString(
5863 resolver, Settings.System.DEBUG_APP);
5864 boolean waitForDebugger = Settings.System.getInt(
5865 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5866 boolean alwaysFinishActivities = Settings.System.getInt(
5867 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5868
5869 Configuration configuration = new Configuration();
5870 Settings.System.getConfiguration(resolver, configuration);
5871
5872 synchronized (this) {
5873 mDebugApp = mOrigDebugApp = debugApp;
5874 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5875 mAlwaysFinishActivities = alwaysFinishActivities;
5876 // This happens before any activities are started, so we can
5877 // change mConfiguration in-place.
5878 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005879 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005880 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 }
5882 }
5883
5884 public boolean testIsSystemReady() {
5885 // no need to synchronize(this) just to read & return the value
5886 return mSystemReady;
5887 }
5888
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005889 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005890 // In the simulator, startRunning will never have been called, which
5891 // normally sets a few crucial variables. Do it here instead.
5892 if (!Process.supportsProcesses()) {
5893 mStartRunning = true;
5894 mTopAction = Intent.ACTION_MAIN;
5895 }
5896
5897 synchronized(this) {
5898 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005899 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005900 return;
5901 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005902
5903 // Check to see if there are any update receivers to run.
5904 if (!mDidUpdate) {
5905 if (mWaitingUpdate) {
5906 return;
5907 }
5908 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5909 List<ResolveInfo> ris = null;
5910 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005911 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005912 intent, null, 0);
5913 } catch (RemoteException e) {
5914 }
5915 if (ris != null) {
5916 for (int i=ris.size()-1; i>=0; i--) {
5917 if ((ris.get(i).activityInfo.applicationInfo.flags
5918 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5919 ris.remove(i);
5920 }
5921 }
5922 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5923 for (int i=0; i<ris.size(); i++) {
5924 ActivityInfo ai = ris.get(i).activityInfo;
5925 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5926 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005927 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005928 finisher = new IIntentReceiver.Stub() {
5929 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005930 String data, Bundle extras, boolean ordered,
5931 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005932 throws RemoteException {
5933 synchronized (ActivityManagerService.this) {
5934 mDidUpdate = true;
5935 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005936 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005937 }
5938 };
5939 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005940 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005941 broadcastIntentLocked(null, null, intent, null, finisher,
5942 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005943 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005944 mWaitingUpdate = true;
5945 }
5946 }
5947 }
5948 if (mWaitingUpdate) {
5949 return;
5950 }
5951 mDidUpdate = true;
5952 }
5953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005954 mSystemReady = true;
5955 if (!mStartRunning) {
5956 return;
5957 }
5958 }
5959
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005960 ArrayList<ProcessRecord> procsToKill = null;
5961 synchronized(mPidsSelfLocked) {
5962 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5963 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5964 if (!isAllowedWhileBooting(proc.info)){
5965 if (procsToKill == null) {
5966 procsToKill = new ArrayList<ProcessRecord>();
5967 }
5968 procsToKill.add(proc);
5969 }
5970 }
5971 }
5972
5973 if (procsToKill != null) {
5974 synchronized(this) {
5975 for (int i=procsToKill.size()-1; i>=0; i--) {
5976 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005977 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005978 removeProcessLocked(proc, true);
5979 }
5980 }
5981 }
5982
Joe Onorato8a9b2202010-02-26 18:56:32 -08005983 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005984 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005985 SystemClock.uptimeMillis());
5986
5987 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005988 // Make sure we have no pre-ready processes sitting around.
5989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005990 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5991 ResolveInfo ri = mContext.getPackageManager()
5992 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005993 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 CharSequence errorMsg = null;
5995 if (ri != null) {
5996 ActivityInfo ai = ri.activityInfo;
5997 ApplicationInfo app = ai.applicationInfo;
5998 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5999 mTopAction = Intent.ACTION_FACTORY_TEST;
6000 mTopData = null;
6001 mTopComponent = new ComponentName(app.packageName,
6002 ai.name);
6003 } else {
6004 errorMsg = mContext.getResources().getText(
6005 com.android.internal.R.string.factorytest_not_system);
6006 }
6007 } else {
6008 errorMsg = mContext.getResources().getText(
6009 com.android.internal.R.string.factorytest_no_action);
6010 }
6011 if (errorMsg != null) {
6012 mTopAction = null;
6013 mTopData = null;
6014 mTopComponent = null;
6015 Message msg = Message.obtain();
6016 msg.what = SHOW_FACTORY_ERROR_MSG;
6017 msg.getData().putCharSequence("msg", errorMsg);
6018 mHandler.sendMessage(msg);
6019 }
6020 }
6021 }
6022
6023 retrieveSettings();
6024
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006025 if (goingCallback != null) goingCallback.run();
6026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006027 synchronized (this) {
6028 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6029 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006030 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006031 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 if (apps != null) {
6033 int N = apps.size();
6034 int i;
6035 for (i=0; i<N; i++) {
6036 ApplicationInfo info
6037 = (ApplicationInfo)apps.get(i);
6038 if (info != null &&
6039 !info.packageName.equals("android")) {
6040 addAppLocked(info);
6041 }
6042 }
6043 }
6044 } catch (RemoteException ex) {
6045 // pm is in same process, this will never happen.
6046 }
6047 }
6048
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006049 // Start up initial activity.
6050 mBooting = true;
6051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006052 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006053 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006054 Message msg = Message.obtain();
6055 msg.what = SHOW_UID_ERROR_MSG;
6056 mHandler.sendMessage(msg);
6057 }
6058 } catch (RemoteException e) {
6059 }
6060
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006061 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006062 }
6063 }
6064
Dan Egnorb7f03672009-12-09 16:22:32 -08006065 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006066 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006068 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006069 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070 startAppProblemLocked(app);
6071 app.stopFreezingAllLocked();
6072 return handleAppCrashLocked(app);
6073 }
6074
Dan Egnorb7f03672009-12-09 16:22:32 -08006075 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006076 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006077 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006078 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006079 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6080 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006081 startAppProblemLocked(app);
6082 app.stopFreezingAllLocked();
6083 }
6084
6085 /**
6086 * Generate a process error record, suitable for attachment to a ProcessRecord.
6087 *
6088 * @param app The ProcessRecord in which the error occurred.
6089 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6090 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006091 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006092 * @param shortMsg Short message describing the crash.
6093 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006094 * @param stackTrace Full crash stack trace, may be null.
6095 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006096 * @return Returns a fully-formed AppErrorStateInfo record.
6097 */
6098 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006099 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 report.condition = condition;
6103 report.processName = app.processName;
6104 report.pid = app.pid;
6105 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006106 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006107 report.shortMsg = shortMsg;
6108 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006109 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006110
6111 return report;
6112 }
6113
Dan Egnor42471dd2010-01-07 17:25:22 -08006114 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 synchronized (this) {
6116 app.crashing = false;
6117 app.crashingReport = null;
6118 app.notResponding = false;
6119 app.notRespondingReport = null;
6120 if (app.anrDialog == fromDialog) {
6121 app.anrDialog = null;
6122 }
6123 if (app.waitDialog == fromDialog) {
6124 app.waitDialog = null;
6125 }
6126 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006127 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006128 Slog.i(ActivityManagerService.TAG, "Killing "
6129 + app.processName + " (pid=" + app.pid + "): user's request");
6130 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6131 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006132 Process.killProcess(app.pid);
6133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006134 }
6135 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006136
Dan Egnorb7f03672009-12-09 16:22:32 -08006137 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006138 long now = SystemClock.uptimeMillis();
6139
6140 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6141 app.info.uid);
6142 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6143 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006144 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006145 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006146 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006147 app.info.processName, app.info.uid);
6148 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006149 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6150 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006151 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006152 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006154 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006155 }
6156 }
6157 if (!app.persistent) {
6158 // We don't want to start this process again until the user
6159 // explicitly does so... but for persistent process, we really
6160 // need to keep it running. If a persistent process is actually
6161 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006162 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006163 app.info.processName);
6164 mBadProcesses.put(app.info.processName, app.info.uid, now);
6165 app.bad = true;
6166 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6167 app.removed = true;
6168 removeProcessLocked(app, false);
6169 return false;
6170 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006171 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006172 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006173 if (r.app == app) {
6174 // If the top running activity is from this crashing
6175 // process, then terminate it to avoid getting in a loop.
6176 Slog.w(TAG, " Force finishing activity "
6177 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006178 int index = mMainStack.indexOfTokenLocked(r);
6179 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006180 Activity.RESULT_CANCELED, null, "crashed");
6181 // Also terminate an activities below it that aren't yet
6182 // stopped, to avoid a situation where one will get
6183 // re-start our crashing activity once it gets resumed again.
6184 index--;
6185 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006186 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006187 if (r.state == ActivityState.RESUMED
6188 || r.state == ActivityState.PAUSING
6189 || r.state == ActivityState.PAUSED) {
6190 if (!r.isHomeActivity) {
6191 Slog.w(TAG, " Force finishing activity "
6192 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006193 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006194 Activity.RESULT_CANCELED, null, "crashed");
6195 }
6196 }
6197 }
6198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006199 }
6200
6201 // Bump up the crash count of any services currently running in the proc.
6202 if (app.services.size() != 0) {
6203 // Any services running in the application need to be placed
6204 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006205 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006207 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006208 sr.crashCount++;
6209 }
6210 }
6211
6212 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6213 return true;
6214 }
6215
6216 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006217 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6218 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 skipCurrentReceiverLocked(app);
6220 }
6221
6222 void skipCurrentReceiverLocked(ProcessRecord app) {
6223 boolean reschedule = false;
6224 BroadcastRecord r = app.curReceiver;
6225 if (r != null) {
6226 // The current broadcast is waiting for this app's receiver
6227 // to be finished. Looks like that's not going to happen, so
6228 // let the broadcast continue.
6229 logBroadcastReceiverDiscard(r);
6230 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6231 r.resultExtras, r.resultAbort, true);
6232 reschedule = true;
6233 }
6234 r = mPendingBroadcast;
6235 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006236 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237 "skip & discard pending app " + r);
6238 logBroadcastReceiverDiscard(r);
6239 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6240 r.resultExtras, r.resultAbort, true);
6241 reschedule = true;
6242 }
6243 if (reschedule) {
6244 scheduleBroadcastsLocked();
6245 }
6246 }
6247
Dan Egnor60d87622009-12-16 16:32:58 -08006248 /**
6249 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6250 * The application process will exit immediately after this call returns.
6251 * @param app object of the crashing app, null for the system server
6252 * @param crashInfo describing the exception
6253 */
6254 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6255 ProcessRecord r = findAppProcess(app);
6256
6257 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6258 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006259 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006260 crashInfo.exceptionClassName,
6261 crashInfo.exceptionMessage,
6262 crashInfo.throwFileName,
6263 crashInfo.throwLineNumber);
6264
Dan Egnor42471dd2010-01-07 17:25:22 -08006265 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006266
6267 crashApplication(r, crashInfo);
6268 }
6269
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006270 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006271 IBinder app,
6272 int violationMask,
6273 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006274 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006275
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006276 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006277 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006278 boolean logIt = true;
6279 synchronized (mAlreadyLoggedViolatedStacks) {
6280 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6281 logIt = false;
6282 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006283 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006284 // the relative pain numbers, without logging all
6285 // the stack traces repeatedly. We'd want to do
6286 // likewise in the client code, which also does
6287 // dup suppression, before the Binder call.
6288 } else {
6289 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6290 mAlreadyLoggedViolatedStacks.clear();
6291 }
6292 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6293 }
6294 }
6295 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006296 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006297 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006298 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006299
6300 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6301 AppErrorResult result = new AppErrorResult();
6302 synchronized (this) {
6303 final long origId = Binder.clearCallingIdentity();
6304
6305 Message msg = Message.obtain();
6306 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6307 HashMap<String, Object> data = new HashMap<String, Object>();
6308 data.put("result", result);
6309 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006310 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006311 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006312 msg.obj = data;
6313 mHandler.sendMessage(msg);
6314
6315 Binder.restoreCallingIdentity(origId);
6316 }
6317 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006318 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006319 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006320 }
6321
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006322 // Depending on the policy in effect, there could be a bunch of
6323 // these in quick succession so we try to batch these together to
6324 // minimize disk writes, number of dropbox entries, and maximize
6325 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006326 private void logStrictModeViolationToDropBox(
6327 ProcessRecord process,
6328 StrictMode.ViolationInfo info) {
6329 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006330 return;
6331 }
6332 final boolean isSystemApp = process == null ||
6333 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6334 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6335 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6336 final DropBoxManager dbox = (DropBoxManager)
6337 mContext.getSystemService(Context.DROPBOX_SERVICE);
6338
6339 // Exit early if the dropbox isn't configured to accept this report type.
6340 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6341
6342 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006343 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006344 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6345 synchronized (sb) {
6346 bufferWasEmpty = sb.length() == 0;
6347 appendDropBoxProcessHeaders(process, sb);
6348 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6349 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006350 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6351 if (info.violationNumThisLoop != 0) {
6352 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6353 }
6354 if (info != null && info.durationMillis != -1) {
6355 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006356 }
6357 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006358 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6359 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006360 }
6361 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006362
6363 // Only buffer up to ~64k. Various logging bits truncate
6364 // things at 128k.
6365 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006366 }
6367
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006368 // Flush immediately if the buffer's grown too large, or this
6369 // is a non-system app. Non-system apps are isolated with a
6370 // different tag & policy and not batched.
6371 //
6372 // Batching is useful during internal testing with
6373 // StrictMode settings turned up high. Without batching,
6374 // thousands of separate files could be created on boot.
6375 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006376 new Thread("Error dump: " + dropboxTag) {
6377 @Override
6378 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006379 String report;
6380 synchronized (sb) {
6381 report = sb.toString();
6382 sb.delete(0, sb.length());
6383 sb.trimToSize();
6384 }
6385 if (report.length() != 0) {
6386 dbox.addText(dropboxTag, report);
6387 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006388 }
6389 }.start();
6390 return;
6391 }
6392
6393 // System app batching:
6394 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006395 // An existing dropbox-writing thread is outstanding, so
6396 // we don't need to start it up. The existing thread will
6397 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006398 return;
6399 }
6400
6401 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6402 // (After this point, we shouldn't access AMS internal data structures.)
6403 new Thread("Error dump: " + dropboxTag) {
6404 @Override
6405 public void run() {
6406 // 5 second sleep to let stacks arrive and be batched together
6407 try {
6408 Thread.sleep(5000); // 5 seconds
6409 } catch (InterruptedException e) {}
6410
6411 String errorReport;
6412 synchronized (mStrictModeBuffer) {
6413 errorReport = mStrictModeBuffer.toString();
6414 if (errorReport.length() == 0) {
6415 return;
6416 }
6417 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6418 mStrictModeBuffer.trimToSize();
6419 }
6420 dbox.addText(dropboxTag, errorReport);
6421 }
6422 }.start();
6423 }
6424
Dan Egnor60d87622009-12-16 16:32:58 -08006425 /**
6426 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6427 * @param app object of the crashing app, null for the system server
6428 * @param tag reported by the caller
6429 * @param crashInfo describing the context of the error
6430 * @return true if the process should exit immediately (WTF is fatal)
6431 */
6432 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006433 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006434 ProcessRecord r = findAppProcess(app);
6435
6436 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6437 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006438 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006439 tag, crashInfo.exceptionMessage);
6440
Dan Egnor42471dd2010-01-07 17:25:22 -08006441 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006442
Doug Zongker43866e02010-01-07 12:09:54 -08006443 if (Settings.Secure.getInt(mContext.getContentResolver(),
6444 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006445 crashApplication(r, crashInfo);
6446 return true;
6447 } else {
6448 return false;
6449 }
6450 }
6451
6452 /**
6453 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6454 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6455 */
6456 private ProcessRecord findAppProcess(IBinder app) {
6457 if (app == null) {
6458 return null;
6459 }
6460
6461 synchronized (this) {
6462 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6463 final int NA = apps.size();
6464 for (int ia=0; ia<NA; ia++) {
6465 ProcessRecord p = apps.valueAt(ia);
6466 if (p.thread != null && p.thread.asBinder() == app) {
6467 return p;
6468 }
6469 }
6470 }
6471
Joe Onorato8a9b2202010-02-26 18:56:32 -08006472 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006473 return null;
6474 }
6475 }
6476
6477 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006478 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6479 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006480 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006481 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006482 if (process == null || process.pid == MY_PID) {
6483 sb.append("Process: system_server\n");
6484 } else {
6485 sb.append("Process: ").append(process.processName).append("\n");
6486 }
6487 if (process != null) {
6488 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006489 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006490 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6491 for (String pkg : process.pkgList) {
6492 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006493 try {
Dan Egnora455d192010-03-12 08:52:28 -08006494 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6495 if (pi != null) {
6496 sb.append(" v").append(pi.versionCode);
6497 if (pi.versionName != null) {
6498 sb.append(" (").append(pi.versionName).append(")");
6499 }
6500 }
6501 } catch (RemoteException e) {
6502 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006503 }
Dan Egnora455d192010-03-12 08:52:28 -08006504 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006505 }
Dan Egnora455d192010-03-12 08:52:28 -08006506 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006507 }
6508
6509 private static String processClass(ProcessRecord process) {
6510 if (process == null || process.pid == MY_PID) {
6511 return "system_server";
6512 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6513 return "system_app";
6514 } else {
6515 return "data_app";
6516 }
6517 }
6518
6519 /**
6520 * Write a description of an error (crash, WTF, ANR) to the drop box.
6521 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6522 * @param process which caused the error, null means the system server
6523 * @param activity which triggered the error, null if unknown
6524 * @param parent activity related to the error, null if unknown
6525 * @param subject line related to the error, null if absent
6526 * @param report in long form describing the error, null if absent
6527 * @param logFile to include in the report, null if none
6528 * @param crashInfo giving an application stack trace, null if absent
6529 */
6530 public void addErrorToDropBox(String eventType,
6531 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6532 final String report, final File logFile,
6533 final ApplicationErrorReport.CrashInfo crashInfo) {
6534 // NOTE -- this must never acquire the ActivityManagerService lock,
6535 // otherwise the watchdog may be prevented from resetting the system.
6536
6537 final String dropboxTag = processClass(process) + "_" + eventType;
6538 final DropBoxManager dbox = (DropBoxManager)
6539 mContext.getSystemService(Context.DROPBOX_SERVICE);
6540
6541 // Exit early if the dropbox isn't configured to accept this report type.
6542 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6543
6544 final StringBuilder sb = new StringBuilder(1024);
6545 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006546 if (activity != null) {
6547 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6548 }
6549 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6550 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6551 }
6552 if (parent != null && parent != activity) {
6553 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6554 }
6555 if (subject != null) {
6556 sb.append("Subject: ").append(subject).append("\n");
6557 }
6558 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6559 sb.append("\n");
6560
6561 // Do the rest in a worker thread to avoid blocking the caller on I/O
6562 // (After this point, we shouldn't access AMS internal data structures.)
6563 Thread worker = new Thread("Error dump: " + dropboxTag) {
6564 @Override
6565 public void run() {
6566 if (report != null) {
6567 sb.append(report);
6568 }
6569 if (logFile != null) {
6570 try {
6571 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6572 } catch (IOException e) {
6573 Slog.e(TAG, "Error reading " + logFile, e);
6574 }
6575 }
6576 if (crashInfo != null && crashInfo.stackTrace != null) {
6577 sb.append(crashInfo.stackTrace);
6578 }
6579
6580 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6581 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6582 if (lines > 0) {
6583 sb.append("\n");
6584
6585 // Merge several logcat streams, and take the last N lines
6586 InputStreamReader input = null;
6587 try {
6588 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6589 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6590 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6591
6592 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6593 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6594 input = new InputStreamReader(logcat.getInputStream());
6595
6596 int num;
6597 char[] buf = new char[8192];
6598 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6599 } catch (IOException e) {
6600 Slog.e(TAG, "Error running logcat", e);
6601 } finally {
6602 if (input != null) try { input.close(); } catch (IOException e) {}
6603 }
6604 }
6605
6606 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006607 }
Dan Egnora455d192010-03-12 08:52:28 -08006608 };
6609
6610 if (process == null || process.pid == MY_PID) {
6611 worker.run(); // We may be about to die -- need to run this synchronously
6612 } else {
6613 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006614 }
6615 }
6616
6617 /**
6618 * Bring up the "unexpected error" dialog box for a crashing app.
6619 * Deal with edge cases (intercepts from instrumented applications,
6620 * ActivityController, error intent receivers, that sort of thing).
6621 * @param r the application crashing
6622 * @param crashInfo describing the failure
6623 */
6624 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006625 long timeMillis = System.currentTimeMillis();
6626 String shortMsg = crashInfo.exceptionClassName;
6627 String longMsg = crashInfo.exceptionMessage;
6628 String stackTrace = crashInfo.stackTrace;
6629 if (shortMsg != null && longMsg != null) {
6630 longMsg = shortMsg + ": " + longMsg;
6631 } else if (shortMsg != null) {
6632 longMsg = shortMsg;
6633 }
6634
Dan Egnor60d87622009-12-16 16:32:58 -08006635 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006636 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006637 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006638 try {
6639 String name = r != null ? r.processName : null;
6640 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006641 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006642 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006643 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006644 + " at watcher's request");
6645 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006646 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006647 }
6648 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006649 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006650 }
6651 }
6652
6653 final long origId = Binder.clearCallingIdentity();
6654
6655 // If this process is running instrumentation, finish it.
6656 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006657 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006659 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6660 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006661 Bundle info = new Bundle();
6662 info.putString("shortMsg", shortMsg);
6663 info.putString("longMsg", longMsg);
6664 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6665 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006666 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006667 }
6668
Dan Egnor60d87622009-12-16 16:32:58 -08006669 // If we can't identify the process or it's already exceeded its crash quota,
6670 // quit right away without showing a crash dialog.
6671 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006672 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006673 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006674 }
6675
6676 Message msg = Message.obtain();
6677 msg.what = SHOW_ERROR_MSG;
6678 HashMap data = new HashMap();
6679 data.put("result", result);
6680 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006681 msg.obj = data;
6682 mHandler.sendMessage(msg);
6683
6684 Binder.restoreCallingIdentity(origId);
6685 }
6686
6687 int res = result.get();
6688
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006689 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006690 synchronized (this) {
6691 if (r != null) {
6692 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6693 SystemClock.uptimeMillis());
6694 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006695 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006696 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006697 }
6698 }
6699
6700 if (appErrorIntent != null) {
6701 try {
6702 mContext.startActivity(appErrorIntent);
6703 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006704 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006708
6709 Intent createAppErrorIntentLocked(ProcessRecord r,
6710 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6711 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006712 if (report == null) {
6713 return null;
6714 }
6715 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6716 result.setComponent(r.errorReportReceiver);
6717 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6718 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6719 return result;
6720 }
6721
Dan Egnorb7f03672009-12-09 16:22:32 -08006722 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6723 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006724 if (r.errorReportReceiver == null) {
6725 return null;
6726 }
6727
6728 if (!r.crashing && !r.notResponding) {
6729 return null;
6730 }
6731
Dan Egnorb7f03672009-12-09 16:22:32 -08006732 ApplicationErrorReport report = new ApplicationErrorReport();
6733 report.packageName = r.info.packageName;
6734 report.installerPackageName = r.errorReportReceiver.getPackageName();
6735 report.processName = r.processName;
6736 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006737 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006738
Dan Egnorb7f03672009-12-09 16:22:32 -08006739 if (r.crashing) {
6740 report.type = ApplicationErrorReport.TYPE_CRASH;
6741 report.crashInfo = crashInfo;
6742 } else if (r.notResponding) {
6743 report.type = ApplicationErrorReport.TYPE_ANR;
6744 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006745
Dan Egnorb7f03672009-12-09 16:22:32 -08006746 report.anrInfo.activity = r.notRespondingReport.tag;
6747 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6748 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006749 }
6750
Dan Egnorb7f03672009-12-09 16:22:32 -08006751 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006752 }
6753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006754 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6755 // assume our apps are happy - lazy create the list
6756 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6757
6758 synchronized (this) {
6759
6760 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006761 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6762 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006763 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6764 // This one's in trouble, so we'll generate a report for it
6765 // crashes are higher priority (in case there's a crash *and* an anr)
6766 ActivityManager.ProcessErrorStateInfo report = null;
6767 if (app.crashing) {
6768 report = app.crashingReport;
6769 } else if (app.notResponding) {
6770 report = app.notRespondingReport;
6771 }
6772
6773 if (report != null) {
6774 if (errList == null) {
6775 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6776 }
6777 errList.add(report);
6778 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006779 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006780 " crashing = " + app.crashing +
6781 " notResponding = " + app.notResponding);
6782 }
6783 }
6784 }
6785 }
6786
6787 return errList;
6788 }
6789
6790 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6791 // Lazy instantiation of list
6792 List<ActivityManager.RunningAppProcessInfo> runList = null;
6793 synchronized (this) {
6794 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006795 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6796 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006797 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6798 // Generate process state info for running application
6799 ActivityManager.RunningAppProcessInfo currApp =
6800 new ActivityManager.RunningAppProcessInfo(app.processName,
6801 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006802 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006803 if (mHeavyWeightProcess == app) {
6804 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006806 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006807 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006808 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6809 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6810 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006811 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6812 } else if (adj >= HOME_APP_ADJ) {
6813 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6814 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006815 } else if (adj >= SECONDARY_SERVER_ADJ) {
6816 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006817 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6818 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6819 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6820 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006821 } else if (adj >= VISIBLE_APP_ADJ) {
6822 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6823 } else {
6824 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6825 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006826 currApp.importanceReasonCode = app.adjTypeCode;
6827 if (app.adjSource instanceof ProcessRecord) {
6828 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006829 } else if (app.adjSource instanceof ActivityRecord) {
6830 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006831 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6832 }
6833 if (app.adjTarget instanceof ComponentName) {
6834 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6835 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006836 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 // + " lru=" + currApp.lru);
6838 if (runList == null) {
6839 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6840 }
6841 runList.add(currApp);
6842 }
6843 }
6844 }
6845 return runList;
6846 }
6847
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006848 public List<ApplicationInfo> getRunningExternalApplications() {
6849 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6850 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6851 if (runningApps != null && runningApps.size() > 0) {
6852 Set<String> extList = new HashSet<String>();
6853 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6854 if (app.pkgList != null) {
6855 for (String pkg : app.pkgList) {
6856 extList.add(pkg);
6857 }
6858 }
6859 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006860 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006861 for (String pkg : extList) {
6862 try {
6863 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6864 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6865 retList.add(info);
6866 }
6867 } catch (RemoteException e) {
6868 }
6869 }
6870 }
6871 return retList;
6872 }
6873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006874 @Override
6875 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006876 if (checkCallingPermission(android.Manifest.permission.DUMP)
6877 != PackageManager.PERMISSION_GRANTED) {
6878 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6879 + Binder.getCallingPid()
6880 + ", uid=" + Binder.getCallingUid()
6881 + " without permission "
6882 + android.Manifest.permission.DUMP);
6883 return;
6884 }
6885
6886 boolean dumpAll = false;
6887
6888 int opti = 0;
6889 while (opti < args.length) {
6890 String opt = args[opti];
6891 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6892 break;
6893 }
6894 opti++;
6895 if ("-a".equals(opt)) {
6896 dumpAll = true;
6897 } else if ("-h".equals(opt)) {
6898 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006899 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006900 pw.println(" cmd may be one of:");
6901 pw.println(" activities: activity stack state");
6902 pw.println(" broadcasts: broadcast state");
6903 pw.println(" intents: pending intent state");
6904 pw.println(" processes: process state");
6905 pw.println(" providers: content provider state");
6906 pw.println(" services: service state");
6907 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006908 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006909 } else {
6910 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006911 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006912 }
6913
6914 // Is the caller requesting to dump a particular piece of data?
6915 if (opti < args.length) {
6916 String cmd = args[opti];
6917 opti++;
6918 if ("activities".equals(cmd) || "a".equals(cmd)) {
6919 synchronized (this) {
6920 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006921 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006922 return;
6923 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6924 synchronized (this) {
6925 dumpBroadcastsLocked(fd, pw, args, opti, true);
6926 }
6927 return;
6928 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6929 synchronized (this) {
6930 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6931 }
6932 return;
6933 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6934 synchronized (this) {
6935 dumpProcessesLocked(fd, pw, args, opti, true);
6936 }
6937 return;
6938 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6939 synchronized (this) {
6940 dumpProvidersLocked(fd, pw, args, opti, true);
6941 }
6942 return;
6943 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006944 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006945 return;
6946 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6947 synchronized (this) {
6948 dumpServicesLocked(fd, pw, args, opti, true);
6949 }
6950 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006951 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006952 }
6953
6954 // No piece of data specified, dump everything.
6955 synchronized (this) {
6956 boolean needSep;
6957 if (dumpAll) {
6958 pw.println("Providers in Current Activity Manager State:");
6959 }
6960 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6961 if (needSep) {
6962 pw.println(" ");
6963 }
6964 if (dumpAll) {
6965 pw.println("-------------------------------------------------------------------------------");
6966 pw.println("Broadcasts in Current Activity Manager State:");
6967 }
6968 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6969 if (needSep) {
6970 pw.println(" ");
6971 }
6972 if (dumpAll) {
6973 pw.println("-------------------------------------------------------------------------------");
6974 pw.println("Services in Current Activity Manager State:");
6975 }
6976 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6977 if (needSep) {
6978 pw.println(" ");
6979 }
6980 if (dumpAll) {
6981 pw.println("-------------------------------------------------------------------------------");
6982 pw.println("PendingIntents in Current Activity Manager State:");
6983 }
6984 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6985 if (needSep) {
6986 pw.println(" ");
6987 }
6988 if (dumpAll) {
6989 pw.println("-------------------------------------------------------------------------------");
6990 pw.println("Activities in Current Activity Manager State:");
6991 }
6992 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6993 if (needSep) {
6994 pw.println(" ");
6995 }
6996 if (dumpAll) {
6997 pw.println("-------------------------------------------------------------------------------");
6998 pw.println("Processes in Current Activity Manager State:");
6999 }
7000 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7001 }
7002 }
7003
7004 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7005 int opti, boolean dumpAll, boolean needHeader) {
7006 if (needHeader) {
7007 pw.println(" Activity stack:");
7008 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007009 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007010 pw.println(" ");
7011 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007012 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7013 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007015 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007016 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007017 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007018 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007019 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007020 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007021 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007022 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007023 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007024 pw.println(" ");
7025 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007026 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007028
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007029 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007030 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7031 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007032 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007033 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007035 if (dumpAll && mRecentTasks.size() > 0) {
7036 pw.println(" ");
7037 pw.println("Recent tasks in Current Activity Manager State:");
7038
7039 final int N = mRecentTasks.size();
7040 for (int i=0; i<N; i++) {
7041 TaskRecord tr = mRecentTasks.get(i);
7042 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7043 pw.println(tr);
7044 mRecentTasks.get(i).dump(pw, " ");
7045 }
7046 }
7047
7048 pw.println(" ");
7049 pw.println(" mCurTask: " + mCurTask);
7050
7051 return true;
7052 }
7053
7054 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7055 int opti, boolean dumpAll) {
7056 boolean needSep = false;
7057 int numPers = 0;
7058
7059 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7061 final int NA = procs.size();
7062 for (int ia=0; ia<NA; ia++) {
7063 if (!needSep) {
7064 pw.println(" All known processes:");
7065 needSep = true;
7066 }
7067 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007068 pw.print(r.persistent ? " *PERS*" : " *APP*");
7069 pw.print(" UID "); pw.print(procs.keyAt(ia));
7070 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007071 r.dump(pw, " ");
7072 if (r.persistent) {
7073 numPers++;
7074 }
7075 }
7076 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007077 }
7078
7079 if (mLruProcesses.size() > 0) {
7080 if (needSep) pw.println(" ");
7081 needSep = true;
7082 pw.println(" Running processes (most recent first):");
7083 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007084 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007085 needSep = true;
7086 }
7087
7088 synchronized (mPidsSelfLocked) {
7089 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007090 if (needSep) pw.println(" ");
7091 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007092 pw.println(" PID mappings:");
7093 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7094 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7095 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007096 }
7097 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007098 }
7099
7100 if (mForegroundProcesses.size() > 0) {
7101 if (needSep) pw.println(" ");
7102 needSep = true;
7103 pw.println(" Foreground Processes:");
7104 for (int i=0; i<mForegroundProcesses.size(); i++) {
7105 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7106 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007107 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007108 }
7109
7110 if (mPersistentStartingProcesses.size() > 0) {
7111 if (needSep) pw.println(" ");
7112 needSep = true;
7113 pw.println(" Persisent processes that are starting:");
7114 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
7115 "Starting Norm", "Restarting PERS", false);
7116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007118 if (mStartingProcesses.size() > 0) {
7119 if (needSep) pw.println(" ");
7120 needSep = true;
7121 pw.println(" Processes that are starting:");
7122 dumpProcessList(pw, this, mStartingProcesses, " ",
7123 "Starting Norm", "Starting PERS", false);
7124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007125
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007126 if (mRemovedProcesses.size() > 0) {
7127 if (needSep) pw.println(" ");
7128 needSep = true;
7129 pw.println(" Processes that are being removed:");
7130 dumpProcessList(pw, this, mRemovedProcesses, " ",
7131 "Removed Norm", "Removed PERS", false);
7132 }
7133
7134 if (mProcessesOnHold.size() > 0) {
7135 if (needSep) pw.println(" ");
7136 needSep = true;
7137 pw.println(" Processes that are on old until the system is ready:");
7138 dumpProcessList(pw, this, mProcessesOnHold, " ",
7139 "OnHold Norm", "OnHold PERS", false);
7140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007141
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007142 if (mProcessesToGc.size() > 0) {
7143 if (needSep) pw.println(" ");
7144 needSep = true;
7145 pw.println(" Processes that are waiting to GC:");
7146 long now = SystemClock.uptimeMillis();
7147 for (int i=0; i<mProcessesToGc.size(); i++) {
7148 ProcessRecord proc = mProcessesToGc.get(i);
7149 pw.print(" Process "); pw.println(proc);
7150 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7151 pw.print(", last gced=");
7152 pw.print(now-proc.lastRequestedGc);
7153 pw.print(" ms ago, last lowMem=");
7154 pw.print(now-proc.lastLowMemory);
7155 pw.println(" ms ago");
7156
7157 }
7158 }
7159
7160 if (mProcessCrashTimes.getMap().size() > 0) {
7161 if (needSep) pw.println(" ");
7162 needSep = true;
7163 pw.println(" Time since processes crashed:");
7164 long now = SystemClock.uptimeMillis();
7165 for (Map.Entry<String, SparseArray<Long>> procs
7166 : mProcessCrashTimes.getMap().entrySet()) {
7167 SparseArray<Long> uids = procs.getValue();
7168 final int N = uids.size();
7169 for (int i=0; i<N; i++) {
7170 pw.print(" Process "); pw.print(procs.getKey());
7171 pw.print(" uid "); pw.print(uids.keyAt(i));
7172 pw.print(": last crashed ");
7173 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007174 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007175 }
7176 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007179 if (mBadProcesses.getMap().size() > 0) {
7180 if (needSep) pw.println(" ");
7181 needSep = true;
7182 pw.println(" Bad processes:");
7183 for (Map.Entry<String, SparseArray<Long>> procs
7184 : mBadProcesses.getMap().entrySet()) {
7185 SparseArray<Long> uids = procs.getValue();
7186 final int N = uids.size();
7187 for (int i=0; i<N; i++) {
7188 pw.print(" Bad process "); pw.print(procs.getKey());
7189 pw.print(" uid "); pw.print(uids.keyAt(i));
7190 pw.print(": crashed at time ");
7191 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007192 }
7193 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007195
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007196 pw.println(" ");
7197 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007198 if (mHeavyWeightProcess != null) {
7199 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7200 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007201 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007202 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007203 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7204 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7205 || mOrigWaitForDebugger) {
7206 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7207 + " mDebugTransient=" + mDebugTransient
7208 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7209 }
7210 if (mAlwaysFinishActivities || mController != null) {
7211 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7212 + " mController=" + mController);
7213 }
7214 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007215 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007216 pw.println(" mStartRunning=" + mStartRunning
7217 + " mSystemReady=" + mSystemReady
7218 + " mBooting=" + mBooting
7219 + " mBooted=" + mBooted
7220 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007221 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7222 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007223 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007224 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007225
7226 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227 }
7228
7229 /**
7230 * There are three ways to call this:
7231 * - no service specified: dump all the services
7232 * - a flattened component name that matched an existing service was specified as the
7233 * first arg: dump that one service
7234 * - the first arg isn't the flattened component name of an existing service:
7235 * dump all services whose component contains the first arg as a substring
7236 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007237 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7238 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007239 String[] newArgs;
7240 String componentNameString;
7241 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007242 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007243 componentNameString = null;
7244 newArgs = EMPTY_STRING_ARRAY;
7245 r = null;
7246 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007247 componentNameString = args[opti];
7248 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007249 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007250 synchronized (this) {
7251 r = componentName != null ? mServices.get(componentName) : null;
7252 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007253 newArgs = new String[args.length - opti];
7254 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007255 }
7256
7257 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007258 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007259 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007260 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7261 synchronized (this) {
7262 for (ServiceRecord r1 : mServices.values()) {
7263 if (componentNameString == null
7264 || r1.name.flattenToString().contains(componentNameString)) {
7265 services.add(r1);
7266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007267 }
7268 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007269 for (int i=0; i<services.size(); i++) {
7270 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 }
7273 }
7274
7275 /**
7276 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7277 * there is a thread associated with the service.
7278 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007279 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7280 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007281 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007282 if (dumpAll) {
7283 synchronized (this) {
7284 pw.print(" * "); pw.println(r);
7285 r.dump(pw, " ");
7286 }
7287 pw.println("");
7288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007289 if (r.app != null && r.app.thread != null) {
7290 try {
7291 // flush anything that is already in the PrintWriter since the thread is going
7292 // to write to the file descriptor directly
7293 pw.flush();
7294 r.app.thread.dumpService(fd, r, args);
7295 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007296 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297 } catch (RemoteException e) {
7298 pw.println("got a RemoteException while dumping the service");
7299 }
7300 }
7301 }
7302
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007303 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7304 int opti, boolean dumpAll) {
7305 boolean needSep = false;
7306
7307 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 if (mRegisteredReceivers.size() > 0) {
7309 pw.println(" ");
7310 pw.println(" Registered Receivers:");
7311 Iterator it = mRegisteredReceivers.values().iterator();
7312 while (it.hasNext()) {
7313 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007314 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 r.dump(pw, " ");
7316 }
7317 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319 pw.println(" ");
7320 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007321 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007322 needSep = true;
7323 }
7324
7325 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7326 || mPendingBroadcast != null) {
7327 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007328 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007329 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007330 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007331 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7332 pw.println(" Broadcast #" + i + ":");
7333 mParallelBroadcasts.get(i).dump(pw, " ");
7334 }
7335 if (mOrderedBroadcasts.size() > 0) {
7336 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007337 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007338 }
7339 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7340 pw.println(" Serialized Broadcast #" + i + ":");
7341 mOrderedBroadcasts.get(i).dump(pw, " ");
7342 }
7343 pw.println(" ");
7344 pw.println(" Pending broadcast:");
7345 if (mPendingBroadcast != null) {
7346 mPendingBroadcast.dump(pw, " ");
7347 } else {
7348 pw.println(" (null)");
7349 }
7350 needSep = true;
7351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007353 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007354 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007355 pw.println(" Historical broadcasts:");
7356 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7357 BroadcastRecord r = mBroadcastHistory[i];
7358 if (r == null) {
7359 break;
7360 }
7361 pw.println(" Historical Broadcast #" + i + ":");
7362 r.dump(pw, " ");
7363 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007364 needSep = true;
7365 }
7366
7367 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007368 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007369 pw.println(" Sticky broadcasts:");
7370 StringBuilder sb = new StringBuilder(128);
7371 for (Map.Entry<String, ArrayList<Intent>> ent
7372 : mStickyBroadcasts.entrySet()) {
7373 pw.print(" * Sticky action "); pw.print(ent.getKey());
7374 pw.println(":");
7375 ArrayList<Intent> intents = ent.getValue();
7376 final int N = intents.size();
7377 for (int i=0; i<N; i++) {
7378 sb.setLength(0);
7379 sb.append(" Intent: ");
7380 intents.get(i).toShortString(sb, true, false);
7381 pw.println(sb.toString());
7382 Bundle bundle = intents.get(i).getExtras();
7383 if (bundle != null) {
7384 pw.print(" ");
7385 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386 }
7387 }
7388 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007389 needSep = true;
7390 }
7391
7392 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007393 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007394 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007395 pw.println(" mHandler:");
7396 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007397 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007399
7400 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 }
7402
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007403 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7404 int opti, boolean dumpAll) {
7405 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007406
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007407 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007408 if (mServices.size() > 0) {
7409 pw.println(" Active services:");
7410 Iterator<ServiceRecord> it = mServices.values().iterator();
7411 while (it.hasNext()) {
7412 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007413 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 r.dump(pw, " ");
7415 }
7416 needSep = true;
7417 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007420 if (mPendingServices.size() > 0) {
7421 if (needSep) pw.println(" ");
7422 pw.println(" Pending services:");
7423 for (int i=0; i<mPendingServices.size(); i++) {
7424 ServiceRecord r = mPendingServices.get(i);
7425 pw.print(" * Pending "); pw.println(r);
7426 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007428 needSep = true;
7429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007431 if (mRestartingServices.size() > 0) {
7432 if (needSep) pw.println(" ");
7433 pw.println(" Restarting services:");
7434 for (int i=0; i<mRestartingServices.size(); i++) {
7435 ServiceRecord r = mRestartingServices.get(i);
7436 pw.print(" * Restarting "); pw.println(r);
7437 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007439 needSep = true;
7440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007441
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007442 if (mStoppingServices.size() > 0) {
7443 if (needSep) pw.println(" ");
7444 pw.println(" Stopping services:");
7445 for (int i=0; i<mStoppingServices.size(); i++) {
7446 ServiceRecord r = mStoppingServices.get(i);
7447 pw.print(" * Stopping "); pw.println(r);
7448 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007449 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007450 needSep = true;
7451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007452
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007453 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007454 if (mServiceConnections.size() > 0) {
7455 if (needSep) pw.println(" ");
7456 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007457 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 = mServiceConnections.values().iterator();
7459 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007460 ArrayList<ConnectionRecord> r = it.next();
7461 for (int i=0; i<r.size(); i++) {
7462 pw.print(" * "); pw.println(r.get(i));
7463 r.get(i).dump(pw, " ");
7464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007466 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007467 }
7468 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007469
7470 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 }
7472
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007473 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7474 int opti, boolean dumpAll) {
7475 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007477 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007478 if (mProvidersByClass.size() > 0) {
7479 if (needSep) pw.println(" ");
7480 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007481 Iterator<Map.Entry<String, ContentProviderRecord>> it
7482 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007483 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007484 Map.Entry<String, ContentProviderRecord> e = it.next();
7485 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007486 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 r.dump(pw, " ");
7488 }
7489 needSep = true;
7490 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007491
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007492 if (mProvidersByName.size() > 0) {
7493 pw.println(" ");
7494 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007495 Iterator<Map.Entry<String, ContentProviderRecord>> it
7496 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007497 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007498 Map.Entry<String, ContentProviderRecord> e = it.next();
7499 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007500 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7501 pw.println(r);
7502 }
7503 needSep = true;
7504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007505 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007506
7507 if (mLaunchingProviders.size() > 0) {
7508 if (needSep) pw.println(" ");
7509 pw.println(" Launching content providers:");
7510 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7511 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7512 pw.println(mLaunchingProviders.get(i));
7513 }
7514 needSep = true;
7515 }
7516
7517 if (mGrantedUriPermissions.size() > 0) {
7518 pw.println();
7519 pw.println("Granted Uri Permissions:");
7520 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7521 int uid = mGrantedUriPermissions.keyAt(i);
7522 HashMap<Uri, UriPermission> perms
7523 = mGrantedUriPermissions.valueAt(i);
7524 pw.print(" * UID "); pw.print(uid);
7525 pw.println(" holds:");
7526 for (UriPermission perm : perms.values()) {
7527 pw.print(" "); pw.println(perm);
7528 perm.dump(pw, " ");
7529 }
7530 }
7531 needSep = true;
7532 }
7533
7534 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007535 }
7536
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007537 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7538 int opti, boolean dumpAll) {
7539 boolean needSep = false;
7540
7541 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542 if (this.mIntentSenderRecords.size() > 0) {
7543 Iterator<WeakReference<PendingIntentRecord>> it
7544 = mIntentSenderRecords.values().iterator();
7545 while (it.hasNext()) {
7546 WeakReference<PendingIntentRecord> ref = it.next();
7547 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007548 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007550 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 rec.dump(pw, " ");
7552 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007553 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554 }
7555 }
7556 }
7557 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007558
7559 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 }
7561
7562 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007563 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007564 TaskRecord lastTask = null;
7565 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007566 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007567 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 if (lastTask != r.task) {
7569 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007570 pw.print(prefix);
7571 pw.print(full ? "* " : " ");
7572 pw.println(lastTask);
7573 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007574 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007577 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7578 pw.print(" #"); pw.print(i); pw.print(": ");
7579 pw.println(r);
7580 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007581 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 }
7584 }
7585
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007586 private static String buildOomTag(String prefix, String space, int val, int base) {
7587 if (val == base) {
7588 if (space == null) return prefix;
7589 return prefix + " ";
7590 }
7591 return prefix + "+" + Integer.toString(val-base);
7592 }
7593
7594 private static final int dumpProcessList(PrintWriter pw,
7595 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007596 String prefix, String normalLabel, String persistentLabel,
7597 boolean inclOomAdj) {
7598 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007599 final int N = list.size()-1;
7600 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007601 ProcessRecord r = (ProcessRecord)list.get(i);
7602 if (false) {
7603 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7604 + " #" + i + ":");
7605 r.dump(pw, prefix + " ");
7606 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007607 String oomAdj;
7608 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007609 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007610 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007611 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7612 } else if (r.setAdj >= HOME_APP_ADJ) {
7613 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7614 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7615 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7616 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7617 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007618 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7619 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7620 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7621 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007622 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7623 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7624 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7625 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007626 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007627 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007628 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007629 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007630 } else {
7631 oomAdj = Integer.toString(r.setAdj);
7632 }
7633 String schedGroup;
7634 switch (r.setSchedGroup) {
7635 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7636 schedGroup = "B";
7637 break;
7638 case Process.THREAD_GROUP_DEFAULT:
7639 schedGroup = "F";
7640 break;
7641 default:
7642 schedGroup = Integer.toString(r.setSchedGroup);
7643 break;
7644 }
7645 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007647 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007648 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007649 pw.print(prefix);
7650 pw.print(" ");
7651 if (r.adjTarget instanceof ComponentName) {
7652 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7653 } else if (r.adjTarget != null) {
7654 pw.print(r.adjTarget.toString());
7655 } else {
7656 pw.print("{null}");
7657 }
7658 pw.print("<=");
7659 if (r.adjSource instanceof ProcessRecord) {
7660 pw.print("Proc{");
7661 pw.print(((ProcessRecord)r.adjSource).toShortString());
7662 pw.println("}");
7663 } else if (r.adjSource != null) {
7664 pw.println(r.adjSource.toString());
7665 } else {
7666 pw.println("{null}");
7667 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007668 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 } else {
7670 pw.println(String.format("%s%s #%2d: %s",
7671 prefix, (r.persistent ? persistentLabel : normalLabel),
7672 i, r.toString()));
7673 }
7674 if (r.persistent) {
7675 numPers++;
7676 }
7677 }
7678 return numPers;
7679 }
7680
Dianne Hackborn472ad872010-04-07 17:31:48 -07007681 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007683 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 long uptime = SystemClock.uptimeMillis();
7685 long realtime = SystemClock.elapsedRealtime();
7686
7687 if (isCheckinRequest) {
7688 // short checkin version
7689 pw.println(uptime + "," + realtime);
7690 pw.flush();
7691 } else {
7692 pw.println("Applications Memory Usage (kB):");
7693 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7694 }
7695 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7696 ProcessRecord r = (ProcessRecord)list.get(i);
7697 if (r.thread != null) {
7698 if (!isCheckinRequest) {
7699 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7700 pw.flush();
7701 }
7702 try {
7703 r.thread.asBinder().dump(fd, args);
7704 } catch (RemoteException e) {
7705 if (!isCheckinRequest) {
7706 pw.println("Got RemoteException!");
7707 pw.flush();
7708 }
7709 }
7710 }
7711 }
7712 }
7713
7714 /**
7715 * Searches array of arguments for the specified string
7716 * @param args array of argument strings
7717 * @param value value to search for
7718 * @return true if the value is contained in the array
7719 */
7720 private static boolean scanArgs(String[] args, String value) {
7721 if (args != null) {
7722 for (String arg : args) {
7723 if (value.equals(arg)) {
7724 return true;
7725 }
7726 }
7727 }
7728 return false;
7729 }
7730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007731 private final void killServicesLocked(ProcessRecord app,
7732 boolean allowRestart) {
7733 // Report disconnected services.
7734 if (false) {
7735 // XXX we are letting the client link to the service for
7736 // death notifications.
7737 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007738 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007739 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007740 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007742 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007743 = r.connections.values().iterator();
7744 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007745 ArrayList<ConnectionRecord> cl = jt.next();
7746 for (int i=0; i<cl.size(); i++) {
7747 ConnectionRecord c = cl.get(i);
7748 if (c.binding.client != app) {
7749 try {
7750 //c.conn.connected(r.className, null);
7751 } catch (Exception e) {
7752 // todo: this should be asynchronous!
7753 Slog.w(TAG, "Exception thrown disconnected servce "
7754 + r.shortName
7755 + " from app " + app.processName, e);
7756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007757 }
7758 }
7759 }
7760 }
7761 }
7762 }
7763 }
7764
7765 // Clean up any connections this application has to other services.
7766 if (app.connections.size() > 0) {
7767 Iterator<ConnectionRecord> it = app.connections.iterator();
7768 while (it.hasNext()) {
7769 ConnectionRecord r = it.next();
7770 removeConnectionLocked(r, app, null);
7771 }
7772 }
7773 app.connections.clear();
7774
7775 if (app.services.size() != 0) {
7776 // Any services running in the application need to be placed
7777 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007778 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007779 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007780 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007781 synchronized (sr.stats.getBatteryStats()) {
7782 sr.stats.stopLaunchedLocked();
7783 }
7784 sr.app = null;
7785 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007786 if (mStoppingServices.remove(sr)) {
7787 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
7788 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007789
7790 boolean hasClients = sr.bindings.size() > 0;
7791 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 Iterator<IntentBindRecord> bindings
7793 = sr.bindings.values().iterator();
7794 while (bindings.hasNext()) {
7795 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007796 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 + ": shouldUnbind=" + b.hasBound);
7798 b.binder = null;
7799 b.requested = b.received = b.hasBound = false;
7800 }
7801 }
7802
7803 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007804 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007805 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007806 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007807 sr.crashCount, sr.shortName, app.pid);
7808 bringDownServiceLocked(sr, true);
7809 } else if (!allowRestart) {
7810 bringDownServiceLocked(sr, true);
7811 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007812 boolean canceled = scheduleServiceRestartLocked(sr, true);
7813
7814 // Should the service remain running? Note that in the
7815 // extreme case of so many attempts to deliver a command
7816 // that it failed, that we also will stop it here.
7817 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7818 if (sr.pendingStarts.size() == 0) {
7819 sr.startRequested = false;
7820 if (!hasClients) {
7821 // Whoops, no reason to restart!
7822 bringDownServiceLocked(sr, true);
7823 }
7824 }
7825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007826 }
7827 }
7828
7829 if (!allowRestart) {
7830 app.services.clear();
7831 }
7832 }
7833
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007834 // Make sure we have no more records on the stopping list.
7835 int i = mStoppingServices.size();
7836 while (i > 0) {
7837 i--;
7838 ServiceRecord sr = mStoppingServices.get(i);
7839 if (sr.app == app) {
7840 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007841 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007842 }
7843 }
7844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007845 app.executingServices.clear();
7846 }
7847
7848 private final void removeDyingProviderLocked(ProcessRecord proc,
7849 ContentProviderRecord cpr) {
7850 synchronized (cpr) {
7851 cpr.launchingApp = null;
7852 cpr.notifyAll();
7853 }
7854
7855 mProvidersByClass.remove(cpr.info.name);
7856 String names[] = cpr.info.authority.split(";");
7857 for (int j = 0; j < names.length; j++) {
7858 mProvidersByName.remove(names[j]);
7859 }
7860
7861 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7862 while (cit.hasNext()) {
7863 ProcessRecord capp = cit.next();
7864 if (!capp.persistent && capp.thread != null
7865 && capp.pid != 0
7866 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007867 Slog.i(TAG, "Kill " + capp.processName
7868 + " (pid " + capp.pid + "): provider " + cpr.info.name
7869 + " in dying process " + proc.processName);
7870 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7871 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007872 Process.killProcess(capp.pid);
7873 }
7874 }
7875
7876 mLaunchingProviders.remove(cpr);
7877 }
7878
7879 /**
7880 * Main code for cleaning up a process when it has gone away. This is
7881 * called both as a result of the process dying, or directly when stopping
7882 * a process when running in single process mode.
7883 */
7884 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7885 boolean restarting, int index) {
7886 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007887 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007888 }
7889
Dianne Hackborn36124872009-10-08 16:22:03 -07007890 mProcessesToGc.remove(app);
7891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 // Dismiss any open dialogs.
7893 if (app.crashDialog != null) {
7894 app.crashDialog.dismiss();
7895 app.crashDialog = null;
7896 }
7897 if (app.anrDialog != null) {
7898 app.anrDialog.dismiss();
7899 app.anrDialog = null;
7900 }
7901 if (app.waitDialog != null) {
7902 app.waitDialog.dismiss();
7903 app.waitDialog = null;
7904 }
7905
7906 app.crashing = false;
7907 app.notResponding = false;
7908
7909 app.resetPackageList();
7910 app.thread = null;
7911 app.forcingToForeground = null;
7912 app.foregroundServices = false;
7913
7914 killServicesLocked(app, true);
7915
7916 boolean restart = false;
7917
7918 int NL = mLaunchingProviders.size();
7919
7920 // Remove published content providers.
7921 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007922 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007924 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007925 cpr.provider = null;
7926 cpr.app = null;
7927
7928 // See if someone is waiting for this provider... in which
7929 // case we don't remove it, but just let it restart.
7930 int i = 0;
7931 if (!app.bad) {
7932 for (; i<NL; i++) {
7933 if (mLaunchingProviders.get(i) == cpr) {
7934 restart = true;
7935 break;
7936 }
7937 }
7938 } else {
7939 i = NL;
7940 }
7941
7942 if (i >= NL) {
7943 removeDyingProviderLocked(app, cpr);
7944 NL = mLaunchingProviders.size();
7945 }
7946 }
7947 app.pubProviders.clear();
7948 }
7949
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007950 // Take care of any launching providers waiting for this process.
7951 if (checkAppInLaunchingProvidersLocked(app, false)) {
7952 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007953 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 // Unregister from connected content providers.
7956 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007957 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007958 while (it.hasNext()) {
7959 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7960 cpr.clients.remove(app);
7961 }
7962 app.conProviders.clear();
7963 }
7964
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007965 // At this point there may be remaining entries in mLaunchingProviders
7966 // where we were the only one waiting, so they are no longer of use.
7967 // Look for these and clean up if found.
7968 // XXX Commented out for now. Trying to figure out a way to reproduce
7969 // the actual situation to identify what is actually going on.
7970 if (false) {
7971 for (int i=0; i<NL; i++) {
7972 ContentProviderRecord cpr = (ContentProviderRecord)
7973 mLaunchingProviders.get(i);
7974 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7975 synchronized (cpr) {
7976 cpr.launchingApp = null;
7977 cpr.notifyAll();
7978 }
7979 }
7980 }
7981 }
7982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007983 skipCurrentReceiverLocked(app);
7984
7985 // Unregister any receivers.
7986 if (app.receivers.size() > 0) {
7987 Iterator<ReceiverList> it = app.receivers.iterator();
7988 while (it.hasNext()) {
7989 removeReceiverLocked(it.next());
7990 }
7991 app.receivers.clear();
7992 }
7993
Christopher Tate181fafa2009-05-14 11:12:14 -07007994 // If the app is undergoing backup, tell the backup manager about it
7995 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007996 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007997 try {
7998 IBackupManager bm = IBackupManager.Stub.asInterface(
7999 ServiceManager.getService(Context.BACKUP_SERVICE));
8000 bm.agentDisconnected(app.info.packageName);
8001 } catch (RemoteException e) {
8002 // can't happen; backup manager is local
8003 }
8004 }
8005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008006 // If the caller is restarting this app, then leave it in its
8007 // current lists and let the caller take care of it.
8008 if (restarting) {
8009 return;
8010 }
8011
8012 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008013 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008014 "Removing non-persistent process during cleanup: " + app);
8015 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008016 if (mHeavyWeightProcess == app) {
8017 mHeavyWeightProcess = null;
8018 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008020 } else if (!app.removed) {
8021 // This app is persistent, so we need to keep its record around.
8022 // If it is not already on the pending app list, add it there
8023 // and start a new process for it.
8024 app.thread = null;
8025 app.forcingToForeground = null;
8026 app.foregroundServices = false;
8027 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8028 mPersistentStartingProcesses.add(app);
8029 restart = true;
8030 }
8031 }
8032 mProcessesOnHold.remove(app);
8033
The Android Open Source Project4df24232009-03-05 14:34:35 -08008034 if (app == mHomeProcess) {
8035 mHomeProcess = null;
8036 }
8037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008038 if (restart) {
8039 // We have components that still need to be running in the
8040 // process, so re-launch it.
8041 mProcessNames.put(app.processName, app.info.uid, app);
8042 startProcessLocked(app, "restart", app.processName);
8043 } else if (app.pid > 0 && app.pid != MY_PID) {
8044 // Goodbye!
8045 synchronized (mPidsSelfLocked) {
8046 mPidsSelfLocked.remove(app.pid);
8047 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8048 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008049 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008050 }
8051 }
8052
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008053 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8054 // Look through the content providers we are waiting to have launched,
8055 // and if any run in this process then either schedule a restart of
8056 // the process or kill the client waiting for it if this process has
8057 // gone bad.
8058 int NL = mLaunchingProviders.size();
8059 boolean restart = false;
8060 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008061 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008062 if (cpr.launchingApp == app) {
8063 if (!alwaysBad && !app.bad) {
8064 restart = true;
8065 } else {
8066 removeDyingProviderLocked(app, cpr);
8067 NL = mLaunchingProviders.size();
8068 }
8069 }
8070 }
8071 return restart;
8072 }
8073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008074 // =========================================================
8075 // SERVICES
8076 // =========================================================
8077
8078 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8079 ActivityManager.RunningServiceInfo info =
8080 new ActivityManager.RunningServiceInfo();
8081 info.service = r.name;
8082 if (r.app != null) {
8083 info.pid = r.app.pid;
8084 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008085 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086 info.process = r.processName;
8087 info.foreground = r.isForeground;
8088 info.activeSince = r.createTime;
8089 info.started = r.startRequested;
8090 info.clientCount = r.connections.size();
8091 info.crashCount = r.crashCount;
8092 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008093 if (r.isForeground) {
8094 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8095 }
8096 if (r.startRequested) {
8097 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8098 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008099 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008100 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8101 }
8102 if (r.app != null && r.app.persistent) {
8103 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8104 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008105
8106 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8107 for (int i=0; i<connl.size(); i++) {
8108 ConnectionRecord conn = connl.get(i);
8109 if (conn.clientLabel != 0) {
8110 info.clientPackage = conn.binding.client.info.packageName;
8111 info.clientLabel = conn.clientLabel;
8112 return info;
8113 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008114 }
8115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008116 return info;
8117 }
8118
8119 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8120 int flags) {
8121 synchronized (this) {
8122 ArrayList<ActivityManager.RunningServiceInfo> res
8123 = new ArrayList<ActivityManager.RunningServiceInfo>();
8124
8125 if (mServices.size() > 0) {
8126 Iterator<ServiceRecord> it = mServices.values().iterator();
8127 while (it.hasNext() && res.size() < maxNum) {
8128 res.add(makeRunningServiceInfoLocked(it.next()));
8129 }
8130 }
8131
8132 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8133 ServiceRecord r = mRestartingServices.get(i);
8134 ActivityManager.RunningServiceInfo info =
8135 makeRunningServiceInfoLocked(r);
8136 info.restarting = r.nextRestartTime;
8137 res.add(info);
8138 }
8139
8140 return res;
8141 }
8142 }
8143
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008144 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8145 synchronized (this) {
8146 ServiceRecord r = mServices.get(name);
8147 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008148 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8149 for (int i=0; i<conn.size(); i++) {
8150 if (conn.get(i).clientIntent != null) {
8151 return conn.get(i).clientIntent;
8152 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008153 }
8154 }
8155 }
8156 }
8157 return null;
8158 }
8159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008160 private final ServiceRecord findServiceLocked(ComponentName name,
8161 IBinder token) {
8162 ServiceRecord r = mServices.get(name);
8163 return r == token ? r : null;
8164 }
8165
8166 private final class ServiceLookupResult {
8167 final ServiceRecord record;
8168 final String permission;
8169
8170 ServiceLookupResult(ServiceRecord _record, String _permission) {
8171 record = _record;
8172 permission = _permission;
8173 }
8174 };
8175
8176 private ServiceLookupResult findServiceLocked(Intent service,
8177 String resolvedType) {
8178 ServiceRecord r = null;
8179 if (service.getComponent() != null) {
8180 r = mServices.get(service.getComponent());
8181 }
8182 if (r == null) {
8183 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8184 r = mServicesByIntent.get(filter);
8185 }
8186
8187 if (r == null) {
8188 try {
8189 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008190 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191 service, resolvedType, 0);
8192 ServiceInfo sInfo =
8193 rInfo != null ? rInfo.serviceInfo : null;
8194 if (sInfo == null) {
8195 return null;
8196 }
8197
8198 ComponentName name = new ComponentName(
8199 sInfo.applicationInfo.packageName, sInfo.name);
8200 r = mServices.get(name);
8201 } catch (RemoteException ex) {
8202 // pm is in same process, this will never happen.
8203 }
8204 }
8205 if (r != null) {
8206 int callingPid = Binder.getCallingPid();
8207 int callingUid = Binder.getCallingUid();
8208 if (checkComponentPermission(r.permission,
8209 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8210 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008211 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008212 + " from pid=" + callingPid
8213 + ", uid=" + callingUid
8214 + " requires " + r.permission);
8215 return new ServiceLookupResult(null, r.permission);
8216 }
8217 return new ServiceLookupResult(r, null);
8218 }
8219 return null;
8220 }
8221
8222 private class ServiceRestarter implements Runnable {
8223 private ServiceRecord mService;
8224
8225 void setService(ServiceRecord service) {
8226 mService = service;
8227 }
8228
8229 public void run() {
8230 synchronized(ActivityManagerService.this) {
8231 performServiceRestartLocked(mService);
8232 }
8233 }
8234 }
8235
8236 private ServiceLookupResult retrieveServiceLocked(Intent service,
8237 String resolvedType, int callingPid, int callingUid) {
8238 ServiceRecord r = null;
8239 if (service.getComponent() != null) {
8240 r = mServices.get(service.getComponent());
8241 }
8242 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8243 r = mServicesByIntent.get(filter);
8244 if (r == null) {
8245 try {
8246 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008247 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008248 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 ServiceInfo sInfo =
8250 rInfo != null ? rInfo.serviceInfo : null;
8251 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008252 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008253 ": not found");
8254 return null;
8255 }
8256
8257 ComponentName name = new ComponentName(
8258 sInfo.applicationInfo.packageName, sInfo.name);
8259 r = mServices.get(name);
8260 if (r == null) {
8261 filter = new Intent.FilterComparison(service.cloneFilter());
8262 ServiceRestarter res = new ServiceRestarter();
8263 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8264 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8265 synchronized (stats) {
8266 ss = stats.getServiceStatsLocked(
8267 sInfo.applicationInfo.uid, sInfo.packageName,
8268 sInfo.name);
8269 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008270 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271 res.setService(r);
8272 mServices.put(name, r);
8273 mServicesByIntent.put(filter, r);
8274
8275 // Make sure this component isn't in the pending list.
8276 int N = mPendingServices.size();
8277 for (int i=0; i<N; i++) {
8278 ServiceRecord pr = mPendingServices.get(i);
8279 if (pr.name.equals(name)) {
8280 mPendingServices.remove(i);
8281 i--;
8282 N--;
8283 }
8284 }
8285 }
8286 } catch (RemoteException ex) {
8287 // pm is in same process, this will never happen.
8288 }
8289 }
8290 if (r != null) {
8291 if (checkComponentPermission(r.permission,
8292 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8293 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008294 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 + " from pid=" + Binder.getCallingPid()
8296 + ", uid=" + Binder.getCallingUid()
8297 + " requires " + r.permission);
8298 return new ServiceLookupResult(null, r.permission);
8299 }
8300 return new ServiceLookupResult(r, null);
8301 }
8302 return null;
8303 }
8304
8305 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8306 long now = SystemClock.uptimeMillis();
8307 if (r.executeNesting == 0 && r.app != null) {
8308 if (r.app.executingServices.size() == 0) {
8309 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8310 msg.obj = r.app;
8311 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8312 }
8313 r.app.executingServices.add(r);
8314 }
8315 r.executeNesting++;
8316 r.executingStart = now;
8317 }
8318
8319 private final void sendServiceArgsLocked(ServiceRecord r,
8320 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008321 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008322 if (N == 0) {
8323 return;
8324 }
8325
Dianne Hackborn39792d22010-08-19 18:01:52 -07008326 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008327 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008328 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008329 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8330 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008331 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008332 // If somehow we got a dummy start at the front, then
8333 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008334 continue;
8335 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008336 si.deliveredTime = SystemClock.uptimeMillis();
8337 r.deliveredStarts.add(si);
8338 si.deliveryCount++;
8339 if (si.targetPermissionUid >= 0) {
8340 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008341 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008342 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008343 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008344 bumpServiceExecutingLocked(r);
8345 if (!oomAdjusted) {
8346 oomAdjusted = true;
8347 updateOomAdjLocked(r.app);
8348 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008349 int flags = 0;
8350 if (si.deliveryCount > 0) {
8351 flags |= Service.START_FLAG_RETRY;
8352 }
8353 if (si.doneExecutingCount > 0) {
8354 flags |= Service.START_FLAG_REDELIVERY;
8355 }
8356 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008357 } catch (RemoteException e) {
8358 // Remote process gone... we'll let the normal cleanup take
8359 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008360 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008361 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008362 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008363 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008364 break;
8365 }
8366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008367 }
8368
8369 private final boolean requestServiceBindingLocked(ServiceRecord r,
8370 IntentBindRecord i, boolean rebind) {
8371 if (r.app == null || r.app.thread == null) {
8372 // If service is not currently running, can't yet bind.
8373 return false;
8374 }
8375 if ((!i.requested || rebind) && i.apps.size() > 0) {
8376 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008377 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
8378 + " in " + i + ": shouldUnbind=" + i.hasBound);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008379 bumpServiceExecutingLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008380 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8381 if (!rebind) {
8382 i.requested = true;
8383 }
8384 i.hasBound = true;
8385 i.doRebind = false;
8386 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008387 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 return false;
8389 }
8390 }
8391 return true;
8392 }
8393
8394 private final void requestServiceBindingsLocked(ServiceRecord r) {
8395 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8396 while (bindings.hasNext()) {
8397 IntentBindRecord i = bindings.next();
8398 if (!requestServiceBindingLocked(r, i, false)) {
8399 break;
8400 }
8401 }
8402 }
8403
8404 private final void realStartServiceLocked(ServiceRecord r,
8405 ProcessRecord app) throws RemoteException {
8406 if (app.thread == null) {
8407 throw new RemoteException();
8408 }
8409
8410 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008411 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008412
8413 app.services.add(r);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008414 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008415 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008416 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008417
8418 boolean created = false;
8419 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008420 mStringBuilder.setLength(0);
8421 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008422 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008423 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008424 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 synchronized (r.stats.getBatteryStats()) {
8426 r.stats.startLaunchedLocked();
8427 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008428 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008429 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008430 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008431 created = true;
8432 } finally {
8433 if (!created) {
8434 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008435 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 }
8437 }
8438
8439 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008440
8441 // If the service is in the started state, and there are no
8442 // pending arguments, then fake up one so its onStartCommand() will
8443 // be called.
8444 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8445 r.lastStartId++;
8446 if (r.lastStartId < 1) {
8447 r.lastStartId = 1;
8448 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008449 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008450 }
8451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 sendServiceArgsLocked(r, true);
8453 }
8454
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008455 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8456 boolean allowCancel) {
8457 boolean canceled = false;
8458
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008459 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008460 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008461 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008462
8463 // Any delivered but not yet finished starts should be put back
8464 // on the pending list.
8465 final int N = r.deliveredStarts.size();
8466 if (N > 0) {
8467 for (int i=N-1; i>=0; i--) {
8468 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008469 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008470 if (si.intent == null) {
8471 // We'll generate this again if needed.
8472 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8473 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8474 r.pendingStarts.add(0, si);
8475 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8476 dur *= 2;
8477 if (minDuration < dur) minDuration = dur;
8478 if (resetTime < dur) resetTime = dur;
8479 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008480 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008481 + r.name);
8482 canceled = true;
8483 }
8484 }
8485 r.deliveredStarts.clear();
8486 }
8487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008488 r.totalRestartCount++;
8489 if (r.restartDelay == 0) {
8490 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008491 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 } else {
8493 // If it has been a "reasonably long time" since the service
8494 // was started, then reset our restart duration back to
8495 // the beginning, so we don't infinitely increase the duration
8496 // on a service that just occasionally gets killed (which is
8497 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008498 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008499 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008500 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008501 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008502 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008503 if (r.restartDelay < minDuration) {
8504 r.restartDelay = minDuration;
8505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008506 }
8507 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008508
8509 r.nextRestartTime = now + r.restartDelay;
8510
8511 // Make sure that we don't end up restarting a bunch of services
8512 // all at the same time.
8513 boolean repeat;
8514 do {
8515 repeat = false;
8516 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8517 ServiceRecord r2 = mRestartingServices.get(i);
8518 if (r2 != r && r.nextRestartTime
8519 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8520 && r.nextRestartTime
8521 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8522 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8523 r.restartDelay = r.nextRestartTime - now;
8524 repeat = true;
8525 break;
8526 }
8527 }
8528 } while (repeat);
8529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008530 if (!mRestartingServices.contains(r)) {
8531 mRestartingServices.add(r);
8532 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008533
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008534 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008536 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008537 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008539 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008541 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 r.shortName, r.restartDelay);
8543
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008544 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008545 }
8546
8547 final void performServiceRestartLocked(ServiceRecord r) {
8548 if (!mRestartingServices.contains(r)) {
8549 return;
8550 }
8551 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8552 }
8553
8554 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8555 if (r.restartDelay == 0) {
8556 return false;
8557 }
8558 r.resetRestartCounter();
8559 mRestartingServices.remove(r);
8560 mHandler.removeCallbacks(r.restarter);
8561 return true;
8562 }
8563
8564 private final boolean bringUpServiceLocked(ServiceRecord r,
8565 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008566 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008567 //r.dump(" ");
8568
Dianne Hackborn36124872009-10-08 16:22:03 -07008569 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 sendServiceArgsLocked(r, false);
8571 return true;
8572 }
8573
8574 if (!whileRestarting && r.restartDelay > 0) {
8575 // If waiting for a restart, then do nothing.
8576 return true;
8577 }
8578
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008579 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008580
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008581 // We are now bringing the service up, so no longer in the
8582 // restarting state.
8583 mRestartingServices.remove(r);
8584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008585 final String appName = r.processName;
8586 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8587 if (app != null && app.thread != null) {
8588 try {
8589 realStartServiceLocked(r, app);
8590 return true;
8591 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008592 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008593 }
8594
8595 // If a dead object exception was thrown -- fall through to
8596 // restart the application.
8597 }
8598
Dianne Hackborn36124872009-10-08 16:22:03 -07008599 // Not running -- get it started, and enqueue this service record
8600 // to be executed when the app comes up.
8601 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8602 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008603 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008604 + r.appInfo.packageName + "/"
8605 + r.appInfo.uid + " for service "
8606 + r.intent.getIntent() + ": process is bad");
8607 bringDownServiceLocked(r, true);
8608 return false;
8609 }
8610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008611 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008612 mPendingServices.add(r);
8613 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008615 return true;
8616 }
8617
8618 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008619 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008620 //r.dump(" ");
8621
8622 // Does it still need to run?
8623 if (!force && r.startRequested) {
8624 return;
8625 }
8626 if (r.connections.size() > 0) {
8627 if (!force) {
8628 // XXX should probably keep a count of the number of auto-create
8629 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008630 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008631 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008632 ArrayList<ConnectionRecord> cr = it.next();
8633 for (int i=0; i<cr.size(); i++) {
8634 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8635 return;
8636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637 }
8638 }
8639 }
8640
8641 // Report to all of the connections that the service is no longer
8642 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008643 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008645 ArrayList<ConnectionRecord> c = it.next();
8646 for (int i=0; i<c.size(); i++) {
8647 try {
8648 c.get(i).conn.connected(r.name, null);
8649 } catch (Exception e) {
8650 Slog.w(TAG, "Failure disconnecting service " + r.name +
8651 " to connection " + c.get(i).conn.asBinder() +
8652 " (in " + c.get(i).binding.client.processName + ")", e);
8653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008654 }
8655 }
8656 }
8657
8658 // Tell the service that it has been unbound.
8659 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8660 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8661 while (it.hasNext()) {
8662 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008663 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008664 + ": hasBound=" + ibr.hasBound);
8665 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8666 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008667 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
8668 + " for " + ibr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 bumpServiceExecutingLocked(r);
8670 updateOomAdjLocked(r.app);
8671 ibr.hasBound = false;
8672 r.app.thread.scheduleUnbindService(r,
8673 ibr.intent.getIntent());
8674 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008675 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008676 + r.shortName, e);
8677 serviceDoneExecutingLocked(r, true);
8678 }
8679 }
8680 }
8681 }
8682
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008683 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008684 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008685 System.identityHashCode(r), r.shortName,
8686 (r.app != null) ? r.app.pid : -1);
8687
8688 mServices.remove(r.name);
8689 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008690 r.totalRestartCount = 0;
8691 unscheduleServiceRestartLocked(r);
8692
8693 // Also make sure it is not on the pending list.
8694 int N = mPendingServices.size();
8695 for (int i=0; i<N; i++) {
8696 if (mPendingServices.get(i) == r) {
8697 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008698 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008699 i--;
8700 N--;
8701 }
8702 }
8703
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008704 r.cancelNotification();
8705 r.isForeground = false;
8706 r.foregroundId = 0;
8707 r.foregroundNoti = null;
8708
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008709 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008710 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008711 r.pendingStarts.clear();
8712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008713 if (r.app != null) {
8714 synchronized (r.stats.getBatteryStats()) {
8715 r.stats.stopLaunchedLocked();
8716 }
8717 r.app.services.remove(r);
8718 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008719 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008720 if (DEBUG_SERVICE) {
8721 RuntimeException here = new RuntimeException();
8722 here.fillInStackTrace();
8723 Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
8724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008725 bumpServiceExecutingLocked(r);
8726 mStoppingServices.add(r);
8727 updateOomAdjLocked(r.app);
8728 r.app.thread.scheduleStopService(r);
8729 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008730 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008731 + r.shortName, e);
8732 serviceDoneExecutingLocked(r, true);
8733 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008734 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008735 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008736 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008737 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 }
8739 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008740 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008741 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008742 }
8743 }
8744
8745 ComponentName startServiceLocked(IApplicationThread caller,
8746 Intent service, String resolvedType,
8747 int callingPid, int callingUid) {
8748 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008749 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008750 + " type=" + resolvedType + " args=" + service.getExtras());
8751
8752 if (caller != null) {
8753 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8754 if (callerApp == null) {
8755 throw new SecurityException(
8756 "Unable to find app for caller " + caller
8757 + " (pid=" + Binder.getCallingPid()
8758 + ") when starting service " + service);
8759 }
8760 }
8761
8762 ServiceLookupResult res =
8763 retrieveServiceLocked(service, resolvedType,
8764 callingPid, callingUid);
8765 if (res == null) {
8766 return null;
8767 }
8768 if (res.record == null) {
8769 return new ComponentName("!", res.permission != null
8770 ? res.permission : "private to package");
8771 }
8772 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07008773 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
8774 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008775 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008776 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008777 }
8778 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008779 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008780 r.lastStartId++;
8781 if (r.lastStartId < 1) {
8782 r.lastStartId = 1;
8783 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008784 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
8785 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 r.lastActivity = SystemClock.uptimeMillis();
8787 synchronized (r.stats.getBatteryStats()) {
8788 r.stats.startRunningLocked();
8789 }
8790 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8791 return new ComponentName("!", "Service process is bad");
8792 }
8793 return r.name;
8794 }
8795 }
8796
8797 public ComponentName startService(IApplicationThread caller, Intent service,
8798 String resolvedType) {
8799 // Refuse possible leaked file descriptors
8800 if (service != null && service.hasFileDescriptors() == true) {
8801 throw new IllegalArgumentException("File descriptors passed in Intent");
8802 }
8803
8804 synchronized(this) {
8805 final int callingPid = Binder.getCallingPid();
8806 final int callingUid = Binder.getCallingUid();
8807 final long origId = Binder.clearCallingIdentity();
8808 ComponentName res = startServiceLocked(caller, service,
8809 resolvedType, callingPid, callingUid);
8810 Binder.restoreCallingIdentity(origId);
8811 return res;
8812 }
8813 }
8814
8815 ComponentName startServiceInPackage(int uid,
8816 Intent service, String resolvedType) {
8817 synchronized(this) {
8818 final long origId = Binder.clearCallingIdentity();
8819 ComponentName res = startServiceLocked(null, service,
8820 resolvedType, -1, uid);
8821 Binder.restoreCallingIdentity(origId);
8822 return res;
8823 }
8824 }
8825
8826 public int stopService(IApplicationThread caller, Intent service,
8827 String resolvedType) {
8828 // Refuse possible leaked file descriptors
8829 if (service != null && service.hasFileDescriptors() == true) {
8830 throw new IllegalArgumentException("File descriptors passed in Intent");
8831 }
8832
8833 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008834 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008835 + " type=" + resolvedType);
8836
8837 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8838 if (caller != null && callerApp == null) {
8839 throw new SecurityException(
8840 "Unable to find app for caller " + caller
8841 + " (pid=" + Binder.getCallingPid()
8842 + ") when stopping service " + service);
8843 }
8844
8845 // If this service is active, make sure it is stopped.
8846 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8847 if (r != null) {
8848 if (r.record != null) {
8849 synchronized (r.record.stats.getBatteryStats()) {
8850 r.record.stats.stopRunningLocked();
8851 }
8852 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008853 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008854 final long origId = Binder.clearCallingIdentity();
8855 bringDownServiceLocked(r.record, false);
8856 Binder.restoreCallingIdentity(origId);
8857 return 1;
8858 }
8859 return -1;
8860 }
8861 }
8862
8863 return 0;
8864 }
8865
8866 public IBinder peekService(Intent service, String resolvedType) {
8867 // Refuse possible leaked file descriptors
8868 if (service != null && service.hasFileDescriptors() == true) {
8869 throw new IllegalArgumentException("File descriptors passed in Intent");
8870 }
8871
8872 IBinder ret = null;
8873
8874 synchronized(this) {
8875 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8876
8877 if (r != null) {
8878 // r.record is null if findServiceLocked() failed the caller permission check
8879 if (r.record == null) {
8880 throw new SecurityException(
8881 "Permission Denial: Accessing service " + r.record.name
8882 + " from pid=" + Binder.getCallingPid()
8883 + ", uid=" + Binder.getCallingUid()
8884 + " requires " + r.permission);
8885 }
8886 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8887 if (ib != null) {
8888 ret = ib.binder;
8889 }
8890 }
8891 }
8892
8893 return ret;
8894 }
8895
8896 public boolean stopServiceToken(ComponentName className, IBinder token,
8897 int startId) {
8898 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008899 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008900 + " " + token + " startId=" + startId);
8901 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008902 if (r != null) {
8903 if (startId >= 0) {
8904 // Asked to only stop if done with all work. Note that
8905 // to avoid leaks, we will take this as dropping all
8906 // start items up to and including this one.
8907 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8908 if (si != null) {
8909 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008910 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
8911 cur.removeUriPermissionsLocked();
8912 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008913 break;
8914 }
8915 }
8916 }
8917
8918 if (r.lastStartId != startId) {
8919 return false;
8920 }
8921
8922 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008923 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008924 + " is last, but have " + r.deliveredStarts.size()
8925 + " remaining args");
8926 }
8927 }
8928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008929 synchronized (r.stats.getBatteryStats()) {
8930 r.stats.stopRunningLocked();
8931 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008932 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008933 }
8934 final long origId = Binder.clearCallingIdentity();
8935 bringDownServiceLocked(r, false);
8936 Binder.restoreCallingIdentity(origId);
8937 return true;
8938 }
8939 }
8940 return false;
8941 }
8942
8943 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008944 int id, Notification notification, boolean removeNotification) {
8945 final long origId = Binder.clearCallingIdentity();
8946 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008947 synchronized(this) {
8948 ServiceRecord r = findServiceLocked(className, token);
8949 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008950 if (id != 0) {
8951 if (notification == null) {
8952 throw new IllegalArgumentException("null notification");
8953 }
8954 if (r.foregroundId != id) {
8955 r.cancelNotification();
8956 r.foregroundId = id;
8957 }
8958 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8959 r.foregroundNoti = notification;
8960 r.isForeground = true;
8961 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 if (r.app != null) {
8963 updateServiceForegroundLocked(r.app, true);
8964 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008965 } else {
8966 if (r.isForeground) {
8967 r.isForeground = false;
8968 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008969 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008970 updateServiceForegroundLocked(r.app, true);
8971 }
8972 }
8973 if (removeNotification) {
8974 r.cancelNotification();
8975 r.foregroundId = 0;
8976 r.foregroundNoti = null;
8977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008978 }
8979 }
8980 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008981 } finally {
8982 Binder.restoreCallingIdentity(origId);
8983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 }
8985
8986 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8987 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008988 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008989 if (sr.isForeground) {
8990 anyForeground = true;
8991 break;
8992 }
8993 }
8994 if (anyForeground != proc.foregroundServices) {
8995 proc.foregroundServices = anyForeground;
8996 if (oomAdj) {
8997 updateOomAdjLocked();
8998 }
8999 }
9000 }
9001
9002 public int bindService(IApplicationThread caller, IBinder token,
9003 Intent service, String resolvedType,
9004 IServiceConnection connection, int flags) {
9005 // Refuse possible leaked file descriptors
9006 if (service != null && service.hasFileDescriptors() == true) {
9007 throw new IllegalArgumentException("File descriptors passed in Intent");
9008 }
9009
9010 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009011 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009012 + " type=" + resolvedType + " conn=" + connection.asBinder()
9013 + " flags=0x" + Integer.toHexString(flags));
9014 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9015 if (callerApp == null) {
9016 throw new SecurityException(
9017 "Unable to find app for caller " + caller
9018 + " (pid=" + Binder.getCallingPid()
9019 + ") when binding service " + service);
9020 }
9021
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009022 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009023 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009024 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009025 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009026 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009027 return 0;
9028 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009029 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009030 }
9031
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009032 int clientLabel = 0;
9033 PendingIntent clientIntent = null;
9034
9035 if (callerApp.info.uid == Process.SYSTEM_UID) {
9036 // Hacky kind of thing -- allow system stuff to tell us
9037 // what they are, so we can report this elsewhere for
9038 // others to know why certain services are running.
9039 try {
9040 clientIntent = (PendingIntent)service.getParcelableExtra(
9041 Intent.EXTRA_CLIENT_INTENT);
9042 } catch (RuntimeException e) {
9043 }
9044 if (clientIntent != null) {
9045 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9046 if (clientLabel != 0) {
9047 // There are no useful extras in the intent, trash them.
9048 // System code calling with this stuff just needs to know
9049 // this will happen.
9050 service = service.cloneFilter();
9051 }
9052 }
9053 }
9054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 ServiceLookupResult res =
9056 retrieveServiceLocked(service, resolvedType,
9057 Binder.getCallingPid(), Binder.getCallingUid());
9058 if (res == null) {
9059 return 0;
9060 }
9061 if (res.record == null) {
9062 return -1;
9063 }
9064 ServiceRecord s = res.record;
9065
9066 final long origId = Binder.clearCallingIdentity();
9067
9068 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009069 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009070 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 }
9072
9073 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9074 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009075 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009076
9077 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009078 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9079 if (clist == null) {
9080 clist = new ArrayList<ConnectionRecord>();
9081 s.connections.put(binder, clist);
9082 }
9083 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009084 b.connections.add(c);
9085 if (activity != null) {
9086 if (activity.connections == null) {
9087 activity.connections = new HashSet<ConnectionRecord>();
9088 }
9089 activity.connections.add(c);
9090 }
9091 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009092 clist = mServiceConnections.get(binder);
9093 if (clist == null) {
9094 clist = new ArrayList<ConnectionRecord>();
9095 mServiceConnections.put(binder, clist);
9096 }
9097 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098
9099 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9100 s.lastActivity = SystemClock.uptimeMillis();
9101 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9102 return 0;
9103 }
9104 }
9105
9106 if (s.app != null) {
9107 // This could have made the service more important.
9108 updateOomAdjLocked(s.app);
9109 }
9110
Joe Onorato8a9b2202010-02-26 18:56:32 -08009111 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 + ": received=" + b.intent.received
9113 + " apps=" + b.intent.apps.size()
9114 + " doRebind=" + b.intent.doRebind);
9115
9116 if (s.app != null && b.intent.received) {
9117 // Service is already running, so we can immediately
9118 // publish the connection.
9119 try {
9120 c.conn.connected(s.name, b.intent.binder);
9121 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009122 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009123 + " to connection " + c.conn.asBinder()
9124 + " (in " + c.binding.client.processName + ")", e);
9125 }
9126
9127 // If this is the first app connected back to this binding,
9128 // and the service had previously asked to be told when
9129 // rebound, then do so.
9130 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9131 requestServiceBindingLocked(s, b.intent, true);
9132 }
9133 } else if (!b.intent.requested) {
9134 requestServiceBindingLocked(s, b.intent, false);
9135 }
9136
9137 Binder.restoreCallingIdentity(origId);
9138 }
9139
9140 return 1;
9141 }
9142
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009143 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009144 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009145 IBinder binder = c.conn.asBinder();
9146 AppBindRecord b = c.binding;
9147 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009148 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9149 if (clist != null) {
9150 clist.remove(c);
9151 if (clist.size() == 0) {
9152 s.connections.remove(binder);
9153 }
9154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155 b.connections.remove(c);
9156 if (c.activity != null && c.activity != skipAct) {
9157 if (c.activity.connections != null) {
9158 c.activity.connections.remove(c);
9159 }
9160 }
9161 if (b.client != skipApp) {
9162 b.client.connections.remove(c);
9163 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009164 clist = mServiceConnections.get(binder);
9165 if (clist != null) {
9166 clist.remove(c);
9167 if (clist.size() == 0) {
9168 mServiceConnections.remove(binder);
9169 }
9170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009171
9172 if (b.connections.size() == 0) {
9173 b.intent.apps.remove(b.client);
9174 }
9175
Joe Onorato8a9b2202010-02-26 18:56:32 -08009176 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 + ": shouldUnbind=" + b.intent.hasBound);
9178 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9179 && b.intent.hasBound) {
9180 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009181 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
9182 + " from " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009183 bumpServiceExecutingLocked(s);
9184 updateOomAdjLocked(s.app);
9185 b.intent.hasBound = false;
9186 // Assume the client doesn't want to know about a rebind;
9187 // we will deal with that later if it asks for one.
9188 b.intent.doRebind = false;
9189 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9190 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009191 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 serviceDoneExecutingLocked(s, true);
9193 }
9194 }
9195
9196 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9197 bringDownServiceLocked(s, false);
9198 }
9199 }
9200
9201 public boolean unbindService(IServiceConnection connection) {
9202 synchronized (this) {
9203 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009204 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009205 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9206 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009207 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009208 + connection.asBinder());
9209 return false;
9210 }
9211
9212 final long origId = Binder.clearCallingIdentity();
9213
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009214 while (clist.size() > 0) {
9215 ConnectionRecord r = clist.get(0);
9216 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009218 if (r.binding.service.app != null) {
9219 // This could have made the service less important.
9220 updateOomAdjLocked(r.binding.service.app);
9221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 }
9223
9224 Binder.restoreCallingIdentity(origId);
9225 }
9226
9227 return true;
9228 }
9229
9230 public void publishService(IBinder token, Intent intent, IBinder service) {
9231 // Refuse possible leaked file descriptors
9232 if (intent != null && intent.hasFileDescriptors() == true) {
9233 throw new IllegalArgumentException("File descriptors passed in Intent");
9234 }
9235
9236 synchronized(this) {
9237 if (!(token instanceof ServiceRecord)) {
9238 throw new IllegalArgumentException("Invalid service token");
9239 }
9240 ServiceRecord r = (ServiceRecord)token;
9241
9242 final long origId = Binder.clearCallingIdentity();
9243
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009244 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009245 + " " + intent + ": " + service);
9246 if (r != null) {
9247 Intent.FilterComparison filter
9248 = new Intent.FilterComparison(intent);
9249 IntentBindRecord b = r.bindings.get(filter);
9250 if (b != null && !b.received) {
9251 b.binder = service;
9252 b.requested = true;
9253 b.received = true;
9254 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009255 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009256 = r.connections.values().iterator();
9257 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009258 ArrayList<ConnectionRecord> clist = it.next();
9259 for (int i=0; i<clist.size(); i++) {
9260 ConnectionRecord c = clist.get(i);
9261 if (!filter.equals(c.binding.intent.intent)) {
9262 if (DEBUG_SERVICE) Slog.v(
9263 TAG, "Not publishing to: " + c);
9264 if (DEBUG_SERVICE) Slog.v(
9265 TAG, "Bound intent: " + c.binding.intent.intent);
9266 if (DEBUG_SERVICE) Slog.v(
9267 TAG, "Published intent: " + intent);
9268 continue;
9269 }
9270 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9271 try {
9272 c.conn.connected(r.name, service);
9273 } catch (Exception e) {
9274 Slog.w(TAG, "Failure sending service " + r.name +
9275 " to connection " + c.conn.asBinder() +
9276 " (in " + c.binding.client.processName + ")", e);
9277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 }
9279 }
9280 }
9281 }
9282
9283 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9284
9285 Binder.restoreCallingIdentity(origId);
9286 }
9287 }
9288 }
9289
9290 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9291 // Refuse possible leaked file descriptors
9292 if (intent != null && intent.hasFileDescriptors() == true) {
9293 throw new IllegalArgumentException("File descriptors passed in Intent");
9294 }
9295
9296 synchronized(this) {
9297 if (!(token instanceof ServiceRecord)) {
9298 throw new IllegalArgumentException("Invalid service token");
9299 }
9300 ServiceRecord r = (ServiceRecord)token;
9301
9302 final long origId = Binder.clearCallingIdentity();
9303
9304 if (r != null) {
9305 Intent.FilterComparison filter
9306 = new Intent.FilterComparison(intent);
9307 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009308 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 + " at " + b + ": apps="
9310 + (b != null ? b.apps.size() : 0));
9311 if (b != null) {
9312 if (b.apps.size() > 0) {
9313 // Applications have already bound since the last
9314 // unbind, so just rebind right here.
9315 requestServiceBindingLocked(r, b, true);
9316 } else {
9317 // Note to tell the service the next time there is
9318 // a new client.
9319 b.doRebind = true;
9320 }
9321 }
9322
9323 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9324
9325 Binder.restoreCallingIdentity(origId);
9326 }
9327 }
9328 }
9329
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009330 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009331 synchronized(this) {
9332 if (!(token instanceof ServiceRecord)) {
9333 throw new IllegalArgumentException("Invalid service token");
9334 }
9335 ServiceRecord r = (ServiceRecord)token;
9336 boolean inStopping = mStoppingServices.contains(token);
9337 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009338 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009339 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 + " with incorrect token: given " + token
9341 + ", expected " + r);
9342 return;
9343 }
9344
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009345 if (type == 1) {
9346 // This is a call from a service start... take care of
9347 // book-keeping.
9348 r.callStart = true;
9349 switch (res) {
9350 case Service.START_STICKY_COMPATIBILITY:
9351 case Service.START_STICKY: {
9352 // We are done with the associated start arguments.
9353 r.findDeliveredStart(startId, true);
9354 // Don't stop if killed.
9355 r.stopIfKilled = false;
9356 break;
9357 }
9358 case Service.START_NOT_STICKY: {
9359 // We are done with the associated start arguments.
9360 r.findDeliveredStart(startId, true);
9361 if (r.lastStartId == startId) {
9362 // There is no more work, and this service
9363 // doesn't want to hang around if killed.
9364 r.stopIfKilled = true;
9365 }
9366 break;
9367 }
9368 case Service.START_REDELIVER_INTENT: {
9369 // We'll keep this item until they explicitly
9370 // call stop for it, but keep track of the fact
9371 // that it was delivered.
9372 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9373 if (si != null) {
9374 si.deliveryCount = 0;
9375 si.doneExecutingCount++;
9376 // Don't stop if killed.
9377 r.stopIfKilled = true;
9378 }
9379 break;
9380 }
9381 default:
9382 throw new IllegalArgumentException(
9383 "Unknown service start result: " + res);
9384 }
9385 if (res == Service.START_STICKY_COMPATIBILITY) {
9386 r.callStart = false;
9387 }
9388 }
9389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009390 final long origId = Binder.clearCallingIdentity();
9391 serviceDoneExecutingLocked(r, inStopping);
9392 Binder.restoreCallingIdentity(origId);
9393 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009394 Slog.w(TAG, "Done executing unknown service from pid "
9395 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009396 }
9397 }
9398 }
9399
9400 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009401 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9402 + ": nesting=" + r.executeNesting
9403 + ", inStopping=" + inStopping + ", app=" + r.app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009404 r.executeNesting--;
9405 if (r.executeNesting <= 0 && r.app != null) {
9406 r.app.executingServices.remove(r);
9407 if (r.app.executingServices.size() == 0) {
9408 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9409 }
9410 if (inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009411 if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009412 mStoppingServices.remove(r);
9413 }
9414 updateOomAdjLocked(r.app);
9415 }
9416 }
9417
9418 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009419 String anrMessage = null;
9420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009421 synchronized(this) {
9422 if (proc.executingServices.size() == 0 || proc.thread == null) {
9423 return;
9424 }
9425 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9426 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9427 ServiceRecord timeout = null;
9428 long nextTime = 0;
9429 while (it.hasNext()) {
9430 ServiceRecord sr = it.next();
9431 if (sr.executingStart < maxTime) {
9432 timeout = sr;
9433 break;
9434 }
9435 if (sr.executingStart > nextTime) {
9436 nextTime = sr.executingStart;
9437 }
9438 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009439 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009440 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009441 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009442 } else {
9443 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9444 msg.obj = proc;
9445 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9446 }
9447 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009448
9449 if (anrMessage != null) {
9450 appNotResponding(proc, null, null, anrMessage);
9451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 }
9453
9454 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009455 // BACKUP AND RESTORE
9456 // =========================================================
9457
9458 // Cause the target app to be launched if necessary and its backup agent
9459 // instantiated. The backup agent will invoke backupAgentCreated() on the
9460 // activity manager to announce its creation.
9461 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009462 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009463 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9464
9465 synchronized(this) {
9466 // !!! TODO: currently no check here that we're already bound
9467 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9468 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9469 synchronized (stats) {
9470 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9471 }
9472
9473 BackupRecord r = new BackupRecord(ss, app, backupMode);
9474 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9475 // startProcessLocked() returns existing proc's record if it's already running
9476 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009477 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009478 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009479 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009480 return false;
9481 }
9482
9483 r.app = proc;
9484 mBackupTarget = r;
9485 mBackupAppName = app.packageName;
9486
Christopher Tate6fa95972009-06-05 18:43:55 -07009487 // Try not to kill the process during backup
9488 updateOomAdjLocked(proc);
9489
Christopher Tate181fafa2009-05-14 11:12:14 -07009490 // If the process is already attached, schedule the creation of the backup agent now.
9491 // If it is not yet live, this will be done when it attaches to the framework.
9492 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009493 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009494 try {
9495 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9496 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009497 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009498 }
9499 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009500 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009501 }
9502 // Invariants: at this point, the target app process exists and the application
9503 // is either already running or in the process of coming up. mBackupTarget and
9504 // mBackupAppName describe the app, so that when it binds back to the AM we
9505 // know that it's scheduled for a backup-agent operation.
9506 }
9507
9508 return true;
9509 }
9510
9511 // A backup agent has just come up
9512 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009513 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009514 + " = " + agent);
9515
9516 synchronized(this) {
9517 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009518 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009519 return;
9520 }
9521
Christopher Tate043dadc2009-06-02 16:11:00 -07009522 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009523 try {
9524 IBackupManager bm = IBackupManager.Stub.asInterface(
9525 ServiceManager.getService(Context.BACKUP_SERVICE));
9526 bm.agentConnected(agentPackageName, agent);
9527 } catch (RemoteException e) {
9528 // can't happen; the backup manager service is local
9529 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009530 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009531 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009532 } finally {
9533 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009534 }
9535 }
9536 }
9537
9538 // done with this agent
9539 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009540 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009541 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009542 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009543 return;
9544 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009545
9546 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009547 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009548 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009549 return;
9550 }
9551
Christopher Tate181fafa2009-05-14 11:12:14 -07009552 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009553 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009554 return;
9555 }
9556
Christopher Tate6fa95972009-06-05 18:43:55 -07009557 ProcessRecord proc = mBackupTarget.app;
9558 mBackupTarget = null;
9559 mBackupAppName = null;
9560
9561 // Not backing this app up any more; reset its OOM adjustment
9562 updateOomAdjLocked(proc);
9563
Christopher Tatec7b31e32009-06-10 15:49:30 -07009564 // If the app crashed during backup, 'thread' will be null here
9565 if (proc.thread != null) {
9566 try {
9567 proc.thread.scheduleDestroyBackupAgent(appInfo);
9568 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009569 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009570 e.printStackTrace();
9571 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009572 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009573 }
9574 }
9575 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009576 // BROADCASTS
9577 // =========================================================
9578
Josh Bartel7f208742010-02-25 11:01:44 -06009579 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009580 List cur) {
9581 final ContentResolver resolver = mContext.getContentResolver();
9582 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9583 if (list == null) {
9584 return cur;
9585 }
9586 int N = list.size();
9587 for (int i=0; i<N; i++) {
9588 Intent intent = list.get(i);
9589 if (filter.match(resolver, intent, true, TAG) >= 0) {
9590 if (cur == null) {
9591 cur = new ArrayList<Intent>();
9592 }
9593 cur.add(intent);
9594 }
9595 }
9596 return cur;
9597 }
9598
9599 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009600 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009601 + mBroadcastsScheduled);
9602
9603 if (mBroadcastsScheduled) {
9604 return;
9605 }
9606 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9607 mBroadcastsScheduled = true;
9608 }
9609
9610 public Intent registerReceiver(IApplicationThread caller,
9611 IIntentReceiver receiver, IntentFilter filter, String permission) {
9612 synchronized(this) {
9613 ProcessRecord callerApp = null;
9614 if (caller != null) {
9615 callerApp = getRecordForAppLocked(caller);
9616 if (callerApp == null) {
9617 throw new SecurityException(
9618 "Unable to find app for caller " + caller
9619 + " (pid=" + Binder.getCallingPid()
9620 + ") when registering receiver " + receiver);
9621 }
9622 }
9623
9624 List allSticky = null;
9625
9626 // Look for any matching sticky broadcasts...
9627 Iterator actions = filter.actionsIterator();
9628 if (actions != null) {
9629 while (actions.hasNext()) {
9630 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009631 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009632 }
9633 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009634 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 }
9636
9637 // The first sticky in the list is returned directly back to
9638 // the client.
9639 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9640
Joe Onorato8a9b2202010-02-26 18:56:32 -08009641 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009642 + ": " + sticky);
9643
9644 if (receiver == null) {
9645 return sticky;
9646 }
9647
9648 ReceiverList rl
9649 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9650 if (rl == null) {
9651 rl = new ReceiverList(this, callerApp,
9652 Binder.getCallingPid(),
9653 Binder.getCallingUid(), receiver);
9654 if (rl.app != null) {
9655 rl.app.receivers.add(rl);
9656 } else {
9657 try {
9658 receiver.asBinder().linkToDeath(rl, 0);
9659 } catch (RemoteException e) {
9660 return sticky;
9661 }
9662 rl.linkedToDeath = true;
9663 }
9664 mRegisteredReceivers.put(receiver.asBinder(), rl);
9665 }
9666 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9667 rl.add(bf);
9668 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009669 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009670 }
9671 mReceiverResolver.addFilter(bf);
9672
9673 // Enqueue broadcasts for all existing stickies that match
9674 // this filter.
9675 if (allSticky != null) {
9676 ArrayList receivers = new ArrayList();
9677 receivers.add(bf);
9678
9679 int N = allSticky.size();
9680 for (int i=0; i<N; i++) {
9681 Intent intent = (Intent)allSticky.get(i);
9682 BroadcastRecord r = new BroadcastRecord(intent, null,
9683 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009684 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009685 if (mParallelBroadcasts.size() == 0) {
9686 scheduleBroadcastsLocked();
9687 }
9688 mParallelBroadcasts.add(r);
9689 }
9690 }
9691
9692 return sticky;
9693 }
9694 }
9695
9696 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009697 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698
9699 boolean doNext = false;
9700
9701 synchronized(this) {
9702 ReceiverList rl
9703 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9704 if (rl != null) {
9705 if (rl.curBroadcast != null) {
9706 BroadcastRecord r = rl.curBroadcast;
9707 doNext = finishReceiverLocked(
9708 receiver.asBinder(), r.resultCode, r.resultData,
9709 r.resultExtras, r.resultAbort, true);
9710 }
9711
9712 if (rl.app != null) {
9713 rl.app.receivers.remove(rl);
9714 }
9715 removeReceiverLocked(rl);
9716 if (rl.linkedToDeath) {
9717 rl.linkedToDeath = false;
9718 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9719 }
9720 }
9721 }
9722
9723 if (!doNext) {
9724 return;
9725 }
9726
9727 final long origId = Binder.clearCallingIdentity();
9728 processNextBroadcast(false);
9729 trimApplications();
9730 Binder.restoreCallingIdentity(origId);
9731 }
9732
9733 void removeReceiverLocked(ReceiverList rl) {
9734 mRegisteredReceivers.remove(rl.receiver.asBinder());
9735 int N = rl.size();
9736 for (int i=0; i<N; i++) {
9737 mReceiverResolver.removeFilter(rl.get(i));
9738 }
9739 }
9740
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009741 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9742 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9743 ProcessRecord r = mLruProcesses.get(i);
9744 if (r.thread != null) {
9745 try {
9746 r.thread.dispatchPackageBroadcast(cmd, packages);
9747 } catch (RemoteException ex) {
9748 }
9749 }
9750 }
9751 }
9752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753 private final int broadcastIntentLocked(ProcessRecord callerApp,
9754 String callerPackage, Intent intent, String resolvedType,
9755 IIntentReceiver resultTo, int resultCode, String resultData,
9756 Bundle map, String requiredPermission,
9757 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9758 intent = new Intent(intent);
9759
Joe Onorato8a9b2202010-02-26 18:56:32 -08009760 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009761 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9762 + " ordered=" + ordered);
9763 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009764 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765 }
9766
9767 // Handle special intents: if this broadcast is from the package
9768 // manager about a package being removed, we need to remove all of
9769 // its activities from the history stack.
9770 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9771 intent.getAction());
9772 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9773 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009774 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 || uidRemoved) {
9776 if (checkComponentPermission(
9777 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9778 callingPid, callingUid, -1)
9779 == PackageManager.PERMISSION_GRANTED) {
9780 if (uidRemoved) {
9781 final Bundle intentExtras = intent.getExtras();
9782 final int uid = intentExtras != null
9783 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9784 if (uid >= 0) {
9785 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9786 synchronized (bs) {
9787 bs.removeUidStatsLocked(uid);
9788 }
9789 }
9790 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009791 // If resources are unvailble just force stop all
9792 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009793 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009794 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9795 if (list != null && (list.length > 0)) {
9796 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009797 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009798 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009799 sendPackageBroadcastLocked(
9800 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009801 }
9802 } else {
9803 Uri data = intent.getData();
9804 String ssp;
9805 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9806 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9807 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009808 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009809 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009810 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9811 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9812 new String[] {ssp});
9813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009814 }
9815 }
9816 }
9817 } else {
9818 String msg = "Permission Denial: " + intent.getAction()
9819 + " broadcast from " + callerPackage + " (pid=" + callingPid
9820 + ", uid=" + callingUid + ")"
9821 + " requires "
9822 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009823 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 throw new SecurityException(msg);
9825 }
9826 }
9827
9828 /*
9829 * If this is the time zone changed action, queue up a message that will reset the timezone
9830 * of all currently running processes. This message will get queued up before the broadcast
9831 * happens.
9832 */
9833 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9834 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9835 }
9836
Dianne Hackborn854060af2009-07-09 18:14:31 -07009837 /*
9838 * Prevent non-system code (defined here to be non-persistent
9839 * processes) from sending protected broadcasts.
9840 */
9841 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9842 || callingUid == Process.SHELL_UID || callingUid == 0) {
9843 // Always okay.
9844 } else if (callerApp == null || !callerApp.persistent) {
9845 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009846 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009847 intent.getAction())) {
9848 String msg = "Permission Denial: not allowed to send broadcast "
9849 + intent.getAction() + " from pid="
9850 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009851 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009852 throw new SecurityException(msg);
9853 }
9854 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009855 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009856 return BROADCAST_SUCCESS;
9857 }
9858 }
9859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860 // Add to the sticky list if requested.
9861 if (sticky) {
9862 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9863 callingPid, callingUid)
9864 != PackageManager.PERMISSION_GRANTED) {
9865 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9866 + callingPid + ", uid=" + callingUid
9867 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009868 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009869 throw new SecurityException(msg);
9870 }
9871 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009872 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009873 + " and enforce permission " + requiredPermission);
9874 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9875 }
9876 if (intent.getComponent() != null) {
9877 throw new SecurityException(
9878 "Sticky broadcasts can't target a specific component");
9879 }
9880 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9881 if (list == null) {
9882 list = new ArrayList<Intent>();
9883 mStickyBroadcasts.put(intent.getAction(), list);
9884 }
9885 int N = list.size();
9886 int i;
9887 for (i=0; i<N; i++) {
9888 if (intent.filterEquals(list.get(i))) {
9889 // This sticky already exists, replace it.
9890 list.set(i, new Intent(intent));
9891 break;
9892 }
9893 }
9894 if (i >= N) {
9895 list.add(new Intent(intent));
9896 }
9897 }
9898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009899 // Figure out who all will receive this broadcast.
9900 List receivers = null;
9901 List<BroadcastFilter> registeredReceivers = null;
9902 try {
9903 if (intent.getComponent() != null) {
9904 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009905 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009906 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009907 if (ai != null) {
9908 receivers = new ArrayList();
9909 ResolveInfo ri = new ResolveInfo();
9910 ri.activityInfo = ai;
9911 receivers.add(ri);
9912 }
9913 } else {
9914 // Need to resolve the intent to interested receivers...
9915 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9916 == 0) {
9917 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009918 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009919 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009920 }
Mihai Preda074edef2009-05-18 17:13:31 +02009921 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 }
9923 } catch (RemoteException ex) {
9924 // pm is in same process, this will never happen.
9925 }
9926
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009927 final boolean replacePending =
9928 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9929
Joe Onorato8a9b2202010-02-26 18:56:32 -08009930 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009931 + " replacePending=" + replacePending);
9932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009933 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9934 if (!ordered && NR > 0) {
9935 // If we are not serializing this broadcast, then send the
9936 // registered receivers separately so they don't wait for the
9937 // components to be launched.
9938 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9939 callerPackage, callingPid, callingUid, requiredPermission,
9940 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009941 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009942 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 TAG, "Enqueueing parallel broadcast " + r
9944 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009945 boolean replaced = false;
9946 if (replacePending) {
9947 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9948 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009949 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009950 "***** DROPPING PARALLEL: " + intent);
9951 mParallelBroadcasts.set(i, r);
9952 replaced = true;
9953 break;
9954 }
9955 }
9956 }
9957 if (!replaced) {
9958 mParallelBroadcasts.add(r);
9959 scheduleBroadcastsLocked();
9960 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009961 registeredReceivers = null;
9962 NR = 0;
9963 }
9964
9965 // Merge into one list.
9966 int ir = 0;
9967 if (receivers != null) {
9968 // A special case for PACKAGE_ADDED: do not allow the package
9969 // being added to see this broadcast. This prevents them from
9970 // using this as a back door to get run as soon as they are
9971 // installed. Maybe in the future we want to have a special install
9972 // broadcast or such for apps, but we'd like to deliberately make
9973 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009974 String skipPackages[] = null;
9975 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9976 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9977 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9978 Uri data = intent.getData();
9979 if (data != null) {
9980 String pkgName = data.getSchemeSpecificPart();
9981 if (pkgName != null) {
9982 skipPackages = new String[] { pkgName };
9983 }
9984 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009985 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009986 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009987 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009988 if (skipPackages != null && (skipPackages.length > 0)) {
9989 for (String skipPackage : skipPackages) {
9990 if (skipPackage != null) {
9991 int NT = receivers.size();
9992 for (int it=0; it<NT; it++) {
9993 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9994 if (curt.activityInfo.packageName.equals(skipPackage)) {
9995 receivers.remove(it);
9996 it--;
9997 NT--;
9998 }
9999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 }
10001 }
10002 }
10003
10004 int NT = receivers != null ? receivers.size() : 0;
10005 int it = 0;
10006 ResolveInfo curt = null;
10007 BroadcastFilter curr = null;
10008 while (it < NT && ir < NR) {
10009 if (curt == null) {
10010 curt = (ResolveInfo)receivers.get(it);
10011 }
10012 if (curr == null) {
10013 curr = registeredReceivers.get(ir);
10014 }
10015 if (curr.getPriority() >= curt.priority) {
10016 // Insert this broadcast record into the final list.
10017 receivers.add(it, curr);
10018 ir++;
10019 curr = null;
10020 it++;
10021 NT++;
10022 } else {
10023 // Skip to the next ResolveInfo in the final list.
10024 it++;
10025 curt = null;
10026 }
10027 }
10028 }
10029 while (ir < NR) {
10030 if (receivers == null) {
10031 receivers = new ArrayList();
10032 }
10033 receivers.add(registeredReceivers.get(ir));
10034 ir++;
10035 }
10036
10037 if ((receivers != null && receivers.size() > 0)
10038 || resultTo != null) {
10039 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10040 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010041 receivers, resultTo, resultCode, resultData, map, ordered,
10042 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010043 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010044 TAG, "Enqueueing ordered broadcast " + r
10045 + ": prev had " + mOrderedBroadcasts.size());
10046 if (DEBUG_BROADCAST) {
10047 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010048 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010049 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010050 boolean replaced = false;
10051 if (replacePending) {
10052 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10053 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010054 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010055 "***** DROPPING ORDERED: " + intent);
10056 mOrderedBroadcasts.set(i, r);
10057 replaced = true;
10058 break;
10059 }
10060 }
10061 }
10062 if (!replaced) {
10063 mOrderedBroadcasts.add(r);
10064 scheduleBroadcastsLocked();
10065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 }
10067
10068 return BROADCAST_SUCCESS;
10069 }
10070
10071 public final int broadcastIntent(IApplicationThread caller,
10072 Intent intent, String resolvedType, IIntentReceiver resultTo,
10073 int resultCode, String resultData, Bundle map,
10074 String requiredPermission, boolean serialized, boolean sticky) {
10075 // Refuse possible leaked file descriptors
10076 if (intent != null && intent.hasFileDescriptors() == true) {
10077 throw new IllegalArgumentException("File descriptors passed in Intent");
10078 }
10079
10080 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010081 int flags = intent.getFlags();
10082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010083 if (!mSystemReady) {
10084 // if the caller really truly claims to know what they're doing, go
10085 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010086 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10087 intent = new Intent(intent);
10088 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10089 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080010090 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010091 + " before boot completion");
10092 throw new IllegalStateException("Cannot broadcast before boot completed");
10093 }
10094 }
10095
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010096 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10097 throw new IllegalArgumentException(
10098 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10099 }
10100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010101 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10102 final int callingPid = Binder.getCallingPid();
10103 final int callingUid = Binder.getCallingUid();
10104 final long origId = Binder.clearCallingIdentity();
10105 int res = broadcastIntentLocked(callerApp,
10106 callerApp != null ? callerApp.info.packageName : null,
10107 intent, resolvedType, resultTo,
10108 resultCode, resultData, map, requiredPermission, serialized,
10109 sticky, callingPid, callingUid);
10110 Binder.restoreCallingIdentity(origId);
10111 return res;
10112 }
10113 }
10114
10115 int broadcastIntentInPackage(String packageName, int uid,
10116 Intent intent, String resolvedType, IIntentReceiver resultTo,
10117 int resultCode, String resultData, Bundle map,
10118 String requiredPermission, boolean serialized, boolean sticky) {
10119 synchronized(this) {
10120 final long origId = Binder.clearCallingIdentity();
10121 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10122 resultTo, resultCode, resultData, map, requiredPermission,
10123 serialized, sticky, -1, uid);
10124 Binder.restoreCallingIdentity(origId);
10125 return res;
10126 }
10127 }
10128
10129 public final void unbroadcastIntent(IApplicationThread caller,
10130 Intent intent) {
10131 // Refuse possible leaked file descriptors
10132 if (intent != null && intent.hasFileDescriptors() == true) {
10133 throw new IllegalArgumentException("File descriptors passed in Intent");
10134 }
10135
10136 synchronized(this) {
10137 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10138 != PackageManager.PERMISSION_GRANTED) {
10139 String msg = "Permission Denial: unbroadcastIntent() from pid="
10140 + Binder.getCallingPid()
10141 + ", uid=" + Binder.getCallingUid()
10142 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010143 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010144 throw new SecurityException(msg);
10145 }
10146 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10147 if (list != null) {
10148 int N = list.size();
10149 int i;
10150 for (i=0; i<N; i++) {
10151 if (intent.filterEquals(list.get(i))) {
10152 list.remove(i);
10153 break;
10154 }
10155 }
10156 }
10157 }
10158 }
10159
10160 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10161 String resultData, Bundle resultExtras, boolean resultAbort,
10162 boolean explicit) {
10163 if (mOrderedBroadcasts.size() == 0) {
10164 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010165 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010166 }
10167 return false;
10168 }
10169 BroadcastRecord r = mOrderedBroadcasts.get(0);
10170 if (r.receiver == null) {
10171 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010172 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010173 }
10174 return false;
10175 }
10176 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010177 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178 return false;
10179 }
10180 int state = r.state;
10181 r.state = r.IDLE;
10182 if (state == r.IDLE) {
10183 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010184 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010185 }
10186 }
10187 r.receiver = null;
10188 r.intent.setComponent(null);
10189 if (r.curApp != null) {
10190 r.curApp.curReceiver = null;
10191 }
10192 if (r.curFilter != null) {
10193 r.curFilter.receiverList.curBroadcast = null;
10194 }
10195 r.curFilter = null;
10196 r.curApp = null;
10197 r.curComponent = null;
10198 r.curReceiver = null;
10199 mPendingBroadcast = null;
10200
10201 r.resultCode = resultCode;
10202 r.resultData = resultData;
10203 r.resultExtras = resultExtras;
10204 r.resultAbort = resultAbort;
10205
10206 // We will process the next receiver right now if this is finishing
10207 // an app receiver (which is always asynchronous) or after we have
10208 // come back from calling a receiver.
10209 return state == BroadcastRecord.APP_RECEIVE
10210 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10211 }
10212
10213 public void finishReceiver(IBinder who, int resultCode, String resultData,
10214 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010215 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010216
10217 // Refuse possible leaked file descriptors
10218 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10219 throw new IllegalArgumentException("File descriptors passed in Bundle");
10220 }
10221
10222 boolean doNext;
10223
10224 final long origId = Binder.clearCallingIdentity();
10225
10226 synchronized(this) {
10227 doNext = finishReceiverLocked(
10228 who, resultCode, resultData, resultExtras, resultAbort, true);
10229 }
10230
10231 if (doNext) {
10232 processNextBroadcast(false);
10233 }
10234 trimApplications();
10235
10236 Binder.restoreCallingIdentity(origId);
10237 }
10238
10239 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10240 if (r.nextReceiver > 0) {
10241 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10242 if (curReceiver instanceof BroadcastFilter) {
10243 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010244 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010245 System.identityHashCode(r),
10246 r.intent.getAction(),
10247 r.nextReceiver - 1,
10248 System.identityHashCode(bf));
10249 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010250 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 System.identityHashCode(r),
10252 r.intent.getAction(),
10253 r.nextReceiver - 1,
10254 ((ResolveInfo)curReceiver).toString());
10255 }
10256 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010257 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010258 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010259 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010260 System.identityHashCode(r),
10261 r.intent.getAction(),
10262 r.nextReceiver,
10263 "NONE");
10264 }
10265 }
10266
10267 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010268 ProcessRecord app = null;
10269 String anrMessage = null;
10270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010271 synchronized (this) {
10272 if (mOrderedBroadcasts.size() == 0) {
10273 return;
10274 }
10275 long now = SystemClock.uptimeMillis();
10276 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010277 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010278 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010279 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010280 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010282 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010283 return;
10284 }
10285
Joe Onorato8a9b2202010-02-26 18:56:32 -080010286 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010287 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010288 r.anrCount++;
10289
10290 // Current receiver has passed its expiration date.
10291 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010292 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010293 return;
10294 }
10295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010297 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010298 logBroadcastReceiverDiscard(r);
10299 if (curReceiver instanceof BroadcastFilter) {
10300 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10301 if (bf.receiverList.pid != 0
10302 && bf.receiverList.pid != MY_PID) {
10303 synchronized (this.mPidsSelfLocked) {
10304 app = this.mPidsSelfLocked.get(
10305 bf.receiverList.pid);
10306 }
10307 }
10308 } else {
10309 app = r.curApp;
10310 }
10311
10312 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010313 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 }
10315
10316 if (mPendingBroadcast == r) {
10317 mPendingBroadcast = null;
10318 }
10319
10320 // Move on to the next receiver.
10321 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10322 r.resultExtras, r.resultAbort, true);
10323 scheduleBroadcastsLocked();
10324 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010325
10326 if (anrMessage != null) {
10327 appNotResponding(app, null, null, anrMessage);
10328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 }
10330
10331 private final void processCurBroadcastLocked(BroadcastRecord r,
10332 ProcessRecord app) throws RemoteException {
10333 if (app.thread == null) {
10334 throw new RemoteException();
10335 }
10336 r.receiver = app.thread.asBinder();
10337 r.curApp = app;
10338 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010339 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340
10341 // Tell the application to launch this receiver.
10342 r.intent.setComponent(r.curComponent);
10343
10344 boolean started = false;
10345 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010346 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010347 "Delivering to component " + r.curComponent
10348 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010349 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010350 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10351 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10352 started = true;
10353 } finally {
10354 if (!started) {
10355 r.receiver = null;
10356 r.curApp = null;
10357 app.curReceiver = null;
10358 }
10359 }
10360
10361 }
10362
10363 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010364 Intent intent, int resultCode, String data, Bundle extras,
10365 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010366 if (app != null && app.thread != null) {
10367 // If we have an app thread, do the call through that so it is
10368 // correctly ordered with other one-way calls.
10369 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010370 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010372 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 }
10374 }
10375
10376 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10377 BroadcastFilter filter, boolean ordered) {
10378 boolean skip = false;
10379 if (filter.requiredPermission != null) {
10380 int perm = checkComponentPermission(filter.requiredPermission,
10381 r.callingPid, r.callingUid, -1);
10382 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010383 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010384 + r.intent.toString()
10385 + " from " + r.callerPackage + " (pid="
10386 + r.callingPid + ", uid=" + r.callingUid + ")"
10387 + " requires " + filter.requiredPermission
10388 + " due to registered receiver " + filter);
10389 skip = true;
10390 }
10391 }
10392 if (r.requiredPermission != null) {
10393 int perm = checkComponentPermission(r.requiredPermission,
10394 filter.receiverList.pid, filter.receiverList.uid, -1);
10395 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010396 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010397 + r.intent.toString()
10398 + " to " + filter.receiverList.app
10399 + " (pid=" + filter.receiverList.pid
10400 + ", uid=" + filter.receiverList.uid + ")"
10401 + " requires " + r.requiredPermission
10402 + " due to sender " + r.callerPackage
10403 + " (uid " + r.callingUid + ")");
10404 skip = true;
10405 }
10406 }
10407
10408 if (!skip) {
10409 // If this is not being sent as an ordered broadcast, then we
10410 // don't want to touch the fields that keep track of the current
10411 // state of ordered broadcasts.
10412 if (ordered) {
10413 r.receiver = filter.receiverList.receiver.asBinder();
10414 r.curFilter = filter;
10415 filter.receiverList.curBroadcast = r;
10416 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010417 if (filter.receiverList.app != null) {
10418 // Bump hosting application to no longer be in background
10419 // scheduling class. Note that we can't do that if there
10420 // isn't an app... but we can only be in that case for
10421 // things that directly call the IActivityManager API, which
10422 // are already core system stuff so don't matter for this.
10423 r.curApp = filter.receiverList.app;
10424 filter.receiverList.app.curReceiver = r;
10425 updateOomAdjLocked();
10426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 }
10428 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010429 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010431 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010432 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010433 }
10434 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10435 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010436 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010437 if (ordered) {
10438 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10439 }
10440 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010441 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010442 if (ordered) {
10443 r.receiver = null;
10444 r.curFilter = null;
10445 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010446 if (filter.receiverList.app != null) {
10447 filter.receiverList.app.curReceiver = null;
10448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010449 }
10450 }
10451 }
10452 }
10453
Dianne Hackborn12527f92009-11-11 17:39:50 -080010454 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10455 if (r.callingUid < 0) {
10456 // This was from a registerReceiver() call; ignore it.
10457 return;
10458 }
10459 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10460 MAX_BROADCAST_HISTORY-1);
10461 r.finishTime = SystemClock.uptimeMillis();
10462 mBroadcastHistory[0] = r;
10463 }
10464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010465 private final void processNextBroadcast(boolean fromMsg) {
10466 synchronized(this) {
10467 BroadcastRecord r;
10468
Joe Onorato8a9b2202010-02-26 18:56:32 -080010469 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010470 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010471 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010472
10473 updateCpuStats();
10474
10475 if (fromMsg) {
10476 mBroadcastsScheduled = false;
10477 }
10478
10479 // First, deliver any non-serialized broadcasts right away.
10480 while (mParallelBroadcasts.size() > 0) {
10481 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010482 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010483 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010484 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010485 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010486 for (int i=0; i<N; i++) {
10487 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010488 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010489 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 + target + ": " + r);
10491 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10492 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010493 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010494 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010495 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010496 }
10497
10498 // Now take care of the next serialized one...
10499
10500 // If we are waiting for a process to come up to handle the next
10501 // broadcast, then do nothing at this point. Just in case, we
10502 // check that the process we're waiting for still exists.
10503 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010504 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010505 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010506 + mPendingBroadcast.curApp);
10507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010508
10509 boolean isDead;
10510 synchronized (mPidsSelfLocked) {
10511 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10512 }
10513 if (!isDead) {
10514 // It's still alive, so keep waiting
10515 return;
10516 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010517 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518 + " died before responding to broadcast");
10519 mPendingBroadcast = null;
10520 }
10521 }
10522
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010523 boolean looped = false;
10524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010525 do {
10526 if (mOrderedBroadcasts.size() == 0) {
10527 // No more broadcasts pending, so all done!
10528 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010529 if (looped) {
10530 // If we had finished the last ordered broadcast, then
10531 // make sure all processes have correct oom and sched
10532 // adjustments.
10533 updateOomAdjLocked();
10534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010535 return;
10536 }
10537 r = mOrderedBroadcasts.get(0);
10538 boolean forceReceive = false;
10539
10540 // Ensure that even if something goes awry with the timeout
10541 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010542 // and continue to make progress.
10543 //
10544 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10545 // receivers don't get executed with with timeouts. They're intended for
10546 // one time heavy lifting after system upgrades and can take
10547 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010549 if (mSystemReady && r.dispatchTime > 0) {
10550 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010551 if ((numReceivers > 0) &&
10552 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010553 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010554 + " now=" + now
10555 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010556 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010557 + " intent=" + r.intent
10558 + " numReceivers=" + numReceivers
10559 + " nextReceiver=" + r.nextReceiver
10560 + " state=" + r.state);
10561 broadcastTimeout(); // forcibly finish this broadcast
10562 forceReceive = true;
10563 r.state = BroadcastRecord.IDLE;
10564 }
10565 }
10566
10567 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010568 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010569 "processNextBroadcast() called when not idle (state="
10570 + r.state + ")");
10571 return;
10572 }
10573
10574 if (r.receivers == null || r.nextReceiver >= numReceivers
10575 || r.resultAbort || forceReceive) {
10576 // No more receivers for this broadcast! Send the final
10577 // result if requested...
10578 if (r.resultTo != null) {
10579 try {
10580 if (DEBUG_BROADCAST) {
10581 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010582 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 + " seq=" + seq + " app=" + r.callerApp);
10584 }
10585 performReceive(r.callerApp, r.resultTo,
10586 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010587 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010589 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010590 }
10591 }
10592
Joe Onorato8a9b2202010-02-26 18:56:32 -080010593 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010594 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10595
Joe Onorato8a9b2202010-02-26 18:56:32 -080010596 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010597 + r);
10598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010599 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010600 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010601 mOrderedBroadcasts.remove(0);
10602 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010603 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010604 continue;
10605 }
10606 } while (r == null);
10607
10608 // Get the next receiver...
10609 int recIdx = r.nextReceiver++;
10610
10611 // Keep track of when this receiver started, and make sure there
10612 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010613 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010615 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010616
Joe Onorato8a9b2202010-02-26 18:56:32 -080010617 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010618 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010619 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010621 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010622 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010623 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010624 }
10625
10626 Object nextReceiver = r.receivers.get(recIdx);
10627 if (nextReceiver instanceof BroadcastFilter) {
10628 // Simple case: this is a registered receiver who gets
10629 // a direct call.
10630 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010631 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010632 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010633 + filter + ": " + r);
10634 deliverToRegisteredReceiver(r, filter, r.ordered);
10635 if (r.receiver == null || !r.ordered) {
10636 // The receiver has already finished, so schedule to
10637 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010638 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10639 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 r.state = BroadcastRecord.IDLE;
10641 scheduleBroadcastsLocked();
10642 }
10643 return;
10644 }
10645
10646 // Hard case: need to instantiate the receiver, possibly
10647 // starting its application process to host it.
10648
10649 ResolveInfo info =
10650 (ResolveInfo)nextReceiver;
10651
10652 boolean skip = false;
10653 int perm = checkComponentPermission(info.activityInfo.permission,
10654 r.callingPid, r.callingUid,
10655 info.activityInfo.exported
10656 ? -1 : info.activityInfo.applicationInfo.uid);
10657 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010658 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010659 + r.intent.toString()
10660 + " from " + r.callerPackage + " (pid=" + r.callingPid
10661 + ", uid=" + r.callingUid + ")"
10662 + " requires " + info.activityInfo.permission
10663 + " due to receiver " + info.activityInfo.packageName
10664 + "/" + info.activityInfo.name);
10665 skip = true;
10666 }
10667 if (r.callingUid != Process.SYSTEM_UID &&
10668 r.requiredPermission != null) {
10669 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010670 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010671 checkPermission(r.requiredPermission,
10672 info.activityInfo.applicationInfo.packageName);
10673 } catch (RemoteException e) {
10674 perm = PackageManager.PERMISSION_DENIED;
10675 }
10676 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010677 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010678 + r.intent + " to "
10679 + info.activityInfo.applicationInfo.packageName
10680 + " requires " + r.requiredPermission
10681 + " due to sender " + r.callerPackage
10682 + " (uid " + r.callingUid + ")");
10683 skip = true;
10684 }
10685 }
10686 if (r.curApp != null && r.curApp.crashing) {
10687 // If the target process is crashing, just skip it.
10688 skip = true;
10689 }
10690
10691 if (skip) {
10692 r.receiver = null;
10693 r.curFilter = null;
10694 r.state = BroadcastRecord.IDLE;
10695 scheduleBroadcastsLocked();
10696 return;
10697 }
10698
10699 r.state = BroadcastRecord.APP_RECEIVE;
10700 String targetProcess = info.activityInfo.processName;
10701 r.curComponent = new ComponentName(
10702 info.activityInfo.applicationInfo.packageName,
10703 info.activityInfo.name);
10704 r.curReceiver = info.activityInfo;
10705
10706 // Is this receiver's application already running?
10707 ProcessRecord app = getProcessRecordLocked(targetProcess,
10708 info.activityInfo.applicationInfo.uid);
10709 if (app != null && app.thread != null) {
10710 try {
10711 processCurBroadcastLocked(r, app);
10712 return;
10713 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010714 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010715 + r.curComponent, e);
10716 }
10717
10718 // If a dead object exception was thrown -- fall through to
10719 // restart the application.
10720 }
10721
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010722 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010723 if ((r.curApp=startProcessLocked(targetProcess,
10724 info.activityInfo.applicationInfo, true,
10725 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010726 "broadcast", r.curComponent,
10727 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10728 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010729 // Ah, this recipient is unavailable. Finish it if necessary,
10730 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010731 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 + info.activityInfo.applicationInfo.packageName + "/"
10733 + info.activityInfo.applicationInfo.uid + " for broadcast "
10734 + r.intent + ": process is bad");
10735 logBroadcastReceiverDiscard(r);
10736 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10737 r.resultExtras, r.resultAbort, true);
10738 scheduleBroadcastsLocked();
10739 r.state = BroadcastRecord.IDLE;
10740 return;
10741 }
10742
10743 mPendingBroadcast = r;
10744 }
10745 }
10746
10747 // =========================================================
10748 // INSTRUMENTATION
10749 // =========================================================
10750
10751 public boolean startInstrumentation(ComponentName className,
10752 String profileFile, int flags, Bundle arguments,
10753 IInstrumentationWatcher watcher) {
10754 // Refuse possible leaked file descriptors
10755 if (arguments != null && arguments.hasFileDescriptors()) {
10756 throw new IllegalArgumentException("File descriptors passed in Bundle");
10757 }
10758
10759 synchronized(this) {
10760 InstrumentationInfo ii = null;
10761 ApplicationInfo ai = null;
10762 try {
10763 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010764 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010766 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010767 } catch (PackageManager.NameNotFoundException e) {
10768 }
10769 if (ii == null) {
10770 reportStartInstrumentationFailure(watcher, className,
10771 "Unable to find instrumentation info for: " + className);
10772 return false;
10773 }
10774 if (ai == null) {
10775 reportStartInstrumentationFailure(watcher, className,
10776 "Unable to find instrumentation target package: " + ii.targetPackage);
10777 return false;
10778 }
10779
10780 int match = mContext.getPackageManager().checkSignatures(
10781 ii.targetPackage, ii.packageName);
10782 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10783 String msg = "Permission Denial: starting instrumentation "
10784 + className + " from pid="
10785 + Binder.getCallingPid()
10786 + ", uid=" + Binder.getCallingPid()
10787 + " not allowed because package " + ii.packageName
10788 + " does not have a signature matching the target "
10789 + ii.targetPackage;
10790 reportStartInstrumentationFailure(watcher, className, msg);
10791 throw new SecurityException(msg);
10792 }
10793
10794 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010795 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010796 ProcessRecord app = addAppLocked(ai);
10797 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010798 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 app.instrumentationProfileFile = profileFile;
10800 app.instrumentationArguments = arguments;
10801 app.instrumentationWatcher = watcher;
10802 app.instrumentationResultClass = className;
10803 Binder.restoreCallingIdentity(origId);
10804 }
10805
10806 return true;
10807 }
10808
10809 /**
10810 * Report errors that occur while attempting to start Instrumentation. Always writes the
10811 * error to the logs, but if somebody is watching, send the report there too. This enables
10812 * the "am" command to report errors with more information.
10813 *
10814 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10815 * @param cn The component name of the instrumentation.
10816 * @param report The error report.
10817 */
10818 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10819 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010820 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010821 try {
10822 if (watcher != null) {
10823 Bundle results = new Bundle();
10824 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10825 results.putString("Error", report);
10826 watcher.instrumentationStatus(cn, -1, results);
10827 }
10828 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010829 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 }
10831 }
10832
10833 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10834 if (app.instrumentationWatcher != null) {
10835 try {
10836 // NOTE: IInstrumentationWatcher *must* be oneway here
10837 app.instrumentationWatcher.instrumentationFinished(
10838 app.instrumentationClass,
10839 resultCode,
10840 results);
10841 } catch (RemoteException e) {
10842 }
10843 }
10844 app.instrumentationWatcher = null;
10845 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010846 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010847 app.instrumentationProfileFile = null;
10848 app.instrumentationArguments = null;
10849
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010850 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010851 }
10852
10853 public void finishInstrumentation(IApplicationThread target,
10854 int resultCode, Bundle results) {
10855 // Refuse possible leaked file descriptors
10856 if (results != null && results.hasFileDescriptors()) {
10857 throw new IllegalArgumentException("File descriptors passed in Intent");
10858 }
10859
10860 synchronized(this) {
10861 ProcessRecord app = getRecordForAppLocked(target);
10862 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010863 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 return;
10865 }
10866 final long origId = Binder.clearCallingIdentity();
10867 finishInstrumentationLocked(app, resultCode, results);
10868 Binder.restoreCallingIdentity(origId);
10869 }
10870 }
10871
10872 // =========================================================
10873 // CONFIGURATION
10874 // =========================================================
10875
10876 public ConfigurationInfo getDeviceConfigurationInfo() {
10877 ConfigurationInfo config = new ConfigurationInfo();
10878 synchronized (this) {
10879 config.reqTouchScreen = mConfiguration.touchscreen;
10880 config.reqKeyboardType = mConfiguration.keyboard;
10881 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010882 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10883 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010884 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10885 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010886 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10887 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010888 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10889 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010890 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 }
10892 return config;
10893 }
10894
10895 public Configuration getConfiguration() {
10896 Configuration ci;
10897 synchronized(this) {
10898 ci = new Configuration(mConfiguration);
10899 }
10900 return ci;
10901 }
10902
10903 public void updateConfiguration(Configuration values) {
10904 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10905 "updateConfiguration()");
10906
10907 synchronized(this) {
10908 if (values == null && mWindowManager != null) {
10909 // sentinel: fetch the current configuration from the window manager
10910 values = mWindowManager.computeNewConfiguration();
10911 }
10912
10913 final long origId = Binder.clearCallingIdentity();
10914 updateConfigurationLocked(values, null);
10915 Binder.restoreCallingIdentity(origId);
10916 }
10917 }
10918
10919 /**
10920 * Do either or both things: (1) change the current configuration, and (2)
10921 * make sure the given activity is running with the (now) current
10922 * configuration. Returns true if the activity has been left running, or
10923 * false if <var>starting</var> is being destroyed to match the new
10924 * configuration.
10925 */
10926 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010927 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928 int changes = 0;
10929
10930 boolean kept = true;
10931
10932 if (values != null) {
10933 Configuration newConfig = new Configuration(mConfiguration);
10934 changes = newConfig.updateFrom(values);
10935 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010936 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010937 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 }
10939
Doug Zongker2bec3d42009-12-04 12:52:44 -080010940 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941
10942 if (values.locale != null) {
10943 saveLocaleLocked(values.locale,
10944 !values.locale.equals(mConfiguration.locale),
10945 values.userSetLocale);
10946 }
10947
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010948 mConfigurationSeq++;
10949 if (mConfigurationSeq <= 0) {
10950 mConfigurationSeq = 1;
10951 }
10952 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010953 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010954 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010955
10956 AttributeCache ac = AttributeCache.instance();
10957 if (ac != null) {
10958 ac.updateConfiguration(mConfiguration);
10959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010961 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10962 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10963 msg.obj = new Configuration(mConfiguration);
10964 mHandler.sendMessage(msg);
10965 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010967 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10968 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 try {
10970 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010971 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010972 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973 app.thread.scheduleConfigurationChanged(mConfiguration);
10974 }
10975 } catch (Exception e) {
10976 }
10977 }
10978 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010979 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10980 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010981 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10982 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010983 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10984 broadcastIntentLocked(null, null,
10985 new Intent(Intent.ACTION_LOCALE_CHANGED),
10986 null, null, 0, null, null,
10987 null, false, false, MY_PID, Process.SYSTEM_UID);
10988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 }
10990 }
10991
10992 if (changes != 0 && starting == null) {
10993 // If the configuration changed, and the caller is not already
10994 // in the process of starting an activity, then find the top
10995 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010996 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 }
10998
10999 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011000 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 if (kept) {
11002 // If this didn't result in the starting activity being
11003 // destroyed, then we need to make sure at this point that all
11004 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011005 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011006 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011007 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 }
11009 }
11010
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011011 if (values != null && mWindowManager != null) {
11012 mWindowManager.setNewConfiguration(mConfiguration);
11013 }
11014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011015 return kept;
11016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017
11018 /**
11019 * Save the locale. You must be inside a synchronized (this) block.
11020 */
11021 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11022 if(isDiff) {
11023 SystemProperties.set("user.language", l.getLanguage());
11024 SystemProperties.set("user.region", l.getCountry());
11025 }
11026
11027 if(isPersist) {
11028 SystemProperties.set("persist.sys.language", l.getLanguage());
11029 SystemProperties.set("persist.sys.country", l.getCountry());
11030 SystemProperties.set("persist.sys.localevar", l.getVariant());
11031 }
11032 }
11033
11034 // =========================================================
11035 // LIFETIME MANAGEMENT
11036 // =========================================================
11037
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011038 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11039 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011041 // This adjustment has already been computed. If we are calling
11042 // from the top, we may have already computed our adjustment with
11043 // an earlier hidden adjustment that isn't really for us... if
11044 // so, use the new hidden adjustment.
11045 if (!recursed && app.hidden) {
11046 app.curAdj = hiddenAdj;
11047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011048 return app.curAdj;
11049 }
11050
11051 if (app.thread == null) {
11052 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011053 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 return (app.curAdj=EMPTY_APP_ADJ);
11055 }
11056
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011057 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11058 // The max adjustment doesn't allow this app to be anything
11059 // below foreground, so it is not worth doing work for it.
11060 app.adjType = "fixed";
11061 app.adjSeq = mAdjSeq;
11062 app.curRawAdj = app.maxAdj;
11063 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11064 return (app.curAdj=app.maxAdj);
11065 }
11066
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011067 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011068 app.adjSource = null;
11069 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011070 app.empty = false;
11071 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072
The Android Open Source Project4df24232009-03-05 14:34:35 -080011073 // Determine the importance of the process, starting with most
11074 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011076 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011078 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 // The last app on the list is the foreground app.
11080 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011081 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011082 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011083 } else if (app.instrumentationClass != null) {
11084 // Don't want to kill running instrumentation.
11085 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011086 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011087 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011088 } else if (app.persistentActivities > 0) {
11089 // Special persistent activities... shouldn't be used these days.
11090 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011091 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011092 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011093 } else if (app.curReceiver != null ||
11094 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11095 // An app that is currently receiving a broadcast also
11096 // counts as being in the foreground.
11097 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011098 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011099 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011100 } else if (app.executingServices.size() > 0) {
11101 // An app that is currently executing a service callback also
11102 // counts as being in the foreground.
11103 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011104 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011105 app.adjType = "exec-service";
11106 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011107 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011108 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011109 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011110 app.adjType = "foreground-service";
11111 } else if (app.forcingToForeground != null) {
11112 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011113 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011114 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011115 app.adjType = "force-foreground";
11116 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011117 } else if (app == mHeavyWeightProcess) {
11118 // We don't want to kill the current heavy-weight process.
11119 adj = HEAVY_WEIGHT_APP_ADJ;
11120 schedGroup = Process.THREAD_GROUP_DEFAULT;
11121 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011122 } else if (app == mHomeProcess) {
11123 // This process is hosting what we currently consider to be the
11124 // home app, so we don't want to let it go into the background.
11125 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011126 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011127 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 } else if ((N=app.activities.size()) != 0) {
11129 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011130 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011131 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011132 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011133 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011134 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011135 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011136 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011138 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011139 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011140 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011141 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 break;
11143 }
11144 }
11145 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011146 // A very not-needed process. If this is lower in the lru list,
11147 // we will push it in to the empty bucket.
11148 app.hidden = true;
11149 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011150 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011151 adj = hiddenAdj;
11152 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011153 }
11154
Joe Onorato8a9b2202010-02-26 18:56:32 -080011155 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011156
The Android Open Source Project4df24232009-03-05 14:34:35 -080011157 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011158 // there are applications dependent on our services or providers, but
11159 // this gives us a baseline and makes sure we don't get into an
11160 // infinite recursion.
11161 app.adjSeq = mAdjSeq;
11162 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011163
Christopher Tate6fa95972009-06-05 18:43:55 -070011164 if (mBackupTarget != null && app == mBackupTarget.app) {
11165 // If possible we want to avoid killing apps while they're being backed up
11166 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011167 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011168 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011169 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011170 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011171 }
11172 }
11173
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011174 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11175 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011176 final long now = SystemClock.uptimeMillis();
11177 // This process is more important if the top activity is
11178 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011179 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011180 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011181 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011182 if (s.startRequested) {
11183 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11184 // This service has seen some activity within
11185 // recent memory, so we will keep its process ahead
11186 // of the background processes.
11187 if (adj > SECONDARY_SERVER_ADJ) {
11188 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011189 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011190 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011191 }
11192 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011193 // If we have let the service slide into the background
11194 // state, still have some text describing what it is doing
11195 // even though the service no longer has an impact.
11196 if (adj > SECONDARY_SERVER_ADJ) {
11197 app.adjType = "started-bg-services";
11198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011200 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11201 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011202 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011203 = s.connections.values().iterator();
11204 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011205 ArrayList<ConnectionRecord> clist = kt.next();
11206 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11207 // XXX should compute this based on the max of
11208 // all connected clients.
11209 ConnectionRecord cr = clist.get(i);
11210 if (cr.binding.client == app) {
11211 // Binding to ourself is not interesting.
11212 continue;
11213 }
11214 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11215 ProcessRecord client = cr.binding.client;
11216 int myHiddenAdj = hiddenAdj;
11217 if (myHiddenAdj > client.hiddenAdj) {
11218 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11219 myHiddenAdj = client.hiddenAdj;
11220 } else {
11221 myHiddenAdj = VISIBLE_APP_ADJ;
11222 }
11223 }
11224 int clientAdj = computeOomAdjLocked(
11225 client, myHiddenAdj, TOP_APP, true);
11226 if (adj > clientAdj) {
11227 adj = clientAdj >= VISIBLE_APP_ADJ
11228 ? clientAdj : VISIBLE_APP_ADJ;
11229 if (!client.hidden) {
11230 app.hidden = false;
11231 }
11232 app.adjType = "service";
11233 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11234 .REASON_SERVICE_IN_USE;
11235 app.adjSource = cr.binding.client;
11236 app.adjTarget = s.name;
11237 }
11238 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11239 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11240 schedGroup = Process.THREAD_GROUP_DEFAULT;
11241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242 }
11243 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011244 ActivityRecord a = cr.activity;
11245 //if (a != null) {
11246 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11247 //}
11248 if (a != null && adj > FOREGROUND_APP_ADJ &&
11249 (a.state == ActivityState.RESUMED
11250 || a.state == ActivityState.PAUSING)) {
11251 adj = FOREGROUND_APP_ADJ;
11252 schedGroup = Process.THREAD_GROUP_DEFAULT;
11253 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011254 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011255 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11256 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011257 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011258 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 }
11261 }
11262 }
11263 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011264
11265 // Finally, f this process has active services running in it, we
11266 // would like to avoid killing it unless it would prevent the current
11267 // application from running. By default we put the process in
11268 // with the rest of the background processes; as we scan through
11269 // its services we may bump it up from there.
11270 if (adj > hiddenAdj) {
11271 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011272 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011273 app.adjType = "bg-services";
11274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011275 }
11276
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011277 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11278 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011279 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011280 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11281 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011282 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011283 if (cpr.clients.size() != 0) {
11284 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11285 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11286 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011287 if (client == app) {
11288 // Being our own client is not interesting.
11289 continue;
11290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 int myHiddenAdj = hiddenAdj;
11292 if (myHiddenAdj > client.hiddenAdj) {
11293 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11294 myHiddenAdj = client.hiddenAdj;
11295 } else {
11296 myHiddenAdj = FOREGROUND_APP_ADJ;
11297 }
11298 }
11299 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011300 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011301 if (adj > clientAdj) {
11302 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011303 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011304 if (!client.hidden) {
11305 app.hidden = false;
11306 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011307 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011308 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11309 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011310 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011311 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011313 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11314 schedGroup = Process.THREAD_GROUP_DEFAULT;
11315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011316 }
11317 }
11318 // If the provider has external (non-framework) process
11319 // dependencies, ensure that its adjustment is at least
11320 // FOREGROUND_APP_ADJ.
11321 if (cpr.externals != 0) {
11322 if (adj > FOREGROUND_APP_ADJ) {
11323 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011324 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011325 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011326 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011327 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 }
11329 }
11330 }
11331 }
11332
11333 app.curRawAdj = adj;
11334
Joe Onorato8a9b2202010-02-26 18:56:32 -080011335 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011336 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11337 if (adj > app.maxAdj) {
11338 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011339 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011340 schedGroup = Process.THREAD_GROUP_DEFAULT;
11341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011342 }
11343
11344 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011345 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 return adj;
11348 }
11349
11350 /**
11351 * Ask a given process to GC right now.
11352 */
11353 final void performAppGcLocked(ProcessRecord app) {
11354 try {
11355 app.lastRequestedGc = SystemClock.uptimeMillis();
11356 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011357 if (app.reportLowMemory) {
11358 app.reportLowMemory = false;
11359 app.thread.scheduleLowMemory();
11360 } else {
11361 app.thread.processInBackground();
11362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011363 }
11364 } catch (Exception e) {
11365 // whatever.
11366 }
11367 }
11368
11369 /**
11370 * Returns true if things are idle enough to perform GCs.
11371 */
Josh Bartel7f208742010-02-25 11:01:44 -060011372 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011373 return mParallelBroadcasts.size() == 0
11374 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011375 && (mSleeping || (mMainStack.mResumedActivity != null &&
11376 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011377 }
11378
11379 /**
11380 * Perform GCs on all processes that are waiting for it, but only
11381 * if things are idle.
11382 */
11383 final void performAppGcsLocked() {
11384 final int N = mProcessesToGc.size();
11385 if (N <= 0) {
11386 return;
11387 }
Josh Bartel7f208742010-02-25 11:01:44 -060011388 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011389 while (mProcessesToGc.size() > 0) {
11390 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011391 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011392 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11393 <= SystemClock.uptimeMillis()) {
11394 // To avoid spamming the system, we will GC processes one
11395 // at a time, waiting a few seconds between each.
11396 performAppGcLocked(proc);
11397 scheduleAppGcsLocked();
11398 return;
11399 } else {
11400 // It hasn't been long enough since we last GCed this
11401 // process... put it in the list to wait for its time.
11402 addProcessToGcListLocked(proc);
11403 break;
11404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 }
11406 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011407
11408 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011409 }
11410 }
11411
11412 /**
11413 * If all looks good, perform GCs on all processes waiting for them.
11414 */
11415 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011416 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011417 performAppGcsLocked();
11418 return;
11419 }
11420 // Still not idle, wait some more.
11421 scheduleAppGcsLocked();
11422 }
11423
11424 /**
11425 * Schedule the execution of all pending app GCs.
11426 */
11427 final void scheduleAppGcsLocked() {
11428 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011429
11430 if (mProcessesToGc.size() > 0) {
11431 // Schedule a GC for the time to the next process.
11432 ProcessRecord proc = mProcessesToGc.get(0);
11433 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11434
11435 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11436 long now = SystemClock.uptimeMillis();
11437 if (when < (now+GC_TIMEOUT)) {
11438 when = now + GC_TIMEOUT;
11439 }
11440 mHandler.sendMessageAtTime(msg, when);
11441 }
11442 }
11443
11444 /**
11445 * Add a process to the array of processes waiting to be GCed. Keeps the
11446 * list in sorted order by the last GC time. The process can't already be
11447 * on the list.
11448 */
11449 final void addProcessToGcListLocked(ProcessRecord proc) {
11450 boolean added = false;
11451 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11452 if (mProcessesToGc.get(i).lastRequestedGc <
11453 proc.lastRequestedGc) {
11454 added = true;
11455 mProcessesToGc.add(i+1, proc);
11456 break;
11457 }
11458 }
11459 if (!added) {
11460 mProcessesToGc.add(0, proc);
11461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011462 }
11463
11464 /**
11465 * Set up to ask a process to GC itself. This will either do it
11466 * immediately, or put it on the list of processes to gc the next
11467 * time things are idle.
11468 */
11469 final void scheduleAppGcLocked(ProcessRecord app) {
11470 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011471 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 return;
11473 }
11474 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011475 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011476 scheduleAppGcsLocked();
11477 }
11478 }
11479
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011480 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11481 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11482 if (mLastWakeLockCheckTime == 0) {
11483 doKills = false;
11484 }
11485 if (stats.isScreenOn()) {
11486 doKills = false;
11487 }
11488 final long curRealtime = SystemClock.elapsedRealtime();
11489 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11490 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011491 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011492 doKills = false;
11493 }
11494 int i = mLruProcesses.size();
11495 while (i > 0) {
11496 i--;
11497 ProcessRecord app = mLruProcesses.get(i);
11498 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11499 long wtime;
11500 synchronized (stats) {
11501 wtime = stats.getProcessWakeTime(app.info.uid,
11502 app.pid, curRealtime);
11503 }
11504 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011505 if (false) {
11506 StringBuilder sb = new StringBuilder(128);
11507 sb.append("Wake for ");
11508 app.toShortString(sb);
11509 sb.append(": over ");
11510 TimeUtils.formatDuration(timeSince, sb);
11511 sb.append(" used ");
11512 TimeUtils.formatDuration(timeUsed, sb);
11513 sb.append(" (");
11514 sb.append((timeUsed*100)/timeSince);
11515 sb.append("%)");
11516 Slog.i(TAG, sb.toString());
11517 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011518 // If a process has held a wake lock for more
11519 // than 50% of the time during this period,
11520 // that sounds pad. Kill!
11521 if (doKills && timeSince > 0
11522 && ((timeUsed*100)/timeSince) >= 50) {
11523 Slog.i(TAG, "Excessive wake lock in " + app.processName
11524 + " (pid " + app.pid + "): held " + timeUsed
11525 + " during " + timeSince);
11526 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11527 app.processName, app.setAdj, "excessive wake lock");
11528 Process.killProcessQuiet(app.pid);
11529 } else {
11530 app.lastWakeTime = wtime;
11531 }
11532 }
11533 }
11534 }
11535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 private final boolean updateOomAdjLocked(
11537 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11538 app.hiddenAdj = hiddenAdj;
11539
11540 if (app.thread == null) {
11541 return true;
11542 }
11543
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011544 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011546 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547 if (app.curRawAdj != app.setRawAdj) {
11548 if (app.curRawAdj > FOREGROUND_APP_ADJ
11549 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11550 // If this app is transitioning from foreground to
11551 // non-foreground, have it do a gc.
11552 scheduleAppGcLocked(app);
11553 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11554 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11555 // Likewise do a gc when an app is moving in to the
11556 // background (such as a service stopping).
11557 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011558 // And note its current wake lock time.
11559 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11560 synchronized (stats) {
11561 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11562 app.pid, SystemClock.elapsedRealtime());
11563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011564 }
11565 app.setRawAdj = app.curRawAdj;
11566 }
11567 if (adj != app.setAdj) {
11568 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011569 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 TAG, "Set app " + app.processName +
11571 " oom adj to " + adj);
11572 app.setAdj = adj;
11573 } else {
11574 return false;
11575 }
11576 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011577 if (app.setSchedGroup != app.curSchedGroup) {
11578 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011579 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011580 "Setting process group of " + app.processName
11581 + " to " + app.curSchedGroup);
11582 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011583 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011584 try {
11585 Process.setProcessGroup(app.pid, app.curSchedGroup);
11586 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011587 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011588 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011589 e.printStackTrace();
11590 } finally {
11591 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011592 }
11593 }
11594 if (false) {
11595 if (app.thread != null) {
11596 try {
11597 app.thread.setSchedulingGroup(app.curSchedGroup);
11598 } catch (RemoteException e) {
11599 }
11600 }
11601 }
11602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011603 }
11604
11605 return true;
11606 }
11607
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011608 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011609 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011610 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011611 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011613 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 }
11615 }
11616 return resumedActivity;
11617 }
11618
11619 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011620 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11622 int curAdj = app.curAdj;
11623 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11624 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11625
11626 mAdjSeq++;
11627
11628 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11629 if (res) {
11630 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11631 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11632 if (nowHidden != wasHidden) {
11633 // Changed to/from hidden state, so apps after it in the LRU
11634 // list may also be changed.
11635 updateOomAdjLocked();
11636 }
11637 }
11638 return res;
11639 }
11640
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011641 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011643 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11645
11646 if (false) {
11647 RuntimeException e = new RuntimeException();
11648 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011649 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011650 }
11651
11652 mAdjSeq++;
11653
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011654 // Let's determine how many processes we have running vs.
11655 // how many slots we have for background processes; we may want
11656 // to put multiple processes in a slot of there are enough of
11657 // them.
11658 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11659 int factor = (mLruProcesses.size()-4)/numSlots;
11660 if (factor < 1) factor = 1;
11661 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011662 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011664 // First try updating the OOM adjustment for each of the
11665 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011666 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011667 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11668 while (i > 0) {
11669 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011670 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011671 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011673 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011674 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011675 step++;
11676 if (step >= factor) {
11677 step = 0;
11678 curHiddenAdj++;
11679 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011680 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011681 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011682 if (!app.killedBackground) {
11683 numHidden++;
11684 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011685 Slog.i(TAG, "No longer want " + app.processName
11686 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011687 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11688 app.processName, app.setAdj, "too many background");
11689 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011690 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011691 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011692 }
11693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011694 } else {
11695 didOomAdj = false;
11696 }
11697 }
11698
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011699 // If we return false, we will fall back on killing processes to
11700 // have a fixed limit. Do this if a limit has been requested; else
11701 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011702 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11703 }
11704
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011705 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 synchronized (this) {
11707 int i;
11708
11709 // First remove any unused application processes whose package
11710 // has been removed.
11711 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11712 final ProcessRecord app = mRemovedProcesses.get(i);
11713 if (app.activities.size() == 0
11714 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011715 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011716 TAG, "Exiting empty application process "
11717 + app.processName + " ("
11718 + (app.thread != null ? app.thread.asBinder() : null)
11719 + ")\n");
11720 if (app.pid > 0 && app.pid != MY_PID) {
11721 Process.killProcess(app.pid);
11722 } else {
11723 try {
11724 app.thread.scheduleExit();
11725 } catch (Exception e) {
11726 // Ignore exceptions.
11727 }
11728 }
11729 cleanUpApplicationRecordLocked(app, false, -1);
11730 mRemovedProcesses.remove(i);
11731
11732 if (app.persistent) {
11733 if (app.persistent) {
11734 addAppLocked(app.info);
11735 }
11736 }
11737 }
11738 }
11739
11740 // Now try updating the OOM adjustment for each of the
11741 // application processes based on their current state.
11742 // If the setOomAdj() API is not supported, then go with our
11743 // back-up plan...
11744 if (!updateOomAdjLocked()) {
11745
11746 // Count how many processes are running services.
11747 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011748 for (i=mLruProcesses.size()-1; i>=0; i--) {
11749 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750
11751 if (app.persistent || app.services.size() != 0
11752 || app.curReceiver != null
11753 || app.persistentActivities > 0) {
11754 // Don't count processes holding services against our
11755 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011756 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011757 TAG, "Not trimming app " + app + " with services: "
11758 + app.services);
11759 numServiceProcs++;
11760 }
11761 }
11762
11763 int curMaxProcs = mProcessLimit;
11764 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11765 if (mAlwaysFinishActivities) {
11766 curMaxProcs = 1;
11767 }
11768 curMaxProcs += numServiceProcs;
11769
11770 // Quit as many processes as we can to get down to the desired
11771 // process count. First remove any processes that no longer
11772 // have activites running in them.
11773 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011774 i<mLruProcesses.size()
11775 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011776 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011777 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011778 // Quit an application only if it is not currently
11779 // running any activities.
11780 if (!app.persistent && app.activities.size() == 0
11781 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011782 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011783 TAG, "Exiting empty application process "
11784 + app.processName + " ("
11785 + (app.thread != null ? app.thread.asBinder() : null)
11786 + ")\n");
11787 if (app.pid > 0 && app.pid != MY_PID) {
11788 Process.killProcess(app.pid);
11789 } else {
11790 try {
11791 app.thread.scheduleExit();
11792 } catch (Exception e) {
11793 // Ignore exceptions.
11794 }
11795 }
11796 // todo: For now we assume the application is not buggy
11797 // or evil, and will quit as a result of our request.
11798 // Eventually we need to drive this off of the death
11799 // notification, and kill the process if it takes too long.
11800 cleanUpApplicationRecordLocked(app, false, i);
11801 i--;
11802 }
11803 }
11804
11805 // If we still have too many processes, now from the least
11806 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011807 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011808 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011809 " of " + curMaxProcs + " processes");
11810 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011811 i<mLruProcesses.size()
11812 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011813 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011814 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011815 // Quit the application only if we have a state saved for
11816 // all of its activities.
11817 boolean canQuit = !app.persistent && app.curReceiver == null
11818 && app.services.size() == 0
11819 && app.persistentActivities == 0;
11820 int NUMA = app.activities.size();
11821 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011822 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011823 TAG, "Looking to quit " + app.processName);
11824 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011825 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011826 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011827 TAG, " " + r.intent.getComponent().flattenToShortString()
11828 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11829 canQuit = (r.haveState || !r.stateNotNeeded)
11830 && !r.visible && r.stopped;
11831 }
11832 if (canQuit) {
11833 // Finish all of the activities, and then the app itself.
11834 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011835 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011836 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011837 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011838 }
11839 r.resultTo = null;
11840 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011841 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011842 + app.processName + " ("
11843 + (app.thread != null ? app.thread.asBinder() : null)
11844 + ")\n");
11845 if (app.pid > 0 && app.pid != MY_PID) {
11846 Process.killProcess(app.pid);
11847 } else {
11848 try {
11849 app.thread.scheduleExit();
11850 } catch (Exception e) {
11851 // Ignore exceptions.
11852 }
11853 }
11854 // todo: For now we assume the application is not buggy
11855 // or evil, and will quit as a result of our request.
11856 // Eventually we need to drive this off of the death
11857 // notification, and kill the process if it takes too long.
11858 cleanUpApplicationRecordLocked(app, false, i);
11859 i--;
11860 //dump();
11861 }
11862 }
11863
11864 }
11865
11866 int curMaxActivities = MAX_ACTIVITIES;
11867 if (mAlwaysFinishActivities) {
11868 curMaxActivities = 1;
11869 }
11870
11871 // Finally, if there are too many activities now running, try to
11872 // finish as many as we can to get back down to the limit.
11873 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011874 i<mMainStack.mLRUActivities.size()
11875 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011877 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011878 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011879
11880 // We can finish this one if we have its icicle saved and
11881 // it is not persistent.
11882 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11883 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011884 final int origSize = mMainStack.mLRUActivities.size();
11885 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011886
11887 // This will remove it from the LRU list, so keep
11888 // our index at the same value. Note that this check to
11889 // see if the size changes is just paranoia -- if
11890 // something unexpected happens, we don't want to end up
11891 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011892 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011893 i--;
11894 }
11895 }
11896 }
11897 }
11898 }
11899
11900 /** This method sends the specified signal to each of the persistent apps */
11901 public void signalPersistentProcesses(int sig) throws RemoteException {
11902 if (sig != Process.SIGNAL_USR1) {
11903 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11904 }
11905
11906 synchronized (this) {
11907 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11908 != PackageManager.PERMISSION_GRANTED) {
11909 throw new SecurityException("Requires permission "
11910 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11911 }
11912
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011913 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11914 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011915 if (r.thread != null && r.persistent) {
11916 Process.sendSignal(r.pid, sig);
11917 }
11918 }
11919 }
11920 }
11921
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011922 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011923 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011924
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011925 try {
11926 synchronized (this) {
11927 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11928 // its own permission.
11929 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11930 != PackageManager.PERMISSION_GRANTED) {
11931 throw new SecurityException("Requires permission "
11932 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011933 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011934
11935 if (start && fd == null) {
11936 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011937 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011938
11939 ProcessRecord proc = null;
11940 try {
11941 int pid = Integer.parseInt(process);
11942 synchronized (mPidsSelfLocked) {
11943 proc = mPidsSelfLocked.get(pid);
11944 }
11945 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011946 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011947
11948 if (proc == null) {
11949 HashMap<String, SparseArray<ProcessRecord>> all
11950 = mProcessNames.getMap();
11951 SparseArray<ProcessRecord> procs = all.get(process);
11952 if (procs != null && procs.size() > 0) {
11953 proc = procs.valueAt(0);
11954 }
11955 }
11956
11957 if (proc == null || proc.thread == null) {
11958 throw new IllegalArgumentException("Unknown process: " + process);
11959 }
11960
11961 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11962 if (isSecure) {
11963 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11964 throw new SecurityException("Process not debuggable: " + proc);
11965 }
11966 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011967
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011968 proc.thread.profilerControl(start, path, fd);
11969 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011970 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011971 }
11972 } catch (RemoteException e) {
11973 throw new IllegalStateException("Process disappeared");
11974 } finally {
11975 if (fd != null) {
11976 try {
11977 fd.close();
11978 } catch (IOException e) {
11979 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011980 }
11981 }
11982 }
11983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011984 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11985 public void monitor() {
11986 synchronized (this) { }
11987 }
11988}