blob: cf767ca878cf9a4512a22d262a2a2c2661786b0f [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
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700134public final class ActivityManagerService extends ActivityManagerNative
135 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 static final String TAG = "ActivityManager";
137 static final boolean DEBUG = false;
138 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
139 static final boolean DEBUG_SWITCH = localLOGV || false;
140 static final boolean DEBUG_TASKS = localLOGV || false;
141 static final boolean DEBUG_PAUSE = localLOGV || false;
142 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
143 static final boolean DEBUG_TRANSITION = localLOGV || false;
144 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700145 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 static final boolean DEBUG_SERVICE = localLOGV || false;
147 static final boolean DEBUG_VISBILITY = localLOGV || false;
148 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700149 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800150 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700152 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700153 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700154 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean VALIDATE_TOKENS = false;
156 static final boolean SHOW_ACTIVITY_START_TIME = true;
157
158 // Control over CPU and battery monitoring.
159 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
160 static final boolean MONITOR_CPU_USAGE = true;
161 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
162 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
163 static final boolean MONITOR_THREAD_CPU_USAGE = false;
164
Dianne Hackborn1655be42009-05-08 14:29:01 -0700165 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700166 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 private static final String SYSTEM_SECURE = "ro.secure";
169
170 // This is the maximum number of application processes we would like
171 // to have running. Due to the asynchronous nature of things, we can
172 // temporarily go beyond this limit.
173 static final int MAX_PROCESSES = 2;
174
175 // Set to false to leave processes running indefinitely, relying on
176 // the kernel killing them as resources are required.
177 static final boolean ENFORCE_PROCESS_LIMIT = false;
178
179 // This is the maximum number of activities that we would like to have
180 // running at a given time.
181 static final int MAX_ACTIVITIES = 20;
182
183 // Maximum number of recent tasks that we can remember.
184 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700185
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700186 // Amount of time after a call to stopAppSwitches() during which we will
187 // prevent further untrusted switches from happening.
188 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
190 // How long we wait for a launched process to attach to the activity manager
191 // before we decide it's never going to come up for real.
192 static final int PROC_START_TIMEOUT = 10*1000;
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 // How long to wait after going idle before forcing apps to GC.
195 static final int GC_TIMEOUT = 5*1000;
196
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700197 // The minimum amount of time between successive GC requests for a process.
198 static final int GC_MIN_INTERVAL = 60*1000;
199
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700200 // The rate at which we check for apps using excessive wake locks -- 15 mins.
201 static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 // How long we allow a receiver to run before giving up on it.
204 static final int BROADCAST_TIMEOUT = 10*1000;
205
206 // How long we wait for a service to finish executing.
207 static final int SERVICE_TIMEOUT = 20*1000;
208
209 // How long a service needs to be running until restarting its process
210 // is no longer considered to be a relaunch of the service.
211 static final int SERVICE_RESTART_DURATION = 5*1000;
212
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700213 // How long a service needs to be running until it will start back at
214 // SERVICE_RESTART_DURATION after being killed.
215 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
216
217 // Multiplying factor to increase restart duration time by, for each time
218 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
219 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
220
221 // The minimum amount of time between restarting services that we allow.
222 // That is, when multiple services are restarting, we won't allow each
223 // to restart less than this amount of time from the last one.
224 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 // Maximum amount of time for there to be no activity on a service before
227 // we consider it non-essential and allow its process to go on the
228 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700229 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230
231 // How long we wait until we timeout on key dispatching.
232 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
233
234 // The minimum time we allow between crashes, for us to consider this
235 // application to be bad and stop and its services and reject broadcasts.
236 static final int MIN_CRASH_INTERVAL = 60*1000;
237
238 // How long we wait until we timeout on key dispatching during instrumentation.
239 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
240
241 // OOM adjustments for processes in various states:
242
243 // This is a process without anything currently running in it. Definitely
244 // the first to go! Value set in system/rootdir/init.rc on startup.
245 // This value is initalized in the constructor, careful when refering to
246 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800247 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248
249 // This is a process only hosting activities that are not visible,
250 // so it can be killed without any disruption. Value set in
251 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800252 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 static int HIDDEN_APP_MIN_ADJ;
254
The Android Open Source Project4df24232009-03-05 14:34:35 -0800255 // This is a process holding the home application -- we want to try
256 // avoiding killing it, even if it would normally be in the background,
257 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800258 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800259
Christopher Tate6fa95972009-06-05 18:43:55 -0700260 // This is a process currently hosting a backup operation. Killing it
261 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800262 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 // This is a process holding a secondary server -- killing it will not
265 // have much of an impact as far as the user is concerned. Value set in
266 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800267 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700269 // This is a process with a heavy-weight application. It is in the
270 // background, but we want to try to avoid killing it. Value set in
271 // system/rootdir/init.rc on startup.
272 static final int HEAVY_WEIGHT_APP_ADJ;
273
274 // This is a process only hosting components that are perceptible to the
275 // user, and we really want to avoid killing them, but they are not
276 // immediately visible. An example is background music playback. Value set in
277 // system/rootdir/init.rc on startup.
278 static final int PERCEPTIBLE_APP_ADJ;
279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 // This is a process only hosting activities that are visible to the
281 // user, so we'd prefer they don't disappear. Value set in
282 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800283 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
285 // This is the process running the current foreground app. We'd really
286 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 // This is a process running a core server, such as telephony. Definitely
290 // don't want to kill it, but doing so is not completely fatal.
291 static final int CORE_SERVER_ADJ = -12;
292
293 // The system process runs at the default adjustment.
294 static final int SYSTEM_ADJ = -16;
295
296 // Memory pages are 4K.
297 static final int PAGE_SIZE = 4*1024;
298
299 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800300 static final int EMPTY_APP_MEM;
301 static final int HIDDEN_APP_MEM;
302 static final int HOME_APP_MEM;
303 static final int BACKUP_APP_MEM;
304 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700305 static final int HEAVY_WEIGHT_APP_MEM;
306 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int VISIBLE_APP_MEM;
308 static final int FOREGROUND_APP_MEM;
309
310 // The minimum number of hidden apps we want to be able to keep around,
311 // without empty apps being able to push them out of memory.
312 static final int MIN_HIDDEN_APPS = 2;
313
Dianne Hackborn8633e682010-04-22 16:03:41 -0700314 // The maximum number of hidden processes we will keep around before
315 // killing them; this is just a control to not let us go too crazy with
316 // keeping around processes on devices with large amounts of RAM.
317 static final int MAX_HIDDEN_APPS = 15;
318
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800319 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700320 // been idle for less than 15 seconds.
321 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800322
323 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700324 // been idle for less than 120 seconds.
325 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800326
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700327 static int getIntProp(String name, boolean allowZero) {
328 String str = SystemProperties.get(name);
329 if (str == null) {
330 throw new IllegalArgumentException("Property not defined: " + name);
331 }
332 int val = Integer.valueOf(str);
333 if (val == 0 && !allowZero) {
334 throw new IllegalArgumentException("Property must not be zero: " + name);
335 }
336 return val;
337 }
338
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339 static {
340 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700341 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
342 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
343 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
344 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
345 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
346 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
347 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
348 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
349 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
350 // These days we use the last empty slot for hidden apps as well.
351 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
352 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
353 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
354 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
355 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
356 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
357 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
358 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
359 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
360 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362
Dan Egnor42471dd2010-01-07 17:25:22 -0800363 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364
365 static final String[] EMPTY_STRING_ARRAY = new String[0];
366
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700367 public ActivityStack mMainStack;
368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700370 * Description of a request to start a new activity, which has been held
371 * due to app switches being disabled.
372 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700373 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700374 ActivityRecord r;
375 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700376 Uri[] grantedUriPermissions;
377 int grantedMode;
378 boolean onlyIfNeeded;
379 }
380
381 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
382 = new ArrayList<PendingActivityLaunch>();
383
384 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 * List of all active broadcasts that are to be executed immediately
386 * (without waiting for another broadcast to finish). Currently this only
387 * contains broadcasts to registered receivers, to avoid spinning up
388 * a bunch of processes to execute IntentReceiver components.
389 */
390 final ArrayList<BroadcastRecord> mParallelBroadcasts
391 = new ArrayList<BroadcastRecord>();
392
393 /**
394 * List of all active broadcasts that are to be executed one at a time.
395 * The object at the top of the list is the currently activity broadcasts;
396 * those after it are waiting for the top to finish..
397 */
398 final ArrayList<BroadcastRecord> mOrderedBroadcasts
399 = new ArrayList<BroadcastRecord>();
400
401 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800402 * Historical data of past broadcasts, for debugging.
403 */
404 static final int MAX_BROADCAST_HISTORY = 100;
405 final BroadcastRecord[] mBroadcastHistory
406 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
407
408 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 * Set when we current have a BROADCAST_INTENT_MSG in flight.
410 */
411 boolean mBroadcastsScheduled = false;
412
413 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 * Activity we have told the window manager to have key focus.
415 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700416 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700417 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 * List of intents that were used to start the most recent tasks.
419 */
420 final ArrayList<TaskRecord> mRecentTasks
421 = new ArrayList<TaskRecord>();
422
423 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 * All of the applications we currently have running organized by name.
425 * The keys are strings of the application package name (as
426 * returned by the package manager), and the keys are ApplicationRecord
427 * objects.
428 */
429 final ProcessMap<ProcessRecord> mProcessNames
430 = new ProcessMap<ProcessRecord>();
431
432 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700433 * The currently running heavy-weight process, if any.
434 */
435 ProcessRecord mHeavyWeightProcess = null;
436
437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * The last time that various processes have crashed.
439 */
440 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
441
442 /**
443 * Set of applications that we consider to be bad, and will reject
444 * incoming broadcasts from (which the user has no control over).
445 * Processes are added to this set when they have crashed twice within
446 * a minimum amount of time; they are removed from it when they are
447 * later restarted (hopefully due to some user action). The value is the
448 * time it was added to the list.
449 */
450 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
451
452 /**
453 * All of the processes we currently have running organized by pid.
454 * The keys are the pid running the application.
455 *
456 * <p>NOTE: This object is protected by its own lock, NOT the global
457 * activity manager lock!
458 */
459 final SparseArray<ProcessRecord> mPidsSelfLocked
460 = new SparseArray<ProcessRecord>();
461
462 /**
463 * All of the processes that have been forced to be foreground. The key
464 * is the pid of the caller who requested it (we hold a death
465 * link on it).
466 */
467 abstract class ForegroundToken implements IBinder.DeathRecipient {
468 int pid;
469 IBinder token;
470 }
471 final SparseArray<ForegroundToken> mForegroundProcesses
472 = new SparseArray<ForegroundToken>();
473
474 /**
475 * List of records for processes that someone had tried to start before the
476 * system was ready. We don't start them at that point, but ensure they
477 * are started by the time booting is complete.
478 */
479 final ArrayList<ProcessRecord> mProcessesOnHold
480 = new ArrayList<ProcessRecord>();
481
482 /**
483 * List of records for processes that we have started and are waiting
484 * for them to call back. This is really only needed when running in
485 * single processes mode, in which case we do not have a unique pid for
486 * each process.
487 */
488 final ArrayList<ProcessRecord> mStartingProcesses
489 = new ArrayList<ProcessRecord>();
490
491 /**
492 * List of persistent applications that are in the process
493 * of being started.
494 */
495 final ArrayList<ProcessRecord> mPersistentStartingProcesses
496 = new ArrayList<ProcessRecord>();
497
498 /**
499 * Processes that are being forcibly torn down.
500 */
501 final ArrayList<ProcessRecord> mRemovedProcesses
502 = new ArrayList<ProcessRecord>();
503
504 /**
505 * List of running applications, sorted by recent usage.
506 * The first entry in the list is the least recently used.
507 * It contains ApplicationRecord objects. This list does NOT include
508 * any persistent application records (since we never want to exit them).
509 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800510 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 = new ArrayList<ProcessRecord>();
512
513 /**
514 * List of processes that should gc as soon as things are idle.
515 */
516 final ArrayList<ProcessRecord> mProcessesToGc
517 = new ArrayList<ProcessRecord>();
518
519 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800520 * This is the process holding what we currently consider to be
521 * the "home" activity.
522 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700523 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800524
525 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 * Set of PendingResultRecord objects that are currently active.
527 */
528 final HashSet mPendingResultRecords = new HashSet();
529
530 /**
531 * Set of IntentSenderRecord objects that are currently active.
532 */
533 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
534 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
535
536 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700537 * Fingerprints (String.hashCode()) of stack traces that we've
538 * already logged DropBox entries for. Guarded by itself. If
539 * something (rogue user app) forces this over
540 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
541 */
542 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
543 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
544
545 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700546 * Strict Mode background batched logging state.
547 *
548 * The string buffer is guarded by itself, and its lock is also
549 * used to determine if another batched write is already
550 * in-flight.
551 */
552 private final StringBuilder mStrictModeBuffer = new StringBuilder();
553
554 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 * Intent broadcast that we have tried to start, but are
556 * waiting for its application's process to be created. We only
557 * need one (instead of a list) because we always process broadcasts
558 * one at a time, so no others can be started while waiting for this
559 * one.
560 */
561 BroadcastRecord mPendingBroadcast = null;
562
563 /**
564 * Keeps track of all IIntentReceivers that have been registered for
565 * broadcasts. Hash keys are the receiver IBinder, hash value is
566 * a ReceiverList.
567 */
568 final HashMap mRegisteredReceivers = new HashMap();
569
570 /**
571 * Resolver for broadcast intents to registered receivers.
572 * Holds BroadcastFilter (subclass of IntentFilter).
573 */
574 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
575 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
576 @Override
577 protected boolean allowFilterResult(
578 BroadcastFilter filter, List<BroadcastFilter> dest) {
579 IBinder target = filter.receiverList.receiver.asBinder();
580 for (int i=dest.size()-1; i>=0; i--) {
581 if (dest.get(i).receiverList.receiver.asBinder() == target) {
582 return false;
583 }
584 }
585 return true;
586 }
587 };
588
589 /**
590 * State of all active sticky broadcasts. Keys are the action of the
591 * sticky Intent, values are an ArrayList of all broadcasted intents with
592 * that action (which should usually be one).
593 */
594 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
595 new HashMap<String, ArrayList<Intent>>();
596
597 /**
598 * All currently running services.
599 */
600 final HashMap<ComponentName, ServiceRecord> mServices =
601 new HashMap<ComponentName, ServiceRecord>();
602
603 /**
604 * All currently running services indexed by the Intent used to start them.
605 */
606 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
607 new HashMap<Intent.FilterComparison, ServiceRecord>();
608
609 /**
610 * All currently bound service connections. Keys are the IBinder of
611 * the client's IServiceConnection.
612 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700613 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
614 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615
616 /**
617 * List of services that we have been asked to start,
618 * but haven't yet been able to. It is used to hold start requests
619 * while waiting for their corresponding application thread to get
620 * going.
621 */
622 final ArrayList<ServiceRecord> mPendingServices
623 = new ArrayList<ServiceRecord>();
624
625 /**
626 * List of services that are scheduled to restart following a crash.
627 */
628 final ArrayList<ServiceRecord> mRestartingServices
629 = new ArrayList<ServiceRecord>();
630
631 /**
632 * List of services that are in the process of being stopped.
633 */
634 final ArrayList<ServiceRecord> mStoppingServices
635 = new ArrayList<ServiceRecord>();
636
637 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700638 * Backup/restore process management
639 */
640 String mBackupAppName = null;
641 BackupRecord mBackupTarget = null;
642
643 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 * List of PendingThumbnailsRecord objects of clients who are still
645 * waiting to receive all of the thumbnails for a task.
646 */
647 final ArrayList mPendingThumbnails = new ArrayList();
648
649 /**
650 * List of HistoryRecord objects that have been finished and must
651 * still report back to a pending thumbnail receiver.
652 */
653 final ArrayList mCancelledThumbnails = new ArrayList();
654
655 /**
656 * All of the currently running global content providers. Keys are a
657 * string containing the provider name and values are a
658 * ContentProviderRecord object containing the data about it. Note
659 * that a single provider may be published under multiple names, so
660 * there may be multiple entries here for a single one in mProvidersByClass.
661 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700662 final HashMap<String, ContentProviderRecord> mProvidersByName
663 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664
665 /**
666 * All of the currently running global content providers. Keys are a
667 * string containing the provider's implementation class and values are a
668 * ContentProviderRecord object containing the data about it.
669 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700670 final HashMap<String, ContentProviderRecord> mProvidersByClass
671 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672
673 /**
674 * List of content providers who have clients waiting for them. The
675 * application is currently being launched and the provider will be
676 * removed from this list once it is published.
677 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700678 final ArrayList<ContentProviderRecord> mLaunchingProviders
679 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680
681 /**
682 * Global set of specific Uri permissions that have been granted.
683 */
684 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
685 = new SparseArray<HashMap<Uri, UriPermission>>();
686
687 /**
688 * Thread-local storage used to carry caller permissions over through
689 * indirect content-provider access.
690 * @see #ActivityManagerService.openContentUri()
691 */
692 private class Identity {
693 public int pid;
694 public int uid;
695
696 Identity(int _pid, int _uid) {
697 pid = _pid;
698 uid = _uid;
699 }
700 }
701 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
702
703 /**
704 * All information we have collected about the runtime performance of
705 * any user id that can impact battery performance.
706 */
707 final BatteryStatsService mBatteryStatsService;
708
709 /**
710 * information about component usage
711 */
712 final UsageStatsService mUsageStatsService;
713
714 /**
715 * Current configuration information. HistoryRecord objects are given
716 * a reference to this object to indicate which configuration they are
717 * currently running in, so this object must be kept immutable.
718 */
719 Configuration mConfiguration = new Configuration();
720
721 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800722 * Current sequencing integer of the configuration, for skipping old
723 * configurations.
724 */
725 int mConfigurationSeq = 0;
726
727 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700728 * Hardware-reported OpenGLES version.
729 */
730 final int GL_ES_VERSION;
731
732 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 * List of initialization arguments to pass to all processes when binding applications to them.
734 * For example, references to the commonly used services.
735 */
736 HashMap<String, IBinder> mAppBindArgs;
737
738 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700739 * Temporary to avoid allocations. Protected by main lock.
740 */
741 final StringBuilder mStringBuilder = new StringBuilder(256);
742
743 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 * Used to control how we initialize the service.
745 */
746 boolean mStartRunning = false;
747 ComponentName mTopComponent;
748 String mTopAction;
749 String mTopData;
750 boolean mSystemReady = false;
751 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700752 boolean mWaitingUpdate = false;
753 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700754 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700755 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756
757 Context mContext;
758
759 int mFactoryTest;
760
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700761 boolean mCheckedForSetup;
762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700764 * The time at which we will allow normal application switches again,
765 * after a call to {@link #stopAppSwitches()}.
766 */
767 long mAppSwitchesAllowedTime;
768
769 /**
770 * This is set to true after the first switch after mAppSwitchesAllowedTime
771 * is set; any switches after that will clear the time.
772 */
773 boolean mDidAppSwitch;
774
775 /**
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700776 * Last time (in realtime) at which we checked for wake lock usage.
777 */
778 long mLastWakeLockCheckTime;
779
780 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 * Set while we are wanting to sleep, to prevent any
782 * activities from being started/resumed.
783 */
784 boolean mSleeping = false;
785
786 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700787 * Set if we are shutting down the system, similar to sleeping.
788 */
789 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790
791 /**
792 * Task identifier that activities are currently being started
793 * in. Incremented each time a new task is created.
794 * todo: Replace this with a TokenSpace class that generates non-repeating
795 * integers that won't wrap.
796 */
797 int mCurTask = 1;
798
799 /**
800 * Current sequence id for oom_adj computation traversal.
801 */
802 int mAdjSeq = 0;
803
804 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700805 * Current sequence id for process LRU updating.
806 */
807 int mLruSeq = 0;
808
809 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
811 * is set, indicating the user wants processes started in such a way
812 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
813 * running in each process (thus no pre-initialized process, etc).
814 */
815 boolean mSimpleProcessManagement = false;
816
817 /**
818 * System monitoring: number of processes that died since the last
819 * N procs were started.
820 */
821 int[] mProcDeaths = new int[20];
822
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700823 /**
824 * This is set if we had to do a delayed dexopt of an app before launching
825 * it, to increasing the ANR timeouts in that case.
826 */
827 boolean mDidDexOpt;
828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 String mDebugApp = null;
830 boolean mWaitForDebugger = false;
831 boolean mDebugTransient = false;
832 String mOrigDebugApp = null;
833 boolean mOrigWaitForDebugger = false;
834 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700835 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700837 final RemoteCallbackList<IActivityWatcher> mWatchers
838 = new RemoteCallbackList<IActivityWatcher>();
839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 /**
841 * Callback of last caller to {@link #requestPss}.
842 */
843 Runnable mRequestPssCallback;
844
845 /**
846 * Remaining processes for which we are waiting results from the last
847 * call to {@link #requestPss}.
848 */
849 final ArrayList<ProcessRecord> mRequestPssList
850 = new ArrayList<ProcessRecord>();
851
852 /**
853 * Runtime statistics collection thread. This object's lock is used to
854 * protect all related state.
855 */
856 final Thread mProcessStatsThread;
857
858 /**
859 * Used to collect process stats when showing not responding dialog.
860 * Protected by mProcessStatsThread.
861 */
862 final ProcessStats mProcessStats = new ProcessStats(
863 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700864 final AtomicLong mLastCpuTime = new AtomicLong(0);
865 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 long mLastWriteTime = 0;
868
869 /**
870 * Set to true after the system has finished booting.
871 */
872 boolean mBooted = false;
873
874 int mProcessLimit = 0;
875
876 WindowManagerService mWindowManager;
877
878 static ActivityManagerService mSelf;
879 static ActivityThread mSystemThread;
880
881 private final class AppDeathRecipient implements IBinder.DeathRecipient {
882 final ProcessRecord mApp;
883 final int mPid;
884 final IApplicationThread mAppThread;
885
886 AppDeathRecipient(ProcessRecord app, int pid,
887 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800888 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 TAG, "New death recipient " + this
890 + " for thread " + thread.asBinder());
891 mApp = app;
892 mPid = pid;
893 mAppThread = thread;
894 }
895
896 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800897 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 TAG, "Death received in " + this
899 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 synchronized(ActivityManagerService.this) {
901 appDiedLocked(mApp, mPid, mAppThread);
902 }
903 }
904 }
905
906 static final int SHOW_ERROR_MSG = 1;
907 static final int SHOW_NOT_RESPONDING_MSG = 2;
908 static final int SHOW_FACTORY_ERROR_MSG = 3;
909 static final int UPDATE_CONFIGURATION_MSG = 4;
910 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
911 static final int WAIT_FOR_DEBUGGER_MSG = 6;
912 static final int BROADCAST_INTENT_MSG = 7;
913 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 static final int SERVICE_TIMEOUT_MSG = 12;
915 static final int UPDATE_TIME_ZONE = 13;
916 static final int SHOW_UID_ERROR_MSG = 14;
917 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700919 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700920 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800921 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700922 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
923 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700924 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700925 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926
927 AlertDialog mUidAlert;
928
929 final Handler mHandler = new Handler() {
930 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800931 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 //}
933
934 public void handleMessage(Message msg) {
935 switch (msg.what) {
936 case SHOW_ERROR_MSG: {
937 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 synchronized (ActivityManagerService.this) {
939 ProcessRecord proc = (ProcessRecord)data.get("app");
940 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800941 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 return;
943 }
944 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700945 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800946 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 d.show();
948 proc.crashDialog = d;
949 } else {
950 // The device is asleep, so just pretend that the user
951 // saw a crash dialog and hit "force quit".
952 res.set(0);
953 }
954 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700955
956 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 } break;
958 case SHOW_NOT_RESPONDING_MSG: {
959 synchronized (ActivityManagerService.this) {
960 HashMap data = (HashMap) msg.obj;
961 ProcessRecord proc = (ProcessRecord)data.get("app");
962 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800963 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 return;
965 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800966
967 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
968 null, null, 0, null, null, null,
969 false, false, MY_PID, Process.SYSTEM_UID);
970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700972 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 d.show();
974 proc.anrDialog = d;
975 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700976
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700977 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700979 case SHOW_STRICT_MODE_VIOLATION_MSG: {
980 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
981 synchronized (ActivityManagerService.this) {
982 ProcessRecord proc = (ProcessRecord) data.get("app");
983 if (proc == null) {
984 Slog.e(TAG, "App not found when showing strict mode dialog.");
985 break;
986 }
987 if (proc.crashDialog != null) {
988 Slog.e(TAG, "App already has strict mode dialog: " + proc);
989 return;
990 }
991 AppErrorResult res = (AppErrorResult) data.get("result");
992 if (!mSleeping && !mShuttingDown) {
993 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
994 d.show();
995 proc.crashDialog = d;
996 } else {
997 // The device is asleep, so just pretend that the user
998 // saw a crash dialog and hit "force quit".
999 res.set(0);
1000 }
1001 }
1002 ensureBootCompleted();
1003 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 case SHOW_FACTORY_ERROR_MSG: {
1005 Dialog d = new FactoryErrorDialog(
1006 mContext, msg.getData().getCharSequence("msg"));
1007 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001008 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 } break;
1010 case UPDATE_CONFIGURATION_MSG: {
1011 final ContentResolver resolver = mContext.getContentResolver();
1012 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1013 } break;
1014 case GC_BACKGROUND_PROCESSES_MSG: {
1015 synchronized (ActivityManagerService.this) {
1016 performAppGcsIfAppropriateLocked();
1017 }
1018 } break;
1019 case WAIT_FOR_DEBUGGER_MSG: {
1020 synchronized (ActivityManagerService.this) {
1021 ProcessRecord app = (ProcessRecord)msg.obj;
1022 if (msg.arg1 != 0) {
1023 if (!app.waitedForDebugger) {
1024 Dialog d = new AppWaitingForDebuggerDialog(
1025 ActivityManagerService.this,
1026 mContext, app);
1027 app.waitDialog = d;
1028 app.waitedForDebugger = true;
1029 d.show();
1030 }
1031 } else {
1032 if (app.waitDialog != null) {
1033 app.waitDialog.dismiss();
1034 app.waitDialog = null;
1035 }
1036 }
1037 }
1038 } break;
1039 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001040 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 TAG, "Received BROADCAST_INTENT_MSG");
1042 processNextBroadcast(true);
1043 } break;
1044 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001045 if (mDidDexOpt) {
1046 mDidDexOpt = false;
1047 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1048 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1049 return;
1050 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001051 // Only process broadcast timeouts if the system is ready. That way
1052 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1053 // to do heavy lifting for system up
1054 if (mSystemReady) {
1055 broadcastTimeout();
1056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001059 if (mDidDexOpt) {
1060 mDidDexOpt = false;
1061 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1062 nmsg.obj = msg.obj;
1063 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1064 return;
1065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 serviceTimeout((ProcessRecord)msg.obj);
1067 } break;
1068 case UPDATE_TIME_ZONE: {
1069 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001070 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1071 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 if (r.thread != null) {
1073 try {
1074 r.thread.updateTimeZone();
1075 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001076 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 }
1078 }
1079 }
1080 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001081 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 case SHOW_UID_ERROR_MSG: {
1083 // XXX This is a temporary dialog, no need to localize.
1084 AlertDialog d = new BaseErrorDialog(mContext);
1085 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1086 d.setCancelable(false);
1087 d.setTitle("System UIDs Inconsistent");
1088 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1089 d.setButton("I'm Feeling Lucky",
1090 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1091 mUidAlert = d;
1092 d.show();
1093 } break;
1094 case IM_FEELING_LUCKY_MSG: {
1095 if (mUidAlert != null) {
1096 mUidAlert.dismiss();
1097 mUidAlert = null;
1098 }
1099 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001101 if (mDidDexOpt) {
1102 mDidDexOpt = false;
1103 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1104 nmsg.obj = msg.obj;
1105 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1106 return;
1107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 ProcessRecord app = (ProcessRecord)msg.obj;
1109 synchronized (ActivityManagerService.this) {
1110 processStartTimedOutLocked(app);
1111 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001112 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001113 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1114 synchronized (ActivityManagerService.this) {
1115 doPendingActivityLaunchesLocked(true);
1116 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001117 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001118 case KILL_APPLICATION_MSG: {
1119 synchronized (ActivityManagerService.this) {
1120 int uid = msg.arg1;
1121 boolean restart = (msg.arg2 == 1);
1122 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001123 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001124 }
1125 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001126 case FINALIZE_PENDING_INTENT_MSG: {
1127 ((PendingIntentRecord)msg.obj).completeFinalize();
1128 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001129 case POST_HEAVY_NOTIFICATION_MSG: {
1130 INotificationManager inm = NotificationManager.getService();
1131 if (inm == null) {
1132 return;
1133 }
1134
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001135 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001136 ProcessRecord process = root.app;
1137 if (process == null) {
1138 return;
1139 }
1140
1141 try {
1142 Context context = mContext.createPackageContext(process.info.packageName, 0);
1143 String text = mContext.getString(R.string.heavy_weight_notification,
1144 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1145 Notification notification = new Notification();
1146 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1147 notification.when = 0;
1148 notification.flags = Notification.FLAG_ONGOING_EVENT;
1149 notification.tickerText = text;
1150 notification.defaults = 0; // please be quiet
1151 notification.sound = null;
1152 notification.vibrate = null;
1153 notification.setLatestEventInfo(context, text,
1154 mContext.getText(R.string.heavy_weight_notification_detail),
1155 PendingIntent.getActivity(mContext, 0, root.intent,
1156 PendingIntent.FLAG_CANCEL_CURRENT));
1157
1158 try {
1159 int[] outId = new int[1];
1160 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1161 notification, outId);
1162 } catch (RuntimeException e) {
1163 Slog.w(ActivityManagerService.TAG,
1164 "Error showing notification for heavy-weight app", e);
1165 } catch (RemoteException e) {
1166 }
1167 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001168 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001169 }
1170 } break;
1171 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1172 INotificationManager inm = NotificationManager.getService();
1173 if (inm == null) {
1174 return;
1175 }
1176 try {
1177 inm.cancelNotification("android",
1178 R.string.heavy_weight_notification);
1179 } catch (RuntimeException e) {
1180 Slog.w(ActivityManagerService.TAG,
1181 "Error canceling notification for service", e);
1182 } catch (RemoteException e) {
1183 }
1184 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001185 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1186 synchronized (ActivityManagerService.this) {
1187 checkExcessiveWakeLocksLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001188 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001189 if (mSleeping) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001190 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1191 sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001192 }
1193 }
1194 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 }
1196 }
1197 };
1198
1199 public static void setSystemProcess() {
1200 try {
1201 ActivityManagerService m = mSelf;
1202
1203 ServiceManager.addService("activity", m);
1204 ServiceManager.addService("meminfo", new MemBinder(m));
1205 if (MONITOR_CPU_USAGE) {
1206 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 ServiceManager.addService("permission", new PermissionController(m));
1209
1210 ApplicationInfo info =
1211 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001212 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001213 mSystemThread.installSystemApplicationInfo(info);
1214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 synchronized (mSelf) {
1216 ProcessRecord app = mSelf.newProcessRecordLocked(
1217 mSystemThread.getApplicationThread(), info,
1218 info.processName);
1219 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001220 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 app.maxAdj = SYSTEM_ADJ;
1222 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1223 synchronized (mSelf.mPidsSelfLocked) {
1224 mSelf.mPidsSelfLocked.put(app.pid, app);
1225 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001226 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 }
1228 } catch (PackageManager.NameNotFoundException e) {
1229 throw new RuntimeException(
1230 "Unable to find android system package", e);
1231 }
1232 }
1233
1234 public void setWindowManager(WindowManagerService wm) {
1235 mWindowManager = wm;
1236 }
1237
1238 public static final Context main(int factoryTest) {
1239 AThread thr = new AThread();
1240 thr.start();
1241
1242 synchronized (thr) {
1243 while (thr.mService == null) {
1244 try {
1245 thr.wait();
1246 } catch (InterruptedException e) {
1247 }
1248 }
1249 }
1250
1251 ActivityManagerService m = thr.mService;
1252 mSelf = m;
1253 ActivityThread at = ActivityThread.systemMain();
1254 mSystemThread = at;
1255 Context context = at.getSystemContext();
1256 m.mContext = context;
1257 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001258 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259
1260 m.mBatteryStatsService.publish(context);
1261 m.mUsageStatsService.publish(context);
1262
1263 synchronized (thr) {
1264 thr.mReady = true;
1265 thr.notifyAll();
1266 }
1267
1268 m.startRunning(null, null, null, null);
1269
1270 return context;
1271 }
1272
1273 public static ActivityManagerService self() {
1274 return mSelf;
1275 }
1276
1277 static class AThread extends Thread {
1278 ActivityManagerService mService;
1279 boolean mReady = false;
1280
1281 public AThread() {
1282 super("ActivityManager");
1283 }
1284
1285 public void run() {
1286 Looper.prepare();
1287
1288 android.os.Process.setThreadPriority(
1289 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001290 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291
1292 ActivityManagerService m = new ActivityManagerService();
1293
1294 synchronized (this) {
1295 mService = m;
1296 notifyAll();
1297 }
1298
1299 synchronized (this) {
1300 while (!mReady) {
1301 try {
1302 wait();
1303 } catch (InterruptedException e) {
1304 }
1305 }
1306 }
1307
1308 Looper.loop();
1309 }
1310 }
1311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312 static class MemBinder extends Binder {
1313 ActivityManagerService mActivityManagerService;
1314 MemBinder(ActivityManagerService activityManagerService) {
1315 mActivityManagerService = activityManagerService;
1316 }
1317
1318 @Override
1319 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1320 ActivityManagerService service = mActivityManagerService;
1321 ArrayList<ProcessRecord> procs;
1322 synchronized (mActivityManagerService) {
1323 if (args != null && args.length > 0
1324 && args[0].charAt(0) != '-') {
1325 procs = new ArrayList<ProcessRecord>();
1326 int pid = -1;
1327 try {
1328 pid = Integer.parseInt(args[0]);
1329 } catch (NumberFormatException e) {
1330
1331 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001332 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1333 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 if (proc.pid == pid) {
1335 procs.add(proc);
1336 } else if (proc.processName.equals(args[0])) {
1337 procs.add(proc);
1338 }
1339 }
1340 if (procs.size() <= 0) {
1341 pw.println("No process found for: " + args[0]);
1342 return;
1343 }
1344 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001345 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 }
1347 }
1348 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1349 }
1350 }
1351
1352 static class CpuBinder extends Binder {
1353 ActivityManagerService mActivityManagerService;
1354 CpuBinder(ActivityManagerService activityManagerService) {
1355 mActivityManagerService = activityManagerService;
1356 }
1357
1358 @Override
1359 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1360 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001361 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1362 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1363 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 }
1365 }
1366 }
1367
1368 private ActivityManagerService() {
1369 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1370 if (v != null && Integer.getInteger(v) != 0) {
1371 mSimpleProcessManagement = true;
1372 }
1373 v = System.getenv("ANDROID_DEBUG_APP");
1374 if (v != null) {
1375 mSimpleProcessManagement = true;
1376 }
1377
Joe Onorato8a9b2202010-02-26 18:56:32 -08001378 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 File dataDir = Environment.getDataDirectory();
1381 File systemDir = new File(dataDir, "system");
1382 systemDir.mkdirs();
1383 mBatteryStatsService = new BatteryStatsService(new File(
1384 systemDir, "batterystats.bin").toString());
1385 mBatteryStatsService.getActiveStatistics().readLocked();
1386 mBatteryStatsService.getActiveStatistics().writeLocked();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001387 mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
1388 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001390 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001391 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392
Jack Palevichb90d28c2009-07-22 15:35:24 -07001393 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1394 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1395
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001396 mConfiguration.setToDefaults();
1397 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 mProcessStats.init();
1399
1400 // Add ourself to the Watchdog monitors.
1401 Watchdog.getInstance().addMonitor(this);
1402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 mProcessStatsThread = new Thread("ProcessStats") {
1404 public void run() {
1405 while (true) {
1406 try {
1407 try {
1408 synchronized(this) {
1409 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001410 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001412 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 // + ", write delay=" + nextWriteDelay);
1414 if (nextWriteDelay < nextCpuDelay) {
1415 nextCpuDelay = nextWriteDelay;
1416 }
1417 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001418 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 this.wait(nextCpuDelay);
1420 }
1421 }
1422 } catch (InterruptedException e) {
1423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 updateCpuStatsNow();
1425 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001426 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 }
1428 }
1429 }
1430 };
1431 mProcessStatsThread.start();
1432 }
1433
1434 @Override
1435 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1436 throws RemoteException {
1437 try {
1438 return super.onTransact(code, data, reply, flags);
1439 } catch (RuntimeException e) {
1440 // The activity manager only throws security exceptions, so let's
1441 // log all others.
1442 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001443 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 }
1445 throw e;
1446 }
1447 }
1448
1449 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001450 final long now = SystemClock.uptimeMillis();
1451 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1452 return;
1453 }
1454 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1455 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 mProcessStatsThread.notify();
1457 }
1458 }
1459 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 void updateCpuStatsNow() {
1462 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001463 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 final long now = SystemClock.uptimeMillis();
1465 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001468 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1469 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 haveNewCpuStats = true;
1471 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001472 //Slog.i(TAG, mProcessStats.printCurrentState());
1473 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 // + mProcessStats.getTotalCpuPercent() + "%");
1475
Joe Onorato8a9b2202010-02-26 18:56:32 -08001476 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 if ("true".equals(SystemProperties.get("events.cpu"))) {
1478 int user = mProcessStats.getLastUserTime();
1479 int system = mProcessStats.getLastSystemTime();
1480 int iowait = mProcessStats.getLastIoWaitTime();
1481 int irq = mProcessStats.getLastIrqTime();
1482 int softIrq = mProcessStats.getLastSoftIrqTime();
1483 int idle = mProcessStats.getLastIdleTime();
1484
1485 int total = user + system + iowait + irq + softIrq + idle;
1486 if (total == 0) total = 1;
1487
Doug Zongker2bec3d42009-12-04 12:52:44 -08001488 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 ((user+system+iowait+irq+softIrq) * 100) / total,
1490 (user * 100) / total,
1491 (system * 100) / total,
1492 (iowait * 100) / total,
1493 (irq * 100) / total,
1494 (softIrq * 100) / total);
1495 }
1496 }
1497
Amith Yamasanie43530a2009-08-21 13:11:37 -07001498 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001499 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001500 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 synchronized(mPidsSelfLocked) {
1502 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001503 if (mOnBattery) {
1504 int perc = bstats.startAddingCpuLocked();
1505 int totalUTime = 0;
1506 int totalSTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 final int N = mProcessStats.countWorkingStats();
1508 for (int i=0; i<N; i++) {
1509 ProcessStats.Stats st
1510 = mProcessStats.getWorkingStats(i);
1511 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001512 int otherUTime = (st.rel_utime*perc)/100;
1513 int otherSTime = (st.rel_stime*perc)/100;
1514 totalUTime += otherUTime;
1515 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 if (pr != null) {
1517 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001518 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1519 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001520 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001521 } else {
1522 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001523 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001524 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001525 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1526 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001527 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 }
1530 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001531 bstats.finishAddingCpuLocked(perc, totalUTime,
1532 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 }
1534 }
1535 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1538 mLastWriteTime = now;
1539 mBatteryStatsService.getActiveStatistics().writeLocked();
1540 }
1541 }
1542 }
1543 }
1544
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001545 @Override
1546 public void batteryNeedsCpuUpdate() {
1547 updateCpuStatsNow();
1548 }
1549
1550 @Override
1551 public void batteryPowerChanged(boolean onBattery) {
1552 // When plugging in, update the CPU stats first before changing
1553 // the plug state.
1554 updateCpuStatsNow();
1555 synchronized (this) {
1556 synchronized(mPidsSelfLocked) {
1557 mOnBattery = onBattery;
1558 }
1559 }
1560 }
1561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 /**
1563 * Initialize the application bind args. These are passed to each
1564 * process when the bindApplication() IPC is sent to the process. They're
1565 * lazily setup to make sure the services are running when they're asked for.
1566 */
1567 private HashMap<String, IBinder> getCommonServicesLocked() {
1568 if (mAppBindArgs == null) {
1569 mAppBindArgs = new HashMap<String, IBinder>();
1570
1571 // Setup the application init args
1572 mAppBindArgs.put("package", ServiceManager.getService("package"));
1573 mAppBindArgs.put("window", ServiceManager.getService("window"));
1574 mAppBindArgs.put(Context.ALARM_SERVICE,
1575 ServiceManager.getService(Context.ALARM_SERVICE));
1576 }
1577 return mAppBindArgs;
1578 }
1579
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001580 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 if (mFocusedActivity != r) {
1582 mFocusedActivity = r;
1583 mWindowManager.setFocusedApp(r, true);
1584 }
1585 }
1586
Dianne Hackborn906497c2010-05-10 15:57:38 -07001587 private final void updateLruProcessInternalLocked(ProcessRecord app,
1588 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001590 int lrui = mLruProcesses.indexOf(app);
1591 if (lrui >= 0) mLruProcesses.remove(lrui);
1592
1593 int i = mLruProcesses.size()-1;
1594 int skipTop = 0;
1595
Dianne Hackborn906497c2010-05-10 15:57:38 -07001596 app.lruSeq = mLruSeq;
1597
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001598 // compute the new weight for this process.
1599 if (updateActivityTime) {
1600 app.lastActivityTime = SystemClock.uptimeMillis();
1601 }
1602 if (app.activities.size() > 0) {
1603 // If this process has activities, we more strongly want to keep
1604 // it around.
1605 app.lruWeight = app.lastActivityTime;
1606 } else if (app.pubProviders.size() > 0) {
1607 // If this process contains content providers, we want to keep
1608 // it a little more strongly.
1609 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1610 // Also don't let it kick out the first few "real" hidden processes.
1611 skipTop = MIN_HIDDEN_APPS;
1612 } else {
1613 // If this process doesn't have activities, we less strongly
1614 // want to keep it around, and generally want to avoid getting
1615 // in front of any very recently used activities.
1616 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1617 // Also don't let it kick out the first few "real" hidden processes.
1618 skipTop = MIN_HIDDEN_APPS;
1619 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001620
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001621 while (i >= 0) {
1622 ProcessRecord p = mLruProcesses.get(i);
1623 // If this app shouldn't be in front of the first N background
1624 // apps, then skip over that many that are currently hidden.
1625 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1626 skipTop--;
1627 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001628 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001629 mLruProcesses.add(i+1, app);
1630 break;
1631 }
1632 i--;
1633 }
1634 if (i < 0) {
1635 mLruProcesses.add(0, app);
1636 }
1637
Dianne Hackborn906497c2010-05-10 15:57:38 -07001638 // If the app is currently using a content provider or service,
1639 // bump those processes as well.
1640 if (app.connections.size() > 0) {
1641 for (ConnectionRecord cr : app.connections) {
1642 if (cr.binding != null && cr.binding.service != null
1643 && cr.binding.service.app != null
1644 && cr.binding.service.app.lruSeq != mLruSeq) {
1645 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1646 updateActivityTime, i+1);
1647 }
1648 }
1649 }
1650 if (app.conProviders.size() > 0) {
1651 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1652 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1653 updateLruProcessInternalLocked(cpr.app, oomAdj,
1654 updateActivityTime, i+1);
1655 }
1656 }
1657 }
1658
Joe Onorato8a9b2202010-02-26 18:56:32 -08001659 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 if (oomAdj) {
1661 updateOomAdjLocked();
1662 }
1663 }
1664
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001665 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001666 boolean oomAdj, boolean updateActivityTime) {
1667 mLruSeq++;
1668 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1669 }
1670
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001671 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 String processName, int uid) {
1673 if (uid == Process.SYSTEM_UID) {
1674 // The system gets to run in any process. If there are multiple
1675 // processes with the same uid, just pick the first (this
1676 // should never happen).
1677 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1678 processName);
1679 return procs != null ? procs.valueAt(0) : null;
1680 }
1681 ProcessRecord proc = mProcessNames.get(processName, uid);
1682 return proc;
1683 }
1684
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001685 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001686 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001687 try {
1688 if (pm.performDexOpt(packageName)) {
1689 mDidDexOpt = true;
1690 }
1691 } catch (RemoteException e) {
1692 }
1693 }
1694
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001695 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 int transit = mWindowManager.getPendingAppTransition();
1697 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1698 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1699 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1700 }
1701
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001702 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001704 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1706 // We don't have to do anything more if:
1707 // (1) There is an existing application record; and
1708 // (2) The caller doesn't think it is dead, OR there is no thread
1709 // object attached to it so we know it couldn't have crashed; and
1710 // (3) There is a pid assigned to it, so it is either starting or
1711 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001712 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 + " app=" + app + " knownToBeDead=" + knownToBeDead
1714 + " thread=" + (app != null ? app.thread : null)
1715 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001716 if (app != null && app.pid > 0) {
1717 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001718 // We already have the app running, or are waiting for it to
1719 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001720 return app;
1721 } else {
1722 // An application record is attached to a previous process,
1723 // clean it up now.
1724 handleAppDiedLocked(app, true);
1725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 String hostingNameStr = hostingName != null
1729 ? hostingName.flattenToShortString() : null;
1730
1731 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1732 // If we are in the background, then check to see if this process
1733 // is bad. If so, we will just silently fail.
1734 if (mBadProcesses.get(info.processName, info.uid) != null) {
1735 return null;
1736 }
1737 } else {
1738 // When the user is explicitly starting a process, then clear its
1739 // crash count so that we won't make it bad until they see at
1740 // least one crash dialog again, and make the process good again
1741 // if it had been bad.
1742 mProcessCrashTimes.remove(info.processName, info.uid);
1743 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001744 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 info.processName);
1746 mBadProcesses.remove(info.processName, info.uid);
1747 if (app != null) {
1748 app.bad = false;
1749 }
1750 }
1751 }
1752
1753 if (app == null) {
1754 app = newProcessRecordLocked(null, info, processName);
1755 mProcessNames.put(processName, info.uid, app);
1756 } else {
1757 // If this is a new package in the process, add the package to the list
1758 app.addPackage(info.packageName);
1759 }
1760
1761 // If the system is not ready yet, then hold off on starting this
1762 // process until it is.
1763 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001764 && !isAllowedWhileBooting(info)
1765 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 if (!mProcessesOnHold.contains(app)) {
1767 mProcessesOnHold.add(app);
1768 }
1769 return app;
1770 }
1771
1772 startProcessLocked(app, hostingType, hostingNameStr);
1773 return (app.pid != 0) ? app : null;
1774 }
1775
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001776 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1777 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1778 }
1779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 private final void startProcessLocked(ProcessRecord app,
1781 String hostingType, String hostingNameStr) {
1782 if (app.pid > 0 && app.pid != MY_PID) {
1783 synchronized (mPidsSelfLocked) {
1784 mPidsSelfLocked.remove(app.pid);
1785 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1786 }
1787 app.pid = 0;
1788 }
1789
1790 mProcessesOnHold.remove(app);
1791
1792 updateCpuStats();
1793
1794 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1795 mProcDeaths[0] = 0;
1796
1797 try {
1798 int uid = app.info.uid;
1799 int[] gids = null;
1800 try {
1801 gids = mContext.getPackageManager().getPackageGids(
1802 app.info.packageName);
1803 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001804 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 }
1806 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1807 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1808 && mTopComponent != null
1809 && app.processName.equals(mTopComponent.getPackageName())) {
1810 uid = 0;
1811 }
1812 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1813 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1814 uid = 0;
1815 }
1816 }
1817 int debugFlags = 0;
1818 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1819 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1820 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001821 // Run the app in safe mode if its manifest requests so or the
1822 // system is booted in safe mode.
1823 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1824 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001825 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1826 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1828 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1829 }
1830 if ("1".equals(SystemProperties.get("debug.assert"))) {
1831 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1832 }
1833 int pid = Process.start("android.app.ActivityThread",
1834 mSimpleProcessManagement ? app.processName : null, uid, uid,
1835 gids, debugFlags, null);
1836 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1837 synchronized (bs) {
1838 if (bs.isOnBattery()) {
1839 app.batteryStats.incStartsLocked();
1840 }
1841 }
1842
Doug Zongker2bec3d42009-12-04 12:52:44 -08001843 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 app.processName, hostingType,
1845 hostingNameStr != null ? hostingNameStr : "");
1846
1847 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001848 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 }
1850
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001851 StringBuilder buf = mStringBuilder;
1852 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 buf.append("Start proc ");
1854 buf.append(app.processName);
1855 buf.append(" for ");
1856 buf.append(hostingType);
1857 if (hostingNameStr != null) {
1858 buf.append(" ");
1859 buf.append(hostingNameStr);
1860 }
1861 buf.append(": pid=");
1862 buf.append(pid);
1863 buf.append(" uid=");
1864 buf.append(uid);
1865 buf.append(" gids={");
1866 if (gids != null) {
1867 for (int gi=0; gi<gids.length; gi++) {
1868 if (gi != 0) buf.append(", ");
1869 buf.append(gids[gi]);
1870
1871 }
1872 }
1873 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001874 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875 if (pid == 0 || pid == MY_PID) {
1876 // Processes are being emulated with threads.
1877 app.pid = MY_PID;
1878 app.removed = false;
1879 mStartingProcesses.add(app);
1880 } else if (pid > 0) {
1881 app.pid = pid;
1882 app.removed = false;
1883 synchronized (mPidsSelfLocked) {
1884 this.mPidsSelfLocked.put(pid, app);
1885 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1886 msg.obj = app;
1887 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1888 }
1889 } else {
1890 app.pid = 0;
1891 RuntimeException e = new RuntimeException(
1892 "Failure starting process " + app.processName
1893 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001894 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 }
1896 } catch (RuntimeException e) {
1897 // XXX do better error recovery.
1898 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001899 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001900 }
1901 }
1902
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001903 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001904 if (resumed) {
1905 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1906 } else {
1907 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1908 }
1909 }
1910
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001911 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001912 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1913 && mTopAction == null) {
1914 // We are running in factory test mode, but unable to find
1915 // the factory test app, so just sit around displaying the
1916 // error message and don't try to start anything.
1917 return false;
1918 }
1919 Intent intent = new Intent(
1920 mTopAction,
1921 mTopData != null ? Uri.parse(mTopData) : null);
1922 intent.setComponent(mTopComponent);
1923 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1924 intent.addCategory(Intent.CATEGORY_HOME);
1925 }
1926 ActivityInfo aInfo =
1927 intent.resolveActivityInfo(mContext.getPackageManager(),
1928 STOCK_PM_FLAGS);
1929 if (aInfo != null) {
1930 intent.setComponent(new ComponentName(
1931 aInfo.applicationInfo.packageName, aInfo.name));
1932 // Don't do this if the home app is currently being
1933 // instrumented.
1934 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1935 aInfo.applicationInfo.uid);
1936 if (app == null || app.instrumentationClass == null) {
1937 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001938 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001939 null, null, 0, 0, 0, false, false);
1940 }
1941 }
1942
1943
1944 return true;
1945 }
1946
1947 /**
1948 * Starts the "new version setup screen" if appropriate.
1949 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001950 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001951 // Only do this once per boot.
1952 if (mCheckedForSetup) {
1953 return;
1954 }
1955
1956 // We will show this screen if the current one is a different
1957 // version than the last one shown, and we are not running in
1958 // low-level factory test mode.
1959 final ContentResolver resolver = mContext.getContentResolver();
1960 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1961 Settings.Secure.getInt(resolver,
1962 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1963 mCheckedForSetup = true;
1964
1965 // See if we should be showing the platform update setup UI.
1966 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1967 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1968 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1969
1970 // We don't allow third party apps to replace this.
1971 ResolveInfo ri = null;
1972 for (int i=0; ris != null && i<ris.size(); i++) {
1973 if ((ris.get(i).activityInfo.applicationInfo.flags
1974 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1975 ri = ris.get(i);
1976 break;
1977 }
1978 }
1979
1980 if (ri != null) {
1981 String vers = ri.activityInfo.metaData != null
1982 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1983 : null;
1984 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1985 vers = ri.activityInfo.applicationInfo.metaData.getString(
1986 Intent.METADATA_SETUP_VERSION);
1987 }
1988 String lastVers = Settings.Secure.getString(
1989 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1990 if (vers != null && !vers.equals(lastVers)) {
1991 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1992 intent.setComponent(new ComponentName(
1993 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001994 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001995 null, null, 0, 0, 0, false, false);
1996 }
1997 }
1998 }
1999 }
2000
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002001 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002002 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002003
2004 final int identHash = System.identityHashCode(r);
2005 updateUsageStats(r, true);
2006
2007 int i = mWatchers.beginBroadcast();
2008 while (i > 0) {
2009 i--;
2010 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2011 if (w != null) {
2012 try {
2013 w.activityResuming(identHash);
2014 } catch (RemoteException e) {
2015 }
2016 }
2017 }
2018 mWatchers.finishBroadcast();
2019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002021 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002022 final int N = mPendingActivityLaunches.size();
2023 if (N <= 0) {
2024 return;
2025 }
2026 for (int i=0; i<N; i++) {
2027 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002028 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002029 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2030 doResume && i == (N-1));
2031 }
2032 mPendingActivityLaunches.clear();
2033 }
2034
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002035 public final int startActivity(IApplicationThread caller,
2036 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2037 int grantedMode, IBinder resultTo,
2038 String resultWho, int requestCode, boolean onlyIfNeeded,
2039 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002040 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002041 grantedUriPermissions, grantedMode, resultTo, resultWho,
2042 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002043 }
2044
2045 public final WaitResult startActivityAndWait(IApplicationThread caller,
2046 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2047 int grantedMode, IBinder resultTo,
2048 String resultWho, int requestCode, boolean onlyIfNeeded,
2049 boolean debug) {
2050 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002051 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002052 grantedUriPermissions, grantedMode, resultTo, resultWho,
2053 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002054 return res;
2055 }
2056
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002057 public final int startActivityWithConfig(IApplicationThread caller,
2058 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2059 int grantedMode, IBinder resultTo,
2060 String resultWho, int requestCode, boolean onlyIfNeeded,
2061 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002062 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002063 grantedUriPermissions, grantedMode, resultTo, resultWho,
2064 requestCode, onlyIfNeeded, debug, null, config);
2065 }
2066
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002067 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002068 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002069 IBinder resultTo, String resultWho, int requestCode,
2070 int flagsMask, int flagsValues) {
2071 // Refuse possible leaked file descriptors
2072 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2073 throw new IllegalArgumentException("File descriptors passed in Intent");
2074 }
2075
2076 IIntentSender sender = intent.getTarget();
2077 if (!(sender instanceof PendingIntentRecord)) {
2078 throw new IllegalArgumentException("Bad PendingIntent object");
2079 }
2080
2081 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002082
2083 synchronized (this) {
2084 // If this is coming from the currently resumed activity, it is
2085 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002086 if (mMainStack.mResumedActivity != null
2087 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002088 Binder.getCallingUid()) {
2089 mAppSwitchesAllowedTime = 0;
2090 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002091 }
2092
2093 return pir.sendInner(0, fillInIntent, resolvedType,
2094 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2095 }
2096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 public boolean startNextMatchingActivity(IBinder callingActivity,
2098 Intent intent) {
2099 // Refuse possible leaked file descriptors
2100 if (intent != null && intent.hasFileDescriptors() == true) {
2101 throw new IllegalArgumentException("File descriptors passed in Intent");
2102 }
2103
2104 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002105 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002106 if (index < 0) {
2107 return false;
2108 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002109 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 if (r.app == null || r.app.thread == null) {
2111 // The caller is not running... d'oh!
2112 return false;
2113 }
2114 intent = new Intent(intent);
2115 // The caller is not allowed to change the data.
2116 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2117 // And we are resetting to find the next component...
2118 intent.setComponent(null);
2119
2120 ActivityInfo aInfo = null;
2121 try {
2122 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002123 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002125 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126
2127 // Look for the original activity in the list...
2128 final int N = resolves != null ? resolves.size() : 0;
2129 for (int i=0; i<N; i++) {
2130 ResolveInfo rInfo = resolves.get(i);
2131 if (rInfo.activityInfo.packageName.equals(r.packageName)
2132 && rInfo.activityInfo.name.equals(r.info.name)) {
2133 // We found the current one... the next matching is
2134 // after it.
2135 i++;
2136 if (i<N) {
2137 aInfo = resolves.get(i).activityInfo;
2138 }
2139 break;
2140 }
2141 }
2142 } catch (RemoteException e) {
2143 }
2144
2145 if (aInfo == null) {
2146 // Nobody who is next!
2147 return false;
2148 }
2149
2150 intent.setComponent(new ComponentName(
2151 aInfo.applicationInfo.packageName, aInfo.name));
2152 intent.setFlags(intent.getFlags()&~(
2153 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2154 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2155 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2156 Intent.FLAG_ACTIVITY_NEW_TASK));
2157
2158 // Okay now we need to start the new activity, replacing the
2159 // currently running activity. This is a little tricky because
2160 // we want to start the new one as if the current one is finished,
2161 // but not finish the current one first so that there is no flicker.
2162 // And thus...
2163 final boolean wasFinishing = r.finishing;
2164 r.finishing = true;
2165
2166 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002167 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168 final String resultWho = r.resultWho;
2169 final int requestCode = r.requestCode;
2170 r.resultTo = null;
2171 if (resultTo != null) {
2172 resultTo.removeResultsLocked(r, resultWho, requestCode);
2173 }
2174
2175 final long origId = Binder.clearCallingIdentity();
2176 // XXX we are not dealing with propagating grantedUriPermissions...
2177 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002178 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002180 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 Binder.restoreCallingIdentity(origId);
2182
2183 r.finishing = wasFinishing;
2184 if (res != START_SUCCESS) {
2185 return false;
2186 }
2187 return true;
2188 }
2189 }
2190
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002191 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 Intent intent, String resolvedType, IBinder resultTo,
2193 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002194
2195 // This is so super not safe, that only the system (or okay root)
2196 // can do it.
2197 final int callingUid = Binder.getCallingUid();
2198 if (callingUid != 0 && callingUid != Process.myUid()) {
2199 throw new SecurityException(
2200 "startActivityInPackage only available to the system");
2201 }
2202
The Android Open Source Project4df24232009-03-05 14:34:35 -08002203 final boolean componentSpecified = intent.getComponent() != null;
2204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205 // Don't modify the client's object!
2206 intent = new Intent(intent);
2207
2208 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002209 ActivityInfo aInfo;
2210 try {
2211 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002212 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002214 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 aInfo = rInfo != null ? rInfo.activityInfo : null;
2216 } catch (RemoteException e) {
2217 aInfo = null;
2218 }
2219
2220 if (aInfo != null) {
2221 // Store the found target back into the intent, because now that
2222 // we have it we never want to do this again. For example, if the
2223 // user navigates back to this point in the history, we should
2224 // always restart the exact same activity.
2225 intent.setComponent(new ComponentName(
2226 aInfo.applicationInfo.packageName, aInfo.name));
2227 }
2228
2229 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002230 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002232 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 }
2234 }
2235
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002236 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 // Remove any existing entries that are the same kind of task.
2238 int N = mRecentTasks.size();
2239 for (int i=0; i<N; i++) {
2240 TaskRecord tr = mRecentTasks.get(i);
2241 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2242 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2243 mRecentTasks.remove(i);
2244 i--;
2245 N--;
2246 if (task.intent == null) {
2247 // If the new recent task we are adding is not fully
2248 // specified, then replace it with the existing recent task.
2249 task = tr;
2250 }
2251 }
2252 }
2253 if (N >= MAX_RECENT_TASKS) {
2254 mRecentTasks.remove(N-1);
2255 }
2256 mRecentTasks.add(0, task);
2257 }
2258
2259 public void setRequestedOrientation(IBinder token,
2260 int requestedOrientation) {
2261 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002262 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263 if (index < 0) {
2264 return;
2265 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002266 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 final long origId = Binder.clearCallingIdentity();
2268 mWindowManager.setAppOrientation(r, requestedOrientation);
2269 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002270 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 r.mayFreezeScreenLocked(r.app) ? r : null);
2272 if (config != null) {
2273 r.frozenBeforeDestroy = true;
2274 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002275 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 }
2277 }
2278 Binder.restoreCallingIdentity(origId);
2279 }
2280 }
2281
2282 public int getRequestedOrientation(IBinder token) {
2283 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002284 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 if (index < 0) {
2286 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2287 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002288 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 return mWindowManager.getAppOrientation(r);
2290 }
2291 }
2292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 /**
2294 * This is the internal entry point for handling Activity.finish().
2295 *
2296 * @param token The Binder token referencing the Activity we want to finish.
2297 * @param resultCode Result code, if any, from this Activity.
2298 * @param resultData Result data (Intent), if any, from this Activity.
2299 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002300 * @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 -08002301 */
2302 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2303 // Refuse possible leaked file descriptors
2304 if (resultData != null && resultData.hasFileDescriptors() == true) {
2305 throw new IllegalArgumentException("File descriptors passed in Intent");
2306 }
2307
2308 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002309 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002310 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002311 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 if (next != null) {
2313 // ask watcher if this is allowed
2314 boolean resumeOK = true;
2315 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002316 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002318 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002319 }
2320
2321 if (!resumeOK) {
2322 return false;
2323 }
2324 }
2325 }
2326 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002327 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 resultData, "app-request");
2329 Binder.restoreCallingIdentity(origId);
2330 return res;
2331 }
2332 }
2333
Dianne Hackborn860755f2010-06-03 18:47:52 -07002334 public final void finishHeavyWeightApp() {
2335 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2336 != PackageManager.PERMISSION_GRANTED) {
2337 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2338 + Binder.getCallingPid()
2339 + ", uid=" + Binder.getCallingUid()
2340 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2341 Slog.w(TAG, msg);
2342 throw new SecurityException(msg);
2343 }
2344
2345 synchronized(this) {
2346 if (mHeavyWeightProcess == null) {
2347 return;
2348 }
2349
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002350 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002351 mHeavyWeightProcess.activities);
2352 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002353 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002354 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002355 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002356 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002357 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002358 null, "finish-heavy");
2359 }
2360 }
2361 }
2362
2363 mHeavyWeightProcess = null;
2364 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2365 }
2366 }
2367
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002368 public void crashApplication(int uid, int initialPid, String packageName,
2369 String message) {
2370 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2371 != PackageManager.PERMISSION_GRANTED) {
2372 String msg = "Permission Denial: crashApplication() from pid="
2373 + Binder.getCallingPid()
2374 + ", uid=" + Binder.getCallingUid()
2375 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2376 Slog.w(TAG, msg);
2377 throw new SecurityException(msg);
2378 }
2379
2380 synchronized(this) {
2381 ProcessRecord proc = null;
2382
2383 // Figure out which process to kill. We don't trust that initialPid
2384 // still has any relation to current pids, so must scan through the
2385 // list.
2386 synchronized (mPidsSelfLocked) {
2387 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2388 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2389 if (p.info.uid != uid) {
2390 continue;
2391 }
2392 if (p.pid == initialPid) {
2393 proc = p;
2394 break;
2395 }
2396 for (String str : p.pkgList) {
2397 if (str.equals(packageName)) {
2398 proc = p;
2399 }
2400 }
2401 }
2402 }
2403
2404 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002405 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002406 + " initialPid=" + initialPid
2407 + " packageName=" + packageName);
2408 return;
2409 }
2410
2411 if (proc.thread != null) {
2412 long ident = Binder.clearCallingIdentity();
2413 try {
2414 proc.thread.scheduleCrash(message);
2415 } catch (RemoteException e) {
2416 }
2417 Binder.restoreCallingIdentity(ident);
2418 }
2419 }
2420 }
2421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 public final void finishSubActivity(IBinder token, String resultWho,
2423 int requestCode) {
2424 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002425 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 if (index < 0) {
2427 return;
2428 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002429 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002430
2431 final long origId = Binder.clearCallingIdentity();
2432
2433 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002434 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2435 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 if (r.resultTo == self && r.requestCode == requestCode) {
2437 if ((r.resultWho == null && resultWho == null) ||
2438 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002439 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002440 Activity.RESULT_CANCELED, null, "request-sub");
2441 }
2442 }
2443 }
2444
2445 Binder.restoreCallingIdentity(origId);
2446 }
2447 }
2448
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002449 public boolean willActivityBeVisible(IBinder token) {
2450 synchronized(this) {
2451 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002452 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2453 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002454 if (r == token) {
2455 return true;
2456 }
2457 if (r.fullscreen && !r.finishing) {
2458 return false;
2459 }
2460 }
2461 return true;
2462 }
2463 }
2464
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002465 public void overridePendingTransition(IBinder token, String packageName,
2466 int enterAnim, int exitAnim) {
2467 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002468 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002469 if (index < 0) {
2470 return;
2471 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002472 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002473
2474 final long origId = Binder.clearCallingIdentity();
2475
2476 if (self.state == ActivityState.RESUMED
2477 || self.state == ActivityState.PAUSING) {
2478 mWindowManager.overridePendingAppTransition(packageName,
2479 enterAnim, exitAnim);
2480 }
2481
2482 Binder.restoreCallingIdentity(origId);
2483 }
2484 }
2485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002487 * Main function for removing an existing process from the activity manager
2488 * as a result of that process going away. Clears out all connections
2489 * to the process.
2490 */
2491 private final void handleAppDiedLocked(ProcessRecord app,
2492 boolean restarting) {
2493 cleanUpApplicationRecordLocked(app, restarting, -1);
2494 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002495 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496 }
2497
2498 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002499 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2500 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2501 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002503 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2504 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 }
2506
2507 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002508 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509
2510 boolean atTop = true;
2511 boolean hasVisibleActivities = false;
2512
2513 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002514 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002515 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 TAG, "Removing app " + app + " from history with " + i + " entries");
2517 while (i > 0) {
2518 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002519 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002520 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2522 if (r.app == app) {
2523 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002524 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 TAG, "Removing this entry! frozen=" + r.haveState
2526 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002527 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528
2529 r.inHistory = false;
2530 mWindowManager.removeAppToken(r);
2531 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002532 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002534 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535
2536 } else {
2537 // We have the current state for this activity, so
2538 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002539 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 TAG, "Keeping entry, setting app to null");
2541 if (r.visible) {
2542 hasVisibleActivities = true;
2543 }
2544 r.app = null;
2545 r.nowVisible = false;
2546 if (!r.haveState) {
2547 r.icicle = null;
2548 }
2549 }
2550
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002551 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 r.state = ActivityState.STOPPED;
2553 }
2554 atTop = false;
2555 }
2556
2557 app.activities.clear();
2558
2559 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002560 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 + " running instrumentation " + app.instrumentationClass);
2562 Bundle info = new Bundle();
2563 info.putString("shortMsg", "Process crashed.");
2564 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2565 }
2566
2567 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002568 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 // If there was nothing to resume, and we are not already
2570 // restarting this process, but there is a visible activity that
2571 // is hosted by the process... then make sure all visible
2572 // activities are running, taking care of restarting this
2573 // process.
2574 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002575 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 }
2577 }
2578 }
2579 }
2580
2581 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2582 IBinder threadBinder = thread.asBinder();
2583
2584 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002585 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2586 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2588 return i;
2589 }
2590 }
2591 return -1;
2592 }
2593
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002594 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 IApplicationThread thread) {
2596 if (thread == null) {
2597 return null;
2598 }
2599
2600 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002601 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002602 }
2603
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002604 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 IApplicationThread thread) {
2606
2607 mProcDeaths[0]++;
2608
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002609 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2610 synchronized (stats) {
2611 stats.noteProcessDiedLocked(app.info.uid, pid);
2612 }
2613
Magnus Edlund7bb25812010-02-24 15:45:06 +01002614 // Clean up already done if the process has been re-started.
2615 if (app.pid == pid && app.thread != null &&
2616 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002617 if (!app.killedBackground) {
2618 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2619 + ") has died.");
2620 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002621 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002622 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 TAG, "Dying app: " + app + ", pid: " + pid
2624 + ", thread: " + thread.asBinder());
2625 boolean doLowMem = app.instrumentationClass == null;
2626 handleAppDiedLocked(app, false);
2627
2628 if (doLowMem) {
2629 // If there are no longer any background processes running,
2630 // and the app that died was not running instrumentation,
2631 // then tell everyone we are now low on memory.
2632 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002633 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2634 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2636 haveBg = true;
2637 break;
2638 }
2639 }
2640
2641 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002642 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002643 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002644 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002645 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2646 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002647 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002648 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2649 // The low memory report is overriding any current
2650 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002651 // heavy/important/visible/foreground processes first.
2652 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002653 rec.lastRequestedGc = 0;
2654 } else {
2655 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002656 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002657 rec.reportLowMemory = true;
2658 rec.lastLowMemory = now;
2659 mProcessesToGc.remove(rec);
2660 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 }
2662 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002663 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 }
2665 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002666 } else if (app.pid != pid) {
2667 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002668 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002669 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002670 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002671 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002672 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002673 + thread.asBinder());
2674 }
2675 }
2676
Dan Egnor42471dd2010-01-07 17:25:22 -08002677 /**
2678 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002679 * @param clearTraces causes the dump file to be erased prior to the new
2680 * traces being written, if true; when false, the new traces will be
2681 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002682 * @param firstPids of dalvik VM processes to dump stack traces for first
2683 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002684 * @return file containing stack traces, or null if no dump file is configured
2685 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002686 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2687 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002688 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2689 if (tracesPath == null || tracesPath.length() == 0) {
2690 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002692
2693 File tracesFile = new File(tracesPath);
2694 try {
2695 File tracesDir = tracesFile.getParentFile();
2696 if (!tracesDir.exists()) tracesFile.mkdirs();
2697 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2698
Christopher Tate6ee412d2010-05-28 12:01:56 -07002699 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002700 tracesFile.createNewFile();
2701 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2702 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002703 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002704 return null;
2705 }
2706
2707 // Use a FileObserver to detect when traces finish writing.
2708 // The order of traces is considered important to maintain for legibility.
2709 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2710 public synchronized void onEvent(int event, String path) { notify(); }
2711 };
2712
2713 try {
2714 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002715
2716 // First collect all of the stacks of the most important pids.
2717 try {
2718 int num = firstPids.size();
2719 for (int i = 0; i < num; i++) {
2720 synchronized (observer) {
2721 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2722 observer.wait(200); // Wait for write-close, give up after 200msec
2723 }
2724 }
2725 } catch (InterruptedException e) {
2726 Log.wtf(TAG, e);
2727 }
2728
2729 // Next measure CPU usage.
2730 if (processStats != null) {
2731 processStats.init();
2732 System.gc();
2733 processStats.update();
2734 try {
2735 synchronized (processStats) {
2736 processStats.wait(500); // measure over 1/2 second.
2737 }
2738 } catch (InterruptedException e) {
2739 }
2740 processStats.update();
2741
2742 // We'll take the stack crawls of just the top apps using CPU.
2743 final int N = processStats.countWorkingStats();
2744 int numProcs = 0;
2745 for (int i=0; i<N && numProcs<5; i++) {
2746 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2747 if (lastPids.indexOfKey(stats.pid) >= 0) {
2748 numProcs++;
2749 try {
2750 synchronized (observer) {
2751 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2752 observer.wait(200); // Wait for write-close, give up after 200msec
2753 }
2754 } catch (InterruptedException e) {
2755 Log.wtf(TAG, e);
2756 }
2757
2758 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002759 }
2760 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002761
2762 return tracesFile;
2763
Dan Egnor42471dd2010-01-07 17:25:22 -08002764 } finally {
2765 observer.stopWatching();
2766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 }
2768
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002769 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2770 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002771 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2772 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2773
2774 long anrTime = SystemClock.uptimeMillis();
2775 if (MONITOR_CPU_USAGE) {
2776 updateCpuStatsNow();
2777 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002778
2779 synchronized (this) {
2780 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2781 if (mShuttingDown) {
2782 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2783 return;
2784 } else if (app.notResponding) {
2785 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2786 return;
2787 } else if (app.crashing) {
2788 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2789 return;
2790 }
2791
2792 // In case we come through here for the same app before completing
2793 // this one, mark as anring now so we will bail out.
2794 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002795
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002796 // Log the ANR to the event log.
2797 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2798 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002799
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002800 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002801 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002802
2803 int parentPid = app.pid;
2804 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002805 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002806
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002807 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002808
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002809 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2810 ProcessRecord r = mLruProcesses.get(i);
2811 if (r != null && r.thread != null) {
2812 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002813 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2814 if (r.persistent) {
2815 firstPids.add(pid);
2816 } else {
2817 lastPids.put(pid, Boolean.TRUE);
2818 }
2819 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002820 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002821 }
2822 }
2823
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002824 final ProcessStats processStats = new ProcessStats(true);
2825
2826 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002827
2828 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002829 StringBuilder info = mStringBuilder;
2830 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002831 info.append("ANR in ").append(app.processName);
2832 if (activity != null && activity.shortComponentName != null) {
2833 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002834 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002835 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002837 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002838 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002839 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002840 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002842
Dan Egnor42471dd2010-01-07 17:25:22 -08002843 String cpuInfo = null;
2844 if (MONITOR_CPU_USAGE) {
2845 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002846 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002847 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002848 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002849 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002850 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 }
2852
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002853 info.append(processStats.printCurrentState(anrTime));
2854
Joe Onorato8a9b2202010-02-26 18:56:32 -08002855 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002856 if (tracesFile == null) {
2857 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2858 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2859 }
2860
2861 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2862
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002863 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002865 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2866 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002867 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002868 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2869 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002870 }
2871 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002872 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002873 }
2874 }
2875
Dan Egnor42471dd2010-01-07 17:25:22 -08002876 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2877 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2878 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002879
2880 synchronized (this) {
2881 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2882 Process.killProcess(app.pid);
2883 return;
2884 }
2885
2886 // Set the app's notResponding state, and look up the errorReportReceiver
2887 makeAppNotRespondingLocked(app,
2888 activity != null ? activity.shortComponentName : null,
2889 annotation != null ? "ANR " + annotation : "ANR",
2890 info.toString());
2891
2892 // Bring up the infamous App Not Responding dialog
2893 Message msg = Message.obtain();
2894 HashMap map = new HashMap();
2895 msg.what = SHOW_NOT_RESPONDING_MSG;
2896 msg.obj = map;
2897 map.put("app", app);
2898 if (activity != null) {
2899 map.put("activity", activity);
2900 }
2901
2902 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904 }
2905
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002906 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2907 if (!mLaunchWarningShown) {
2908 mLaunchWarningShown = true;
2909 mHandler.post(new Runnable() {
2910 @Override
2911 public void run() {
2912 synchronized (ActivityManagerService.this) {
2913 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2914 d.show();
2915 mHandler.postDelayed(new Runnable() {
2916 @Override
2917 public void run() {
2918 synchronized (ActivityManagerService.this) {
2919 d.dismiss();
2920 mLaunchWarningShown = false;
2921 }
2922 }
2923 }, 4000);
2924 }
2925 }
2926 });
2927 }
2928 }
2929
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002930 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931 app.persistentActivities--;
2932 if (app.persistentActivities > 0) {
2933 // Still more of 'em...
2934 return;
2935 }
2936 if (app.persistent) {
2937 // Ah, but the application itself is persistent. Whatever!
2938 return;
2939 }
2940
2941 // App is no longer persistent... make sure it and the ones
2942 // following it in the LRU list have the correc oom_adj.
2943 updateOomAdjLocked();
2944 }
2945
2946 public void setPersistent(IBinder token, boolean isPersistent) {
2947 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2948 != PackageManager.PERMISSION_GRANTED) {
2949 String msg = "Permission Denial: setPersistent() from pid="
2950 + Binder.getCallingPid()
2951 + ", uid=" + Binder.getCallingUid()
2952 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002953 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 throw new SecurityException(msg);
2955 }
2956
2957 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002958 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 if (index < 0) {
2960 return;
2961 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002962 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 ProcessRecord app = r.app;
2964
Joe Onorato8a9b2202010-02-26 18:56:32 -08002965 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002966 TAG, "Setting persistence " + isPersistent + ": " + r);
2967
2968 if (isPersistent) {
2969 if (r.persistent) {
2970 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002971 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 return;
2973 }
2974 r.persistent = true;
2975 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002976 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 if (app.persistentActivities > 1) {
2978 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002979 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 return;
2981 }
2982 if (app.persistent) {
2983 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002984 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 return;
2986 }
2987
2988 // App is now persistent... make sure it and the ones
2989 // following it now have the correct oom_adj.
2990 final long origId = Binder.clearCallingIdentity();
2991 updateOomAdjLocked();
2992 Binder.restoreCallingIdentity(origId);
2993
2994 } else {
2995 if (!r.persistent) {
2996 // Okay okay, I heard you already!
2997 return;
2998 }
2999 r.persistent = false;
3000 final long origId = Binder.clearCallingIdentity();
3001 decPersistentCountLocked(app);
3002 Binder.restoreCallingIdentity(origId);
3003
3004 }
3005 }
3006 }
3007
3008 public boolean clearApplicationUserData(final String packageName,
3009 final IPackageDataObserver observer) {
3010 int uid = Binder.getCallingUid();
3011 int pid = Binder.getCallingPid();
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 false;
3024 }
3025 if (uid == pkgUid || checkComponentPermission(
3026 android.Manifest.permission.CLEAR_APP_USER_DATA,
3027 pid, uid, -1)
3028 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003029 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 } else {
3031 throw new SecurityException(pid+" does not have permission:"+
3032 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3033 "for process:"+packageName);
3034 }
3035 }
3036
3037 try {
3038 //clear application user data
3039 pm.clearApplicationUserData(packageName, observer);
3040 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3041 Uri.fromParts("package", packageName, null));
3042 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06003043 synchronized (this) {
3044 broadcastIntentLocked(null, null, intent,
3045 null, null, 0, null, null, null,
3046 false, false, MY_PID, Process.SYSTEM_UID);
3047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 } catch (RemoteException e) {
3049 }
3050 } finally {
3051 Binder.restoreCallingIdentity(callingId);
3052 }
3053 return true;
3054 }
3055
Dianne Hackborn03abb812010-01-04 18:43:19 -08003056 public void killBackgroundProcesses(final String packageName) {
3057 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3058 != PackageManager.PERMISSION_GRANTED &&
3059 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3060 != PackageManager.PERMISSION_GRANTED) {
3061 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 + Binder.getCallingPid()
3063 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003064 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003065 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 throw new SecurityException(msg);
3067 }
3068
3069 long callingId = Binder.clearCallingIdentity();
3070 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003071 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 int pkgUid = -1;
3073 synchronized(this) {
3074 try {
3075 pkgUid = pm.getPackageUid(packageName);
3076 } catch (RemoteException e) {
3077 }
3078 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003079 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 return;
3081 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003082 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003083 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003084 }
3085 } finally {
3086 Binder.restoreCallingIdentity(callingId);
3087 }
3088 }
3089
3090 public void forceStopPackage(final String packageName) {
3091 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3092 != PackageManager.PERMISSION_GRANTED) {
3093 String msg = "Permission Denial: forceStopPackage() from pid="
3094 + Binder.getCallingPid()
3095 + ", uid=" + Binder.getCallingUid()
3096 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003097 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003098 throw new SecurityException(msg);
3099 }
3100
3101 long callingId = Binder.clearCallingIdentity();
3102 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003103 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003104 int pkgUid = -1;
3105 synchronized(this) {
3106 try {
3107 pkgUid = pm.getPackageUid(packageName);
3108 } catch (RemoteException e) {
3109 }
3110 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003111 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003112 return;
3113 }
3114 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 }
3116 } finally {
3117 Binder.restoreCallingIdentity(callingId);
3118 }
3119 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003120
3121 /*
3122 * The pkg name and uid have to be specified.
3123 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3124 */
3125 public void killApplicationWithUid(String pkg, int uid) {
3126 if (pkg == null) {
3127 return;
3128 }
3129 // Make sure the uid is valid.
3130 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003131 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003132 return;
3133 }
3134 int callerUid = Binder.getCallingUid();
3135 // Only the system server can kill an application
3136 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003137 // Post an aysnc message to kill the application
3138 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3139 msg.arg1 = uid;
3140 msg.arg2 = 0;
3141 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003142 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003143 } else {
3144 throw new SecurityException(callerUid + " cannot kill pkg: " +
3145 pkg);
3146 }
3147 }
3148
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003149 public void closeSystemDialogs(String reason) {
3150 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3151 if (reason != null) {
3152 intent.putExtra("reason", reason);
3153 }
3154
3155 final int uid = Binder.getCallingUid();
3156 final long origId = Binder.clearCallingIdentity();
3157 synchronized (this) {
3158 int i = mWatchers.beginBroadcast();
3159 while (i > 0) {
3160 i--;
3161 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3162 if (w != null) {
3163 try {
3164 w.closingSystemDialogs(reason);
3165 } catch (RemoteException e) {
3166 }
3167 }
3168 }
3169 mWatchers.finishBroadcast();
3170
Dianne Hackbornffa42482009-09-23 22:20:11 -07003171 mWindowManager.closeSystemDialogs(reason);
3172
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003173 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3174 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003175 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003176 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003177 Activity.RESULT_CANCELED, null, "close-sys");
3178 }
3179 }
3180
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003181 broadcastIntentLocked(null, null, intent, null,
3182 null, 0, null, null, null, false, false, -1, uid);
3183 }
3184 Binder.restoreCallingIdentity(origId);
3185 }
3186
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003187 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003188 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003189 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3190 for (int i=pids.length-1; i>=0; i--) {
3191 infos[i] = new Debug.MemoryInfo();
3192 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003193 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003194 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003195 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003196
3197 public void killApplicationProcess(String processName, int uid) {
3198 if (processName == null) {
3199 return;
3200 }
3201
3202 int callerUid = Binder.getCallingUid();
3203 // Only the system server can kill an application
3204 if (callerUid == Process.SYSTEM_UID) {
3205 synchronized (this) {
3206 ProcessRecord app = getProcessRecordLocked(processName, uid);
3207 if (app != null) {
3208 try {
3209 app.thread.scheduleSuicide();
3210 } catch (RemoteException e) {
3211 // If the other end already died, then our work here is done.
3212 }
3213 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003214 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003215 + processName + " / " + uid);
3216 }
3217 }
3218 } else {
3219 throw new SecurityException(callerUid + " cannot kill app process: " +
3220 processName);
3221 }
3222 }
3223
Dianne Hackborn03abb812010-01-04 18:43:19 -08003224 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003225 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3227 Uri.fromParts("package", packageName, null));
3228 intent.putExtra(Intent.EXTRA_UID, uid);
3229 broadcastIntentLocked(null, null, intent,
3230 null, null, 0, null, null, null,
3231 false, false, MY_PID, Process.SYSTEM_UID);
3232 }
3233
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003234 private final boolean killPackageProcessesLocked(String packageName, int uid,
3235 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003236 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237
Dianne Hackborn03abb812010-01-04 18:43:19 -08003238 // Remove all processes this package may have touched: all with the
3239 // same UID (except for the system or root user), and all whose name
3240 // matches the package name.
3241 final String procNamePrefix = packageName + ":";
3242 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3243 final int NA = apps.size();
3244 for (int ia=0; ia<NA; ia++) {
3245 ProcessRecord app = apps.valueAt(ia);
3246 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003247 if (doit) {
3248 procs.add(app);
3249 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003250 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3251 || app.processName.equals(packageName)
3252 || app.processName.startsWith(procNamePrefix)) {
3253 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003254 if (!doit) {
3255 return true;
3256 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003257 app.removed = true;
3258 procs.add(app);
3259 }
3260 }
3261 }
3262 }
3263
3264 int N = procs.size();
3265 for (int i=0; i<N; i++) {
3266 removeProcessLocked(procs.get(i), callerWillRestart);
3267 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003268 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003269 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003270
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003271 private final boolean forceStopPackageLocked(String name, int uid,
3272 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273 int i, N;
3274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003275 if (uid < 0) {
3276 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003277 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 } catch (RemoteException e) {
3279 }
3280 }
3281
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003282 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003283 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003284
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003285 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3286 while (badApps.hasNext()) {
3287 SparseArray<Long> ba = badApps.next();
3288 if (ba.get(uid) != null) {
3289 badApps.remove();
3290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003291 }
3292 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003293
3294 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3295 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003297 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3298 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003300 if (!doit) {
3301 return true;
3302 }
3303 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003304 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 if (r.app != null) {
3306 r.app.removed = true;
3307 }
3308 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003309 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 }
3311 }
3312
3313 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3314 for (ServiceRecord service : mServices.values()) {
3315 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003316 if (!doit) {
3317 return true;
3318 }
3319 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003320 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003321 if (service.app != null) {
3322 service.app.removed = true;
3323 }
3324 service.app = null;
3325 services.add(service);
3326 }
3327 }
3328
3329 N = services.size();
3330 for (i=0; i<N; i++) {
3331 bringDownServiceLocked(services.get(i), true);
3332 }
3333
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003334 if (doit) {
3335 if (purgeCache) {
3336 AttributeCache ac = AttributeCache.instance();
3337 if (ac != null) {
3338 ac.removePackage(name);
3339 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003340 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003341 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003342 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003343
3344 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 }
3346
3347 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3348 final String name = app.processName;
3349 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003350 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 TAG, "Force removing process " + app + " (" + name
3352 + "/" + uid + ")");
3353
3354 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003355 if (mHeavyWeightProcess == app) {
3356 mHeavyWeightProcess = null;
3357 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 boolean needRestart = false;
3360 if (app.pid > 0 && app.pid != MY_PID) {
3361 int pid = app.pid;
3362 synchronized (mPidsSelfLocked) {
3363 mPidsSelfLocked.remove(pid);
3364 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3365 }
3366 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003367 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 Process.killProcess(pid);
3369
3370 if (app.persistent) {
3371 if (!callerWillRestart) {
3372 addAppLocked(app.info);
3373 } else {
3374 needRestart = true;
3375 }
3376 }
3377 } else {
3378 mRemovedProcesses.add(app);
3379 }
3380
3381 return needRestart;
3382 }
3383
3384 private final void processStartTimedOutLocked(ProcessRecord app) {
3385 final int pid = app.pid;
3386 boolean gone = false;
3387 synchronized (mPidsSelfLocked) {
3388 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3389 if (knownApp != null && knownApp.thread == null) {
3390 mPidsSelfLocked.remove(pid);
3391 gone = true;
3392 }
3393 }
3394
3395 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003396 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003397 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003398 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003399 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003400 if (mHeavyWeightProcess == app) {
3401 mHeavyWeightProcess = null;
3402 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3403 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003404 // Take care of any launching providers waiting for this process.
3405 checkAppInLaunchingProvidersLocked(app, true);
3406 // Take care of any services that are waiting for the process.
3407 for (int i=0; i<mPendingServices.size(); i++) {
3408 ServiceRecord sr = mPendingServices.get(i);
3409 if (app.info.uid == sr.appInfo.uid
3410 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003411 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003412 mPendingServices.remove(i);
3413 i--;
3414 bringDownServiceLocked(sr, true);
3415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003416 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003417 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003418 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003419 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003420 try {
3421 IBackupManager bm = IBackupManager.Stub.asInterface(
3422 ServiceManager.getService(Context.BACKUP_SERVICE));
3423 bm.agentDisconnected(app.info.packageName);
3424 } catch (RemoteException e) {
3425 // Can't happen; the backup manager is local
3426 }
3427 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003428 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003429 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003430 mPendingBroadcast = null;
3431 scheduleBroadcastsLocked();
3432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003434 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 }
3436 }
3437
3438 private final boolean attachApplicationLocked(IApplicationThread thread,
3439 int pid) {
3440
3441 // Find the application record that is being attached... either via
3442 // the pid if we are running in multiple processes, or just pull the
3443 // next app record if we are emulating process with anonymous threads.
3444 ProcessRecord app;
3445 if (pid != MY_PID && pid >= 0) {
3446 synchronized (mPidsSelfLocked) {
3447 app = mPidsSelfLocked.get(pid);
3448 }
3449 } else if (mStartingProcesses.size() > 0) {
3450 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003451 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 } else {
3453 app = null;
3454 }
3455
3456 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003457 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003458 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003459 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 if (pid > 0 && pid != MY_PID) {
3461 Process.killProcess(pid);
3462 } else {
3463 try {
3464 thread.scheduleExit();
3465 } catch (Exception e) {
3466 // Ignore exceptions.
3467 }
3468 }
3469 return false;
3470 }
3471
3472 // If this application record is still attached to a previous
3473 // process, clean it up now.
3474 if (app.thread != null) {
3475 handleAppDiedLocked(app, true);
3476 }
3477
3478 // Tell the process all about itself.
3479
Joe Onorato8a9b2202010-02-26 18:56:32 -08003480 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 TAG, "Binding process pid " + pid + " to record " + app);
3482
3483 String processName = app.processName;
3484 try {
3485 thread.asBinder().linkToDeath(new AppDeathRecipient(
3486 app, pid, thread), 0);
3487 } catch (RemoteException e) {
3488 app.resetPackageList();
3489 startProcessLocked(app, "link fail", processName);
3490 return false;
3491 }
3492
Doug Zongker2bec3d42009-12-04 12:52:44 -08003493 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494
3495 app.thread = thread;
3496 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003497 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3498 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499 app.forcingToForeground = null;
3500 app.foregroundServices = false;
3501 app.debugging = false;
3502
3503 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3504
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003505 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3506 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003508 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003509 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003510 }
3511
Joe Onorato8a9b2202010-02-26 18:56:32 -08003512 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 TAG, "New app record " + app
3514 + " thread=" + thread.asBinder() + " pid=" + pid);
3515 try {
3516 int testMode = IApplicationThread.DEBUG_OFF;
3517 if (mDebugApp != null && mDebugApp.equals(processName)) {
3518 testMode = mWaitForDebugger
3519 ? IApplicationThread.DEBUG_WAIT
3520 : IApplicationThread.DEBUG_ON;
3521 app.debugging = true;
3522 if (mDebugTransient) {
3523 mDebugApp = mOrigDebugApp;
3524 mWaitForDebugger = mOrigWaitForDebugger;
3525 }
3526 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003527
Christopher Tate181fafa2009-05-14 11:12:14 -07003528 // If the app is being launched for restore or full backup, set it up specially
3529 boolean isRestrictedBackupMode = false;
3530 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3531 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3532 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3533 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003534
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003535 ensurePackageDexOpt(app.instrumentationInfo != null
3536 ? app.instrumentationInfo.packageName
3537 : app.info.packageName);
3538 if (app.instrumentationClass != null) {
3539 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003540 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003541 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003542 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003543 thread.bindApplication(processName, app.instrumentationInfo != null
3544 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 app.instrumentationClass, app.instrumentationProfileFile,
3546 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003547 isRestrictedBackupMode || !normalMode,
3548 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003549 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003550 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 } catch (Exception e) {
3552 // todo: Yikes! What should we do? For now we will try to
3553 // start another process, but that could easily get us in
3554 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003555 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556
3557 app.resetPackageList();
3558 startProcessLocked(app, "bind fail", processName);
3559 return false;
3560 }
3561
3562 // Remove this record from the list of starting applications.
3563 mPersistentStartingProcesses.remove(app);
3564 mProcessesOnHold.remove(app);
3565
3566 boolean badApp = false;
3567 boolean didSomething = false;
3568
3569 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003570 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003571 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3573 && processName.equals(hr.processName)) {
3574 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003575 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003576 didSomething = true;
3577 }
3578 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003579 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 + hr.intent.getComponent().flattenToShortString(), e);
3581 badApp = true;
3582 }
3583 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003584 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003585 }
3586 }
3587
3588 // Find any services that should be running in this process...
3589 if (!badApp && mPendingServices.size() > 0) {
3590 ServiceRecord sr = null;
3591 try {
3592 for (int i=0; i<mPendingServices.size(); i++) {
3593 sr = mPendingServices.get(i);
3594 if (app.info.uid != sr.appInfo.uid
3595 || !processName.equals(sr.processName)) {
3596 continue;
3597 }
3598
3599 mPendingServices.remove(i);
3600 i--;
3601 realStartServiceLocked(sr, app);
3602 didSomething = true;
3603 }
3604 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003605 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003606 + sr.shortName, e);
3607 badApp = true;
3608 }
3609 }
3610
3611 // Check if the next broadcast receiver is in this process...
3612 BroadcastRecord br = mPendingBroadcast;
3613 if (!badApp && br != null && br.curApp == app) {
3614 try {
3615 mPendingBroadcast = null;
3616 processCurBroadcastLocked(br, app);
3617 didSomething = true;
3618 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003619 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 + br.curComponent.flattenToShortString(), e);
3621 badApp = true;
3622 logBroadcastReceiverDiscard(br);
3623 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3624 br.resultExtras, br.resultAbort, true);
3625 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003626 // We need to reset the state if we fails to start the receiver.
3627 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 }
3629 }
3630
Christopher Tate181fafa2009-05-14 11:12:14 -07003631 // Check whether the next backup agent is in this process...
3632 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003633 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003634 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003635 try {
3636 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3637 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003638 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003639 e.printStackTrace();
3640 }
3641 }
3642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643 if (badApp) {
3644 // todo: Also need to kill application to deal with all
3645 // kinds of exceptions.
3646 handleAppDiedLocked(app, false);
3647 return false;
3648 }
3649
3650 if (!didSomething) {
3651 updateOomAdjLocked();
3652 }
3653
3654 return true;
3655 }
3656
3657 public final void attachApplication(IApplicationThread thread) {
3658 synchronized (this) {
3659 int callingPid = Binder.getCallingPid();
3660 final long origId = Binder.clearCallingIdentity();
3661 attachApplicationLocked(thread, callingPid);
3662 Binder.restoreCallingIdentity(origId);
3663 }
3664 }
3665
Dianne Hackborne88846e2009-09-30 21:34:25 -07003666 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003668 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 Binder.restoreCallingIdentity(origId);
3670 }
3671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003673 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003674 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 mWindowManager.enableScreenAfterBoot();
3676 }
3677
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003678 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003679 IntentFilter pkgFilter = new IntentFilter();
3680 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3681 pkgFilter.addDataScheme("package");
3682 mContext.registerReceiver(new BroadcastReceiver() {
3683 @Override
3684 public void onReceive(Context context, Intent intent) {
3685 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3686 if (pkgs != null) {
3687 for (String pkg : pkgs) {
3688 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3689 setResultCode(Activity.RESULT_OK);
3690 return;
3691 }
3692 }
3693 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003694 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003695 }, pkgFilter);
3696
3697 synchronized (this) {
3698 // Ensure that any processes we had put on hold are now started
3699 // up.
3700 final int NP = mProcessesOnHold.size();
3701 if (NP > 0) {
3702 ArrayList<ProcessRecord> procs =
3703 new ArrayList<ProcessRecord>(mProcessesOnHold);
3704 for (int ip=0; ip<NP; ip++) {
3705 this.startProcessLocked(procs.get(ip), "on-hold", null);
3706 }
3707 }
3708
3709 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003710 // Start looking for apps that are abusing wake locks.
3711 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
3712 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003713 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003714 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003715 broadcastIntentLocked(null, null,
3716 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3717 null, null, 0, null, null,
3718 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3719 false, false, MY_PID, Process.SYSTEM_UID);
3720 }
3721 }
3722 }
3723
3724 final void ensureBootCompleted() {
3725 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003726 boolean enableScreen;
3727 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003728 booting = mBooting;
3729 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003730 enableScreen = !mBooted;
3731 mBooted = true;
3732 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003733
3734 if (booting) {
3735 finishBooting();
3736 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003737
3738 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003739 enableScreenAfterBoot();
3740 }
3741 }
3742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 public final void activityPaused(IBinder token, Bundle icicle) {
3744 // Refuse possible leaked file descriptors
3745 if (icicle != null && icicle.hasFileDescriptors()) {
3746 throw new IllegalArgumentException("File descriptors passed in Bundle");
3747 }
3748
3749 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003750 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 Binder.restoreCallingIdentity(origId);
3752 }
3753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 public final void activityStopped(IBinder token, Bitmap thumbnail,
3755 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003756 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 TAG, "Activity stopped: token=" + token);
3758
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003759 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760
3761 final long origId = Binder.clearCallingIdentity();
3762
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 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 r.thumbnail = thumbnail;
3768 r.description = description;
3769 r.stopped = true;
3770 r.state = ActivityState.STOPPED;
3771 if (!r.finishing) {
3772 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003773 r.stack.destroyActivityLocked(r, true);
3774 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 }
3776 }
3777 }
3778 }
3779
3780 if (r != null) {
3781 sendPendingThumbnail(r, null, null, null, false);
3782 }
3783
3784 trimApplications();
3785
3786 Binder.restoreCallingIdentity(origId);
3787 }
3788
3789 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003790 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003791 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792 }
3793
3794 public String getCallingPackage(IBinder token) {
3795 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003796 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003797 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 }
3799 }
3800
3801 public ComponentName getCallingActivity(IBinder token) {
3802 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003803 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 return r != null ? r.intent.getComponent() : null;
3805 }
3806 }
3807
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003808 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003809 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003811 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003812 if (r != null) {
3813 return r.resultTo;
3814 }
3815 }
3816 return null;
3817 }
3818
3819 public ComponentName getActivityClassForToken(IBinder token) {
3820 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003821 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003823 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 return r.intent.getComponent();
3825 }
3826 return null;
3827 }
3828 }
3829
3830 public String getPackageForToken(IBinder token) {
3831 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003832 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003833 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003834 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 return r.packageName;
3836 }
3837 return null;
3838 }
3839 }
3840
3841 public IIntentSender getIntentSender(int type,
3842 String packageName, IBinder token, String resultWho,
3843 int requestCode, Intent intent, String resolvedType, int flags) {
3844 // Refuse possible leaked file descriptors
3845 if (intent != null && intent.hasFileDescriptors() == true) {
3846 throw new IllegalArgumentException("File descriptors passed in Intent");
3847 }
3848
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003849 if (type == INTENT_SENDER_BROADCAST) {
3850 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3851 throw new IllegalArgumentException(
3852 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3853 }
3854 }
3855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 synchronized(this) {
3857 int callingUid = Binder.getCallingUid();
3858 try {
3859 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3860 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003861 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 .getPackageUid(packageName);
3863 if (uid != Binder.getCallingUid()) {
3864 String msg = "Permission Denial: getIntentSender() from pid="
3865 + Binder.getCallingPid()
3866 + ", uid=" + Binder.getCallingUid()
3867 + ", (need uid=" + uid + ")"
3868 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003869 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 throw new SecurityException(msg);
3871 }
3872 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003873
3874 return getIntentSenderLocked(type, packageName, callingUid,
3875 token, resultWho, requestCode, intent, resolvedType, flags);
3876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 } catch (RemoteException e) {
3878 throw new SecurityException(e);
3879 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003880 }
3881 }
3882
3883 IIntentSender getIntentSenderLocked(int type,
3884 String packageName, int callingUid, IBinder token, String resultWho,
3885 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003886 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003887 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003888 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003889 if (index < 0) {
3890 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003891 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003892 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003893 if (activity.finishing) {
3894 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003896 }
3897
3898 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3899 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3900 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3901 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3902 |PendingIntent.FLAG_UPDATE_CURRENT);
3903
3904 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3905 type, packageName, activity, resultWho,
3906 requestCode, intent, resolvedType, flags);
3907 WeakReference<PendingIntentRecord> ref;
3908 ref = mIntentSenderRecords.get(key);
3909 PendingIntentRecord rec = ref != null ? ref.get() : null;
3910 if (rec != null) {
3911 if (!cancelCurrent) {
3912 if (updateCurrent) {
3913 rec.key.requestIntent.replaceExtras(intent);
3914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003915 return rec;
3916 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003917 rec.canceled = true;
3918 mIntentSenderRecords.remove(key);
3919 }
3920 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003921 return rec;
3922 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003923 rec = new PendingIntentRecord(this, key, callingUid);
3924 mIntentSenderRecords.put(key, rec.ref);
3925 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3926 if (activity.pendingResults == null) {
3927 activity.pendingResults
3928 = new HashSet<WeakReference<PendingIntentRecord>>();
3929 }
3930 activity.pendingResults.add(rec.ref);
3931 }
3932 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 }
3934
3935 public void cancelIntentSender(IIntentSender sender) {
3936 if (!(sender instanceof PendingIntentRecord)) {
3937 return;
3938 }
3939 synchronized(this) {
3940 PendingIntentRecord rec = (PendingIntentRecord)sender;
3941 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003942 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 .getPackageUid(rec.key.packageName);
3944 if (uid != Binder.getCallingUid()) {
3945 String msg = "Permission Denial: cancelIntentSender() from pid="
3946 + Binder.getCallingPid()
3947 + ", uid=" + Binder.getCallingUid()
3948 + " is not allowed to cancel packges "
3949 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003950 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 throw new SecurityException(msg);
3952 }
3953 } catch (RemoteException e) {
3954 throw new SecurityException(e);
3955 }
3956 cancelIntentSenderLocked(rec, true);
3957 }
3958 }
3959
3960 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3961 rec.canceled = true;
3962 mIntentSenderRecords.remove(rec.key);
3963 if (cleanActivity && rec.key.activity != null) {
3964 rec.key.activity.pendingResults.remove(rec.ref);
3965 }
3966 }
3967
3968 public String getPackageForIntentSender(IIntentSender pendingResult) {
3969 if (!(pendingResult instanceof PendingIntentRecord)) {
3970 return null;
3971 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003972 try {
3973 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3974 return res.key.packageName;
3975 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976 }
3977 return null;
3978 }
3979
3980 public void setProcessLimit(int max) {
3981 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3982 "setProcessLimit()");
3983 mProcessLimit = max;
3984 }
3985
3986 public int getProcessLimit() {
3987 return mProcessLimit;
3988 }
3989
3990 void foregroundTokenDied(ForegroundToken token) {
3991 synchronized (ActivityManagerService.this) {
3992 synchronized (mPidsSelfLocked) {
3993 ForegroundToken cur
3994 = mForegroundProcesses.get(token.pid);
3995 if (cur != token) {
3996 return;
3997 }
3998 mForegroundProcesses.remove(token.pid);
3999 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4000 if (pr == null) {
4001 return;
4002 }
4003 pr.forcingToForeground = null;
4004 pr.foregroundServices = false;
4005 }
4006 updateOomAdjLocked();
4007 }
4008 }
4009
4010 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4011 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4012 "setProcessForeground()");
4013 synchronized(this) {
4014 boolean changed = false;
4015
4016 synchronized (mPidsSelfLocked) {
4017 ProcessRecord pr = mPidsSelfLocked.get(pid);
4018 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004019 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 return;
4021 }
4022 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4023 if (oldToken != null) {
4024 oldToken.token.unlinkToDeath(oldToken, 0);
4025 mForegroundProcesses.remove(pid);
4026 pr.forcingToForeground = null;
4027 changed = true;
4028 }
4029 if (isForeground && token != null) {
4030 ForegroundToken newToken = new ForegroundToken() {
4031 public void binderDied() {
4032 foregroundTokenDied(this);
4033 }
4034 };
4035 newToken.pid = pid;
4036 newToken.token = token;
4037 try {
4038 token.linkToDeath(newToken, 0);
4039 mForegroundProcesses.put(pid, newToken);
4040 pr.forcingToForeground = token;
4041 changed = true;
4042 } catch (RemoteException e) {
4043 // If the process died while doing this, we will later
4044 // do the cleanup with the process death link.
4045 }
4046 }
4047 }
4048
4049 if (changed) {
4050 updateOomAdjLocked();
4051 }
4052 }
4053 }
4054
4055 // =========================================================
4056 // PERMISSIONS
4057 // =========================================================
4058
4059 static class PermissionController extends IPermissionController.Stub {
4060 ActivityManagerService mActivityManagerService;
4061 PermissionController(ActivityManagerService activityManagerService) {
4062 mActivityManagerService = activityManagerService;
4063 }
4064
4065 public boolean checkPermission(String permission, int pid, int uid) {
4066 return mActivityManagerService.checkPermission(permission, pid,
4067 uid) == PackageManager.PERMISSION_GRANTED;
4068 }
4069 }
4070
4071 /**
4072 * This can be called with or without the global lock held.
4073 */
4074 int checkComponentPermission(String permission, int pid, int uid,
4075 int reqUid) {
4076 // We might be performing an operation on behalf of an indirect binder
4077 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4078 // client identity accordingly before proceeding.
4079 Identity tlsIdentity = sCallerIdentity.get();
4080 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004081 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4083 uid = tlsIdentity.uid;
4084 pid = tlsIdentity.pid;
4085 }
4086
4087 // Root, system server and our own process get to do everything.
4088 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4089 !Process.supportsProcesses()) {
4090 return PackageManager.PERMISSION_GRANTED;
4091 }
4092 // If the target requires a specific UID, always fail for others.
4093 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004094 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095 return PackageManager.PERMISSION_DENIED;
4096 }
4097 if (permission == null) {
4098 return PackageManager.PERMISSION_GRANTED;
4099 }
4100 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004101 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 .checkUidPermission(permission, uid);
4103 } catch (RemoteException e) {
4104 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004105 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 }
4107 return PackageManager.PERMISSION_DENIED;
4108 }
4109
4110 /**
4111 * As the only public entry point for permissions checking, this method
4112 * can enforce the semantic that requesting a check on a null global
4113 * permission is automatically denied. (Internally a null permission
4114 * string is used when calling {@link #checkComponentPermission} in cases
4115 * when only uid-based security is needed.)
4116 *
4117 * This can be called with or without the global lock held.
4118 */
4119 public int checkPermission(String permission, int pid, int uid) {
4120 if (permission == null) {
4121 return PackageManager.PERMISSION_DENIED;
4122 }
4123 return checkComponentPermission(permission, pid, uid, -1);
4124 }
4125
4126 /**
4127 * Binder IPC calls go through the public entry point.
4128 * This can be called with or without the global lock held.
4129 */
4130 int checkCallingPermission(String permission) {
4131 return checkPermission(permission,
4132 Binder.getCallingPid(),
4133 Binder.getCallingUid());
4134 }
4135
4136 /**
4137 * This can be called with or without the global lock held.
4138 */
4139 void enforceCallingPermission(String permission, String func) {
4140 if (checkCallingPermission(permission)
4141 == PackageManager.PERMISSION_GRANTED) {
4142 return;
4143 }
4144
4145 String msg = "Permission Denial: " + func + " from pid="
4146 + Binder.getCallingPid()
4147 + ", uid=" + Binder.getCallingUid()
4148 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004149 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 throw new SecurityException(msg);
4151 }
4152
4153 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4154 ProviderInfo pi, int uid, int modeFlags) {
4155 try {
4156 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4157 if ((pi.readPermission != null) &&
4158 (pm.checkUidPermission(pi.readPermission, uid)
4159 != PackageManager.PERMISSION_GRANTED)) {
4160 return false;
4161 }
4162 }
4163 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4164 if ((pi.writePermission != null) &&
4165 (pm.checkUidPermission(pi.writePermission, uid)
4166 != PackageManager.PERMISSION_GRANTED)) {
4167 return false;
4168 }
4169 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004170 if (!pi.exported && pi.applicationInfo.uid != uid) {
4171 return false;
4172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 return true;
4174 } catch (RemoteException e) {
4175 return false;
4176 }
4177 }
4178
4179 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4180 int modeFlags) {
4181 // Root gets to do everything.
4182 if (uid == 0 || !Process.supportsProcesses()) {
4183 return true;
4184 }
4185 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4186 if (perms == null) return false;
4187 UriPermission perm = perms.get(uri);
4188 if (perm == null) return false;
4189 return (modeFlags&perm.modeFlags) == modeFlags;
4190 }
4191
4192 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4193 // Another redirected-binder-call permissions check as in
4194 // {@link checkComponentPermission}.
4195 Identity tlsIdentity = sCallerIdentity.get();
4196 if (tlsIdentity != null) {
4197 uid = tlsIdentity.uid;
4198 pid = tlsIdentity.pid;
4199 }
4200
4201 // Our own process gets to do everything.
4202 if (pid == MY_PID) {
4203 return PackageManager.PERMISSION_GRANTED;
4204 }
4205 synchronized(this) {
4206 return checkUriPermissionLocked(uri, uid, modeFlags)
4207 ? PackageManager.PERMISSION_GRANTED
4208 : PackageManager.PERMISSION_DENIED;
4209 }
4210 }
4211
Dianne Hackborn39792d22010-08-19 18:01:52 -07004212 /**
4213 * Check if the targetPkg can be granted permission to access uri by
4214 * the callingUid using the given modeFlags. Throws a security exception
4215 * if callingUid is not allowed to do this. Returns the uid of the target
4216 * if the URI permission grant should be performed; returns -1 if it is not
4217 * needed (for example targetPkg already has permission to access the URI).
4218 */
4219 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4220 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4222 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4223 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004224 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 }
4226
Joe Onorato8a9b2202010-02-26 18:56:32 -08004227 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004228 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004229
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004230 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004231
4232 // If this is not a content: uri, we can't do anything with it.
4233 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004234 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004235 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004236 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 }
4238
4239 String name = uri.getAuthority();
4240 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004241 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 if (cpr != null) {
4243 pi = cpr.info;
4244 } else {
4245 try {
4246 pi = pm.resolveContentProvider(name,
4247 PackageManager.GET_URI_PERMISSION_PATTERNS);
4248 } catch (RemoteException ex) {
4249 }
4250 }
4251 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004252 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004253 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 }
4255
4256 int targetUid;
4257 try {
4258 targetUid = pm.getPackageUid(targetPkg);
4259 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004260 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004261 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004262 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004263 }
4264 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004265 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004266 }
4267
4268 // First... does the target actually need this permission?
4269 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4270 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004271 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004272 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004273 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 }
4275
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004276 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 if (!pi.grantUriPermissions) {
4278 throw new SecurityException("Provider " + pi.packageName
4279 + "/" + pi.name
4280 + " does not allow granting of Uri permissions (uri "
4281 + uri + ")");
4282 }
4283 if (pi.uriPermissionPatterns != null) {
4284 final int N = pi.uriPermissionPatterns.length;
4285 boolean allowed = false;
4286 for (int i=0; i<N; i++) {
4287 if (pi.uriPermissionPatterns[i] != null
4288 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4289 allowed = true;
4290 break;
4291 }
4292 }
4293 if (!allowed) {
4294 throw new SecurityException("Provider " + pi.packageName
4295 + "/" + pi.name
4296 + " does not allow granting of permission to path of Uri "
4297 + uri);
4298 }
4299 }
4300
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004301 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 // this uri?
4303 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4304 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4305 throw new SecurityException("Uid " + callingUid
4306 + " does not have permission to uri " + uri);
4307 }
4308 }
4309
Dianne Hackborn39792d22010-08-19 18:01:52 -07004310 return targetUid;
4311 }
4312
4313 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4314 Uri uri, int modeFlags, UriPermissionOwner owner) {
4315 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4316 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4317 if (modeFlags == 0) {
4318 return;
4319 }
4320
4321 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004322 // to the uri, and the target doesn't. Let's now give this to
4323 // the target.
4324
Joe Onorato8a9b2202010-02-26 18:56:32 -08004325 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004326 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004328 HashMap<Uri, UriPermission> targetUris
4329 = mGrantedUriPermissions.get(targetUid);
4330 if (targetUris == null) {
4331 targetUris = new HashMap<Uri, UriPermission>();
4332 mGrantedUriPermissions.put(targetUid, targetUris);
4333 }
4334
4335 UriPermission perm = targetUris.get(uri);
4336 if (perm == null) {
4337 perm = new UriPermission(targetUid, uri);
4338 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004342 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 perm.globalModeFlags |= modeFlags;
4344 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004345 perm.readOwners.add(owner);
4346 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004348 perm.writeOwners.add(owner);
4349 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 }
4351 }
4352
Dianne Hackborn39792d22010-08-19 18:01:52 -07004353 void grantUriPermissionLocked(int callingUid,
4354 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4355 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4356 if (targetUid < 0) {
4357 return;
4358 }
4359
4360 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4361 }
4362
4363 /**
4364 * Like checkGrantUriPermissionLocked, but takes an Intent.
4365 */
4366 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4367 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004368 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004369 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004370 + " from " + intent + "; flags=0x"
4371 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004374 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004375 }
4376 Uri data = intent.getData();
4377 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004378 return -1;
4379 }
4380 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4381 intent.getFlags());
4382 }
4383
4384 /**
4385 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4386 */
4387 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4388 String targetPkg, Intent intent, UriPermissionOwner owner) {
4389 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4390 intent.getFlags(), owner);
4391 }
4392
4393 void grantUriPermissionFromIntentLocked(int callingUid,
4394 String targetPkg, Intent intent, UriPermissionOwner owner) {
4395 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4396 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 return;
4398 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004399
4400 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004401 }
4402
4403 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4404 Uri uri, int modeFlags) {
4405 synchronized(this) {
4406 final ProcessRecord r = getRecordForAppLocked(caller);
4407 if (r == null) {
4408 throw new SecurityException("Unable to find app for caller "
4409 + caller
4410 + " when granting permission to uri " + uri);
4411 }
4412 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004413 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 }
4415 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004416 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 }
4418
4419 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4420 null);
4421 }
4422 }
4423
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004424 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4426 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4427 HashMap<Uri, UriPermission> perms
4428 = mGrantedUriPermissions.get(perm.uid);
4429 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004430 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004431 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 perms.remove(perm.uri);
4433 if (perms.size() == 0) {
4434 mGrantedUriPermissions.remove(perm.uid);
4435 }
4436 }
4437 }
4438 }
4439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4441 int modeFlags) {
4442 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4443 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4444 if (modeFlags == 0) {
4445 return;
4446 }
4447
Joe Onorato8a9b2202010-02-26 18:56:32 -08004448 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004449 "Revoking all granted permissions to " + uri);
4450
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004451 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004452
4453 final String authority = uri.getAuthority();
4454 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004455 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 if (cpr != null) {
4457 pi = cpr.info;
4458 } else {
4459 try {
4460 pi = pm.resolveContentProvider(authority,
4461 PackageManager.GET_URI_PERMISSION_PATTERNS);
4462 } catch (RemoteException ex) {
4463 }
4464 }
4465 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004466 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 return;
4468 }
4469
4470 // Does the caller have this permission on the URI?
4471 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4472 // Right now, if you are not the original owner of the permission,
4473 // you are not allowed to revoke it.
4474 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4475 throw new SecurityException("Uid " + callingUid
4476 + " does not have permission to uri " + uri);
4477 //}
4478 }
4479
4480 // Go through all of the permissions and remove any that match.
4481 final List<String> SEGMENTS = uri.getPathSegments();
4482 if (SEGMENTS != null) {
4483 final int NS = SEGMENTS.size();
4484 int N = mGrantedUriPermissions.size();
4485 for (int i=0; i<N; i++) {
4486 HashMap<Uri, UriPermission> perms
4487 = mGrantedUriPermissions.valueAt(i);
4488 Iterator<UriPermission> it = perms.values().iterator();
4489 toploop:
4490 while (it.hasNext()) {
4491 UriPermission perm = it.next();
4492 Uri targetUri = perm.uri;
4493 if (!authority.equals(targetUri.getAuthority())) {
4494 continue;
4495 }
4496 List<String> targetSegments = targetUri.getPathSegments();
4497 if (targetSegments == null) {
4498 continue;
4499 }
4500 if (targetSegments.size() < NS) {
4501 continue;
4502 }
4503 for (int j=0; j<NS; j++) {
4504 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4505 continue toploop;
4506 }
4507 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004508 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004509 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 perm.clearModes(modeFlags);
4511 if (perm.modeFlags == 0) {
4512 it.remove();
4513 }
4514 }
4515 if (perms.size() == 0) {
4516 mGrantedUriPermissions.remove(
4517 mGrantedUriPermissions.keyAt(i));
4518 N--;
4519 i--;
4520 }
4521 }
4522 }
4523 }
4524
4525 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4526 int modeFlags) {
4527 synchronized(this) {
4528 final ProcessRecord r = getRecordForAppLocked(caller);
4529 if (r == null) {
4530 throw new SecurityException("Unable to find app for caller "
4531 + caller
4532 + " when revoking permission to uri " + uri);
4533 }
4534 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004535 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 return;
4537 }
4538
4539 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4540 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4541 if (modeFlags == 0) {
4542 return;
4543 }
4544
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004545 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004546
4547 final String authority = uri.getAuthority();
4548 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004549 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 if (cpr != null) {
4551 pi = cpr.info;
4552 } else {
4553 try {
4554 pi = pm.resolveContentProvider(authority,
4555 PackageManager.GET_URI_PERMISSION_PATTERNS);
4556 } catch (RemoteException ex) {
4557 }
4558 }
4559 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004560 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 return;
4562 }
4563
4564 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4565 }
4566 }
4567
Dianne Hackborn7e269642010-08-25 19:50:20 -07004568 @Override
4569 public IBinder newUriPermissionOwner(String name) {
4570 synchronized(this) {
4571 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4572 return owner.getExternalTokenLocked();
4573 }
4574 }
4575
4576 @Override
4577 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4578 Uri uri, int modeFlags) {
4579 synchronized(this) {
4580 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4581 if (owner == null) {
4582 throw new IllegalArgumentException("Unknown owner: " + token);
4583 }
4584 if (fromUid != Binder.getCallingUid()) {
4585 if (Binder.getCallingUid() != Process.myUid()) {
4586 // Only system code can grant URI permissions on behalf
4587 // of other users.
4588 throw new SecurityException("nice try");
4589 }
4590 }
4591 if (targetPkg == null) {
4592 throw new IllegalArgumentException("null target");
4593 }
4594 if (uri == null) {
4595 throw new IllegalArgumentException("null uri");
4596 }
4597
4598 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4599 }
4600 }
4601
4602 @Override
4603 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4604 synchronized(this) {
4605 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4606 if (owner == null) {
4607 throw new IllegalArgumentException("Unknown owner: " + token);
4608 }
4609
4610 if (uri == null) {
4611 owner.removeUriPermissionsLocked(mode);
4612 } else {
4613 owner.removeUriPermissionLocked(uri, mode);
4614 }
4615 }
4616 }
4617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4619 synchronized (this) {
4620 ProcessRecord app =
4621 who != null ? getRecordForAppLocked(who) : null;
4622 if (app == null) return;
4623
4624 Message msg = Message.obtain();
4625 msg.what = WAIT_FOR_DEBUGGER_MSG;
4626 msg.obj = app;
4627 msg.arg1 = waiting ? 1 : 0;
4628 mHandler.sendMessage(msg);
4629 }
4630 }
4631
4632 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4633 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004634 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004636 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 }
4638
4639 // =========================================================
4640 // TASK MANAGEMENT
4641 // =========================================================
4642
4643 public List getTasks(int maxNum, int flags,
4644 IThumbnailReceiver receiver) {
4645 ArrayList list = new ArrayList();
4646
4647 PendingThumbnailsRecord pending = null;
4648 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004649 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650
4651 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004652 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4654 + ", receiver=" + receiver);
4655
4656 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4657 != PackageManager.PERMISSION_GRANTED) {
4658 if (receiver != null) {
4659 // If the caller wants to wait for pending thumbnails,
4660 // it ain't gonna get them.
4661 try {
4662 receiver.finished();
4663 } catch (RemoteException ex) {
4664 }
4665 }
4666 String msg = "Permission Denial: getTasks() from pid="
4667 + Binder.getCallingPid()
4668 + ", uid=" + Binder.getCallingUid()
4669 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004670 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004671 throw new SecurityException(msg);
4672 }
4673
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004674 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004675 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004676 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004677 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 CharSequence topDescription = null;
4679 TaskRecord curTask = null;
4680 int numActivities = 0;
4681 int numRunning = 0;
4682 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004683 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004685 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686
4687 // Initialize state for next task if needed.
4688 if (top == null ||
4689 (top.state == ActivityState.INITIALIZING
4690 && top.task == r.task)) {
4691 top = r;
4692 topDescription = r.description;
4693 curTask = r.task;
4694 numActivities = numRunning = 0;
4695 }
4696
4697 // Add 'r' into the current task.
4698 numActivities++;
4699 if (r.app != null && r.app.thread != null) {
4700 numRunning++;
4701 }
4702 if (topDescription == null) {
4703 topDescription = r.description;
4704 }
4705
Joe Onorato8a9b2202010-02-26 18:56:32 -08004706 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 TAG, r.intent.getComponent().flattenToShortString()
4708 + ": task=" + r.task);
4709
4710 // If the next one is a different task, generate a new
4711 // TaskInfo entry for what we have.
4712 if (next == null || next.task != curTask) {
4713 ActivityManager.RunningTaskInfo ci
4714 = new ActivityManager.RunningTaskInfo();
4715 ci.id = curTask.taskId;
4716 ci.baseActivity = r.intent.getComponent();
4717 ci.topActivity = top.intent.getComponent();
4718 ci.thumbnail = top.thumbnail;
4719 ci.description = topDescription;
4720 ci.numActivities = numActivities;
4721 ci.numRunning = numRunning;
4722 //System.out.println(
4723 // "#" + maxNum + ": " + " descr=" + ci.description);
4724 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004725 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 TAG, "State=" + top.state + "Idle=" + top.idle
4727 + " app=" + top.app
4728 + " thr=" + (top.app != null ? top.app.thread : null));
4729 if (top.state == ActivityState.RESUMED
4730 || top.state == ActivityState.PAUSING) {
4731 if (top.idle && top.app != null
4732 && top.app.thread != null) {
4733 topRecord = top;
4734 topThumbnail = top.app.thread;
4735 } else {
4736 top.thumbnailNeeded = true;
4737 }
4738 }
4739 if (pending == null) {
4740 pending = new PendingThumbnailsRecord(receiver);
4741 }
4742 pending.pendingRecords.add(top);
4743 }
4744 list.add(ci);
4745 maxNum--;
4746 top = null;
4747 }
4748 }
4749
4750 if (pending != null) {
4751 mPendingThumbnails.add(pending);
4752 }
4753 }
4754
Joe Onorato8a9b2202010-02-26 18:56:32 -08004755 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756
4757 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004758 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 try {
4760 topThumbnail.requestThumbnail(topRecord);
4761 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004762 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 sendPendingThumbnail(null, topRecord, null, null, true);
4764 }
4765 }
4766
4767 if (pending == null && receiver != null) {
4768 // In this case all thumbnails were available and the client
4769 // is being asked to be told when the remaining ones come in...
4770 // which is unusually, since the top-most currently running
4771 // activity should never have a canned thumbnail! Oh well.
4772 try {
4773 receiver.finished();
4774 } catch (RemoteException ex) {
4775 }
4776 }
4777
4778 return list;
4779 }
4780
4781 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4782 int flags) {
4783 synchronized (this) {
4784 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4785 "getRecentTasks()");
4786
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004787 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 final int N = mRecentTasks.size();
4790 ArrayList<ActivityManager.RecentTaskInfo> res
4791 = new ArrayList<ActivityManager.RecentTaskInfo>(
4792 maxNum < N ? maxNum : N);
4793 for (int i=0; i<N && maxNum > 0; i++) {
4794 TaskRecord tr = mRecentTasks.get(i);
4795 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4796 || (tr.intent == null)
4797 || ((tr.intent.getFlags()
4798 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4799 ActivityManager.RecentTaskInfo rti
4800 = new ActivityManager.RecentTaskInfo();
4801 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4802 rti.baseIntent = new Intent(
4803 tr.intent != null ? tr.intent : tr.affinityIntent);
4804 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004805
4806 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4807 // Check whether this activity is currently available.
4808 try {
4809 if (rti.origActivity != null) {
4810 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4811 continue;
4812 }
4813 } else if (rti.baseIntent != null) {
4814 if (pm.queryIntentActivities(rti.baseIntent,
4815 null, 0) == null) {
4816 continue;
4817 }
4818 }
4819 } catch (RemoteException e) {
4820 // Will never happen.
4821 }
4822 }
4823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824 res.add(rti);
4825 maxNum--;
4826 }
4827 }
4828 return res;
4829 }
4830 }
4831
4832 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4833 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004834 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 TaskRecord jt = startTask;
4836
4837 // First look backwards
4838 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004839 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 if (r.task != jt) {
4841 jt = r.task;
4842 if (affinity.equals(jt.affinity)) {
4843 return j;
4844 }
4845 }
4846 }
4847
4848 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004849 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004850 jt = startTask;
4851 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004852 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 if (r.task != jt) {
4854 if (affinity.equals(jt.affinity)) {
4855 return j;
4856 }
4857 jt = r.task;
4858 }
4859 }
4860
4861 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004862 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 return N-1;
4864 }
4865
4866 return -1;
4867 }
4868
4869 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004870 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 */
4872 public void moveTaskToFront(int task) {
4873 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4874 "moveTaskToFront()");
4875
4876 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004877 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4878 Binder.getCallingUid(), "Task to front")) {
4879 return;
4880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 final long origId = Binder.clearCallingIdentity();
4882 try {
4883 int N = mRecentTasks.size();
4884 for (int i=0; i<N; i++) {
4885 TaskRecord tr = mRecentTasks.get(i);
4886 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004887 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004888 return;
4889 }
4890 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004891 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4892 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004893 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004894 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 return;
4896 }
4897 }
4898 } finally {
4899 Binder.restoreCallingIdentity(origId);
4900 }
4901 }
4902 }
4903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 public void moveTaskToBack(int task) {
4905 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4906 "moveTaskToBack()");
4907
4908 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004909 if (mMainStack.mResumedActivity != null
4910 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004911 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4912 Binder.getCallingUid(), "Task to back")) {
4913 return;
4914 }
4915 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004916 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004917 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 Binder.restoreCallingIdentity(origId);
4919 }
4920 }
4921
4922 /**
4923 * Moves an activity, and all of the other activities within the same task, to the bottom
4924 * of the history stack. The activity's order within the task is unchanged.
4925 *
4926 * @param token A reference to the activity we wish to move
4927 * @param nonRoot If false then this only works if the activity is the root
4928 * of a task; if true it will work for any activity in a task.
4929 * @return Returns true if the move completed, false if not.
4930 */
4931 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4932 synchronized(this) {
4933 final long origId = Binder.clearCallingIdentity();
4934 int taskId = getTaskForActivityLocked(token, !nonRoot);
4935 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004936 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 }
4938 Binder.restoreCallingIdentity(origId);
4939 }
4940 return false;
4941 }
4942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004943 public void moveTaskBackwards(int task) {
4944 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4945 "moveTaskBackwards()");
4946
4947 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004948 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4949 Binder.getCallingUid(), "Task backwards")) {
4950 return;
4951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 final long origId = Binder.clearCallingIdentity();
4953 moveTaskBackwardsLocked(task);
4954 Binder.restoreCallingIdentity(origId);
4955 }
4956 }
4957
4958 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004959 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 }
4961
4962 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4963 synchronized(this) {
4964 return getTaskForActivityLocked(token, onlyRoot);
4965 }
4966 }
4967
4968 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004969 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970 TaskRecord lastTask = null;
4971 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004972 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004973 if (r == token) {
4974 if (!onlyRoot || lastTask != r.task) {
4975 return r.task.taskId;
4976 }
4977 return -1;
4978 }
4979 lastTask = r.task;
4980 }
4981
4982 return -1;
4983 }
4984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 public void finishOtherInstances(IBinder token, ComponentName className) {
4986 synchronized(this) {
4987 final long origId = Binder.clearCallingIdentity();
4988
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004989 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 TaskRecord lastTask = null;
4991 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004992 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 if (r.realActivity.equals(className)
4994 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004995 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 null, "others")) {
4997 i--;
4998 N--;
4999 }
5000 }
5001 lastTask = r.task;
5002 }
5003
5004 Binder.restoreCallingIdentity(origId);
5005 }
5006 }
5007
5008 // =========================================================
5009 // THUMBNAILS
5010 // =========================================================
5011
5012 public void reportThumbnail(IBinder token,
5013 Bitmap thumbnail, CharSequence description) {
5014 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5015 final long origId = Binder.clearCallingIdentity();
5016 sendPendingThumbnail(null, token, thumbnail, description, true);
5017 Binder.restoreCallingIdentity(origId);
5018 }
5019
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005020 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005021 Bitmap thumbnail, CharSequence description, boolean always) {
5022 TaskRecord task = null;
5023 ArrayList receivers = null;
5024
5025 //System.out.println("Send pending thumbnail: " + r);
5026
5027 synchronized(this) {
5028 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005029 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 if (index < 0) {
5031 return;
5032 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005033 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 }
5035 if (thumbnail == null) {
5036 thumbnail = r.thumbnail;
5037 description = r.description;
5038 }
5039 if (thumbnail == null && !always) {
5040 // If there is no thumbnail, and this entry is not actually
5041 // going away, then abort for now and pick up the next
5042 // thumbnail we get.
5043 return;
5044 }
5045 task = r.task;
5046
5047 int N = mPendingThumbnails.size();
5048 int i=0;
5049 while (i<N) {
5050 PendingThumbnailsRecord pr =
5051 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5052 //System.out.println("Looking in " + pr.pendingRecords);
5053 if (pr.pendingRecords.remove(r)) {
5054 if (receivers == null) {
5055 receivers = new ArrayList();
5056 }
5057 receivers.add(pr);
5058 if (pr.pendingRecords.size() == 0) {
5059 pr.finished = true;
5060 mPendingThumbnails.remove(i);
5061 N--;
5062 continue;
5063 }
5064 }
5065 i++;
5066 }
5067 }
5068
5069 if (receivers != null) {
5070 final int N = receivers.size();
5071 for (int i=0; i<N; i++) {
5072 try {
5073 PendingThumbnailsRecord pr =
5074 (PendingThumbnailsRecord)receivers.get(i);
5075 pr.receiver.newThumbnail(
5076 task != null ? task.taskId : -1, thumbnail, description);
5077 if (pr.finished) {
5078 pr.receiver.finished();
5079 }
5080 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005081 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 }
5083 }
5084 }
5085 }
5086
5087 // =========================================================
5088 // CONTENT PROVIDERS
5089 // =========================================================
5090
5091 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5092 List providers = null;
5093 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005094 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005095 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005096 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 } catch (RemoteException ex) {
5098 }
5099 if (providers != null) {
5100 final int N = providers.size();
5101 for (int i=0; i<N; i++) {
5102 ProviderInfo cpi =
5103 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005104 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 if (cpr == null) {
5106 cpr = new ContentProviderRecord(cpi, app.info);
5107 mProvidersByClass.put(cpi.name, cpr);
5108 }
5109 app.pubProviders.put(cpi.name, cpr);
5110 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005111 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 }
5113 }
5114 return providers;
5115 }
5116
5117 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005118 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5120 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5121 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5122 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005123 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 return null;
5125 }
5126 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5127 cpi.exported ? -1 : cpi.applicationInfo.uid)
5128 == PackageManager.PERMISSION_GRANTED) {
5129 return null;
5130 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005131
5132 PathPermission[] pps = cpi.pathPermissions;
5133 if (pps != null) {
5134 int i = pps.length;
5135 while (i > 0) {
5136 i--;
5137 PathPermission pp = pps[i];
5138 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5139 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005140 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005141 return null;
5142 }
5143 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5144 cpi.exported ? -1 : cpi.applicationInfo.uid)
5145 == PackageManager.PERMISSION_GRANTED) {
5146 return null;
5147 }
5148 }
5149 }
5150
Dianne Hackbornb424b632010-08-18 15:59:05 -07005151 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5152 if (perms != null) {
5153 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5154 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5155 return null;
5156 }
5157 }
5158 }
5159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 String msg = "Permission Denial: opening provider " + cpi.name
5161 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5162 + ", uid=" + callingUid + ") requires "
5163 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005164 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 return msg;
5166 }
5167
5168 private final ContentProviderHolder getContentProviderImpl(
5169 IApplicationThread caller, String name) {
5170 ContentProviderRecord cpr;
5171 ProviderInfo cpi = null;
5172
5173 synchronized(this) {
5174 ProcessRecord r = null;
5175 if (caller != null) {
5176 r = getRecordForAppLocked(caller);
5177 if (r == null) {
5178 throw new SecurityException(
5179 "Unable to find app for caller " + caller
5180 + " (pid=" + Binder.getCallingPid()
5181 + ") when getting content provider " + name);
5182 }
5183 }
5184
5185 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005186 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005187 if (cpr != null) {
5188 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005189 String msg;
5190 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5191 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 }
5193
5194 if (r != null && cpr.canRunHere(r)) {
5195 // This provider has been published or is in the process
5196 // of being published... but it is also allowed to run
5197 // in the caller's process, so don't make a connection
5198 // and just let the caller instantiate its own instance.
5199 if (cpr.provider != null) {
5200 // don't give caller the provider object, it needs
5201 // to make its own.
5202 cpr = new ContentProviderRecord(cpr);
5203 }
5204 return cpr;
5205 }
5206
5207 final long origId = Binder.clearCallingIdentity();
5208
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005209 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 // return it right away.
5211 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005212 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005213 "Adding provider requested by "
5214 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005215 + cpr.info.processName);
5216 Integer cnt = r.conProviders.get(cpr);
5217 if (cnt == null) {
5218 r.conProviders.put(cpr, new Integer(1));
5219 } else {
5220 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005222 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005223 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5224 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005225 // make sure to count it as being accessed and thus
5226 // back up on the LRU list. This is good because
5227 // content providers are often expensive to start.
5228 updateLruProcessLocked(cpr.app, false, true);
5229 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005230 } else {
5231 cpr.externals++;
5232 }
5233
5234 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 updateOomAdjLocked(cpr.app);
5236 }
5237
5238 Binder.restoreCallingIdentity(origId);
5239
5240 } else {
5241 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005242 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005243 resolveContentProvider(name,
5244 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 } catch (RemoteException ex) {
5246 }
5247 if (cpi == null) {
5248 return null;
5249 }
5250
Dianne Hackbornb424b632010-08-18 15:59:05 -07005251 String msg;
5252 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5253 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 }
5255
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005256 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5257 && !cpi.processName.equals("system")) {
5258 // If this content provider does not run in the system
5259 // process, and the system is not yet ready to run other
5260 // processes, then fail fast instead of hanging.
5261 throw new IllegalArgumentException(
5262 "Attempt to launch content provider before system ready");
5263 }
5264
Dianne Hackborn860755f2010-06-03 18:47:52 -07005265 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 final boolean firstClass = cpr == null;
5267 if (firstClass) {
5268 try {
5269 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005270 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 getApplicationInfo(
5272 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005273 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005275 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 + cpi.name);
5277 return null;
5278 }
5279 cpr = new ContentProviderRecord(cpi, ai);
5280 } catch (RemoteException ex) {
5281 // pm is in same process, this will never happen.
5282 }
5283 }
5284
5285 if (r != null && cpr.canRunHere(r)) {
5286 // If this is a multiprocess provider, then just return its
5287 // info and allow the caller to instantiate it. Only do
5288 // this if the provider is the same user as the caller's
5289 // process, or can run as root (so can be in any process).
5290 return cpr;
5291 }
5292
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005293 if (DEBUG_PROVIDER) {
5294 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005295 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005296 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005297 }
5298
5299 // This is single process, and our app is now connecting to it.
5300 // See if we are already in the process of launching this
5301 // provider.
5302 final int N = mLaunchingProviders.size();
5303 int i;
5304 for (i=0; i<N; i++) {
5305 if (mLaunchingProviders.get(i) == cpr) {
5306 break;
5307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005308 }
5309
5310 // If the provider is not already being launched, then get it
5311 // started.
5312 if (i >= N) {
5313 final long origId = Binder.clearCallingIdentity();
5314 ProcessRecord proc = startProcessLocked(cpi.processName,
5315 cpr.appInfo, false, 0, "content provider",
5316 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005317 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005319 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 + cpi.applicationInfo.packageName + "/"
5321 + cpi.applicationInfo.uid + " for provider "
5322 + name + ": process is bad");
5323 return null;
5324 }
5325 cpr.launchingApp = proc;
5326 mLaunchingProviders.add(cpr);
5327 Binder.restoreCallingIdentity(origId);
5328 }
5329
5330 // Make sure the provider is published (the same provider class
5331 // may be published under multiple names).
5332 if (firstClass) {
5333 mProvidersByClass.put(cpi.name, cpr);
5334 }
5335 mProvidersByName.put(name, cpr);
5336
5337 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005338 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005339 "Adding provider requested by "
5340 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005341 + cpr.info.processName);
5342 Integer cnt = r.conProviders.get(cpr);
5343 if (cnt == null) {
5344 r.conProviders.put(cpr, new Integer(1));
5345 } else {
5346 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 cpr.clients.add(r);
5349 } else {
5350 cpr.externals++;
5351 }
5352 }
5353 }
5354
5355 // Wait for the provider to be published...
5356 synchronized (cpr) {
5357 while (cpr.provider == null) {
5358 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005359 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005360 + cpi.applicationInfo.packageName + "/"
5361 + cpi.applicationInfo.uid + " for provider "
5362 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005363 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 cpi.applicationInfo.packageName,
5365 cpi.applicationInfo.uid, name);
5366 return null;
5367 }
5368 try {
5369 cpr.wait();
5370 } catch (InterruptedException ex) {
5371 }
5372 }
5373 }
5374 return cpr;
5375 }
5376
5377 public final ContentProviderHolder getContentProvider(
5378 IApplicationThread caller, String name) {
5379 if (caller == null) {
5380 String msg = "null IApplicationThread when getting content provider "
5381 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005382 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005383 throw new SecurityException(msg);
5384 }
5385
5386 return getContentProviderImpl(caller, name);
5387 }
5388
5389 private ContentProviderHolder getContentProviderExternal(String name) {
5390 return getContentProviderImpl(null, name);
5391 }
5392
5393 /**
5394 * Drop a content provider from a ProcessRecord's bookkeeping
5395 * @param cpr
5396 */
5397 public void removeContentProvider(IApplicationThread caller, String name) {
5398 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005399 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005400 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005401 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005402 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005403 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 return;
5405 }
5406 final ProcessRecord r = getRecordForAppLocked(caller);
5407 if (r == null) {
5408 throw new SecurityException(
5409 "Unable to find app for caller " + caller +
5410 " when removing content provider " + name);
5411 }
5412 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005413 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005414 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005415 + r.info.processName + " from process "
5416 + localCpr.appInfo.processName);
5417 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005418 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005419 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005420 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 return;
5422 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005423 Integer cnt = r.conProviders.get(localCpr);
5424 if (cnt == null || cnt.intValue() <= 1) {
5425 localCpr.clients.remove(r);
5426 r.conProviders.remove(localCpr);
5427 } else {
5428 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005430 }
5431 updateOomAdjLocked();
5432 }
5433 }
5434
5435 private void removeContentProviderExternal(String name) {
5436 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005437 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438 if(cpr == null) {
5439 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005440 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005441 return;
5442 }
5443
5444 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005445 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 localCpr.externals--;
5447 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005448 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 }
5450 updateOomAdjLocked();
5451 }
5452 }
5453
5454 public final void publishContentProviders(IApplicationThread caller,
5455 List<ContentProviderHolder> providers) {
5456 if (providers == null) {
5457 return;
5458 }
5459
5460 synchronized(this) {
5461 final ProcessRecord r = getRecordForAppLocked(caller);
5462 if (r == null) {
5463 throw new SecurityException(
5464 "Unable to find app for caller " + caller
5465 + " (pid=" + Binder.getCallingPid()
5466 + ") when publishing content providers");
5467 }
5468
5469 final long origId = Binder.clearCallingIdentity();
5470
5471 final int N = providers.size();
5472 for (int i=0; i<N; i++) {
5473 ContentProviderHolder src = providers.get(i);
5474 if (src == null || src.info == null || src.provider == null) {
5475 continue;
5476 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005477 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 if (dst != null) {
5479 mProvidersByClass.put(dst.info.name, dst);
5480 String names[] = dst.info.authority.split(";");
5481 for (int j = 0; j < names.length; j++) {
5482 mProvidersByName.put(names[j], dst);
5483 }
5484
5485 int NL = mLaunchingProviders.size();
5486 int j;
5487 for (j=0; j<NL; j++) {
5488 if (mLaunchingProviders.get(j) == dst) {
5489 mLaunchingProviders.remove(j);
5490 j--;
5491 NL--;
5492 }
5493 }
5494 synchronized (dst) {
5495 dst.provider = src.provider;
5496 dst.app = r;
5497 dst.notifyAll();
5498 }
5499 updateOomAdjLocked(r);
5500 }
5501 }
5502
5503 Binder.restoreCallingIdentity(origId);
5504 }
5505 }
5506
5507 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005508 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005509 synchronized (mSelf) {
5510 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5511 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005512 if (providers != null) {
5513 for (int i=providers.size()-1; i>=0; i--) {
5514 ProviderInfo pi = (ProviderInfo)providers.get(i);
5515 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5516 Slog.w(TAG, "Not installing system proc provider " + pi.name
5517 + ": not system .apk");
5518 providers.remove(i);
5519 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005520 }
5521 }
5522 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005523 if (providers != null) {
5524 mSystemThread.installSystemProviders(providers);
5525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526 }
5527
5528 // =========================================================
5529 // GLOBAL MANAGEMENT
5530 // =========================================================
5531
5532 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5533 ApplicationInfo info, String customProcess) {
5534 String proc = customProcess != null ? customProcess : info.processName;
5535 BatteryStatsImpl.Uid.Proc ps = null;
5536 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5537 synchronized (stats) {
5538 ps = stats.getProcessStatsLocked(info.uid, proc);
5539 }
5540 return new ProcessRecord(ps, thread, info, proc);
5541 }
5542
5543 final ProcessRecord addAppLocked(ApplicationInfo info) {
5544 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5545
5546 if (app == null) {
5547 app = newProcessRecordLocked(null, info, null);
5548 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005549 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005550 }
5551
5552 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5553 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5554 app.persistent = true;
5555 app.maxAdj = CORE_SERVER_ADJ;
5556 }
5557 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5558 mPersistentStartingProcesses.add(app);
5559 startProcessLocked(app, "added application", app.processName);
5560 }
5561
5562 return app;
5563 }
5564
5565 public void unhandledBack() {
5566 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5567 "unhandledBack()");
5568
5569 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005570 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005571 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005572 TAG, "Performing unhandledBack(): stack size = " + count);
5573 if (count > 1) {
5574 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005575 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5577 Binder.restoreCallingIdentity(origId);
5578 }
5579 }
5580 }
5581
5582 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5583 String name = uri.getAuthority();
5584 ContentProviderHolder cph = getContentProviderExternal(name);
5585 ParcelFileDescriptor pfd = null;
5586 if (cph != null) {
5587 // We record the binder invoker's uid in thread-local storage before
5588 // going to the content provider to open the file. Later, in the code
5589 // that handles all permissions checks, we look for this uid and use
5590 // that rather than the Activity Manager's own uid. The effect is that
5591 // we do the check against the caller's permissions even though it looks
5592 // to the content provider like the Activity Manager itself is making
5593 // the request.
5594 sCallerIdentity.set(new Identity(
5595 Binder.getCallingPid(), Binder.getCallingUid()));
5596 try {
5597 pfd = cph.provider.openFile(uri, "r");
5598 } catch (FileNotFoundException e) {
5599 // do nothing; pfd will be returned null
5600 } finally {
5601 // Ensure that whatever happens, we clean up the identity state
5602 sCallerIdentity.remove();
5603 }
5604
5605 // We've got the fd now, so we're done with the provider.
5606 removeContentProviderExternal(name);
5607 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005608 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 }
5610 return pfd;
5611 }
5612
5613 public void goingToSleep() {
5614 synchronized(this) {
5615 mSleeping = true;
5616 mWindowManager.setEventDispatching(false);
5617
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005618 if (mMainStack.mResumedActivity != null) {
5619 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005621 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005623
5624 // Initialize the wake times of all processes.
5625 checkExcessiveWakeLocksLocked(false);
5626 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5627 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5628 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 }
5630 }
5631
Dianne Hackborn55280a92009-05-07 15:53:46 -07005632 public boolean shutdown(int timeout) {
5633 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5634 != PackageManager.PERMISSION_GRANTED) {
5635 throw new SecurityException("Requires permission "
5636 + android.Manifest.permission.SHUTDOWN);
5637 }
5638
5639 boolean timedout = false;
5640
5641 synchronized(this) {
5642 mShuttingDown = true;
5643 mWindowManager.setEventDispatching(false);
5644
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005645 if (mMainStack.mResumedActivity != null) {
5646 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005647 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005648 while (mMainStack.mResumedActivity != null
5649 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005650 long delay = endTime - System.currentTimeMillis();
5651 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005652 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005653 timedout = true;
5654 break;
5655 }
5656 try {
5657 this.wait();
5658 } catch (InterruptedException e) {
5659 }
5660 }
5661 }
5662 }
5663
5664 mUsageStatsService.shutdown();
5665 mBatteryStatsService.shutdown();
5666
5667 return timedout;
5668 }
5669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005670 public void wakingUp() {
5671 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005672 if (mMainStack.mGoingToSleep.isHeld()) {
5673 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 }
5675 mWindowManager.setEventDispatching(true);
5676 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005677 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005678 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 }
5680 }
5681
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005682 public void stopAppSwitches() {
5683 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5684 != PackageManager.PERMISSION_GRANTED) {
5685 throw new SecurityException("Requires permission "
5686 + android.Manifest.permission.STOP_APP_SWITCHES);
5687 }
5688
5689 synchronized(this) {
5690 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5691 + APP_SWITCH_DELAY_TIME;
5692 mDidAppSwitch = false;
5693 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5694 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5695 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5696 }
5697 }
5698
5699 public void resumeAppSwitches() {
5700 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5701 != PackageManager.PERMISSION_GRANTED) {
5702 throw new SecurityException("Requires permission "
5703 + android.Manifest.permission.STOP_APP_SWITCHES);
5704 }
5705
5706 synchronized(this) {
5707 // Note that we don't execute any pending app switches... we will
5708 // let those wait until either the timeout, or the next start
5709 // activity request.
5710 mAppSwitchesAllowedTime = 0;
5711 }
5712 }
5713
5714 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5715 String name) {
5716 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5717 return true;
5718 }
5719
5720 final int perm = checkComponentPermission(
5721 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5722 callingUid, -1);
5723 if (perm == PackageManager.PERMISSION_GRANTED) {
5724 return true;
5725 }
5726
Joe Onorato8a9b2202010-02-26 18:56:32 -08005727 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005728 return false;
5729 }
5730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005731 public void setDebugApp(String packageName, boolean waitForDebugger,
5732 boolean persistent) {
5733 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5734 "setDebugApp()");
5735
5736 // Note that this is not really thread safe if there are multiple
5737 // callers into it at the same time, but that's not a situation we
5738 // care about.
5739 if (persistent) {
5740 final ContentResolver resolver = mContext.getContentResolver();
5741 Settings.System.putString(
5742 resolver, Settings.System.DEBUG_APP,
5743 packageName);
5744 Settings.System.putInt(
5745 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5746 waitForDebugger ? 1 : 0);
5747 }
5748
5749 synchronized (this) {
5750 if (!persistent) {
5751 mOrigDebugApp = mDebugApp;
5752 mOrigWaitForDebugger = mWaitForDebugger;
5753 }
5754 mDebugApp = packageName;
5755 mWaitForDebugger = waitForDebugger;
5756 mDebugTransient = !persistent;
5757 if (packageName != null) {
5758 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005759 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 Binder.restoreCallingIdentity(origId);
5761 }
5762 }
5763 }
5764
5765 public void setAlwaysFinish(boolean enabled) {
5766 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5767 "setAlwaysFinish()");
5768
5769 Settings.System.putInt(
5770 mContext.getContentResolver(),
5771 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5772
5773 synchronized (this) {
5774 mAlwaysFinishActivities = enabled;
5775 }
5776 }
5777
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005778 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005779 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005780 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005782 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005783 }
5784 }
5785
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005786 public boolean isUserAMonkey() {
5787 // For now the fact that there is a controller implies
5788 // we have a monkey.
5789 synchronized (this) {
5790 return mController != null;
5791 }
5792 }
5793
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005794 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005795 synchronized (this) {
5796 mWatchers.register(watcher);
5797 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005798 }
5799
5800 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005801 synchronized (this) {
5802 mWatchers.unregister(watcher);
5803 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005804 }
5805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 public final void enterSafeMode() {
5807 synchronized(this) {
5808 // It only makes sense to do this before the system is ready
5809 // and started launching other packages.
5810 if (!mSystemReady) {
5811 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005812 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005813 } catch (RemoteException e) {
5814 }
5815
5816 View v = LayoutInflater.from(mContext).inflate(
5817 com.android.internal.R.layout.safe_mode, null);
5818 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5819 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5820 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5821 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5822 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5823 lp.format = v.getBackground().getOpacity();
5824 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5825 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5826 ((WindowManager)mContext.getSystemService(
5827 Context.WINDOW_SERVICE)).addView(v, lp);
5828 }
5829 }
5830 }
5831
5832 public void noteWakeupAlarm(IIntentSender sender) {
5833 if (!(sender instanceof PendingIntentRecord)) {
5834 return;
5835 }
5836 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5837 synchronized (stats) {
5838 if (mBatteryStatsService.isOnBattery()) {
5839 mBatteryStatsService.enforceCallingPermission();
5840 PendingIntentRecord rec = (PendingIntentRecord)sender;
5841 int MY_UID = Binder.getCallingUid();
5842 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5843 BatteryStatsImpl.Uid.Pkg pkg =
5844 stats.getPackageStatsLocked(uid, rec.key.packageName);
5845 pkg.incWakeupsLocked();
5846 }
5847 }
5848 }
5849
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005850 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005852 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005854 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005855 // XXX Note: don't acquire main activity lock here, because the window
5856 // manager calls in with its locks held.
5857
5858 boolean killed = false;
5859 synchronized (mPidsSelfLocked) {
5860 int[] types = new int[pids.length];
5861 int worstType = 0;
5862 for (int i=0; i<pids.length; i++) {
5863 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5864 if (proc != null) {
5865 int type = proc.setAdj;
5866 types[i] = type;
5867 if (type > worstType) {
5868 worstType = type;
5869 }
5870 }
5871 }
5872
5873 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5874 // then constrain it so we will kill all hidden procs.
5875 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5876 worstType = HIDDEN_APP_MIN_ADJ;
5877 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005878 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 for (int i=0; i<pids.length; i++) {
5880 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5881 if (proc == null) {
5882 continue;
5883 }
5884 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005885 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005886 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005887 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5888 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005889 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005890 proc.killedBackground = true;
5891 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005892 }
5893 }
5894 }
5895 return killed;
5896 }
5897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005898 public final void startRunning(String pkg, String cls, String action,
5899 String data) {
5900 synchronized(this) {
5901 if (mStartRunning) {
5902 return;
5903 }
5904 mStartRunning = true;
5905 mTopComponent = pkg != null && cls != null
5906 ? new ComponentName(pkg, cls) : null;
5907 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5908 mTopData = data;
5909 if (!mSystemReady) {
5910 return;
5911 }
5912 }
5913
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005914 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 }
5916
5917 private void retrieveSettings() {
5918 final ContentResolver resolver = mContext.getContentResolver();
5919 String debugApp = Settings.System.getString(
5920 resolver, Settings.System.DEBUG_APP);
5921 boolean waitForDebugger = Settings.System.getInt(
5922 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5923 boolean alwaysFinishActivities = Settings.System.getInt(
5924 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5925
5926 Configuration configuration = new Configuration();
5927 Settings.System.getConfiguration(resolver, configuration);
5928
5929 synchronized (this) {
5930 mDebugApp = mOrigDebugApp = debugApp;
5931 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5932 mAlwaysFinishActivities = alwaysFinishActivities;
5933 // This happens before any activities are started, so we can
5934 // change mConfiguration in-place.
5935 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005936 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005937 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 }
5939 }
5940
5941 public boolean testIsSystemReady() {
5942 // no need to synchronize(this) just to read & return the value
5943 return mSystemReady;
5944 }
5945
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005946 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 // In the simulator, startRunning will never have been called, which
5948 // normally sets a few crucial variables. Do it here instead.
5949 if (!Process.supportsProcesses()) {
5950 mStartRunning = true;
5951 mTopAction = Intent.ACTION_MAIN;
5952 }
5953
5954 synchronized(this) {
5955 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005956 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 return;
5958 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005959
5960 // Check to see if there are any update receivers to run.
5961 if (!mDidUpdate) {
5962 if (mWaitingUpdate) {
5963 return;
5964 }
5965 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5966 List<ResolveInfo> ris = null;
5967 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005968 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005969 intent, null, 0);
5970 } catch (RemoteException e) {
5971 }
5972 if (ris != null) {
5973 for (int i=ris.size()-1; i>=0; i--) {
5974 if ((ris.get(i).activityInfo.applicationInfo.flags
5975 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5976 ris.remove(i);
5977 }
5978 }
5979 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5980 for (int i=0; i<ris.size(); i++) {
5981 ActivityInfo ai = ris.get(i).activityInfo;
5982 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5983 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005984 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005985 finisher = new IIntentReceiver.Stub() {
5986 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005987 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07005988 boolean sticky) {
5989 // The raw IIntentReceiver interface is called
5990 // with the AM lock held, so redispatch to
5991 // execute our code without the lock.
5992 mHandler.post(new Runnable() {
5993 public void run() {
5994 synchronized (ActivityManagerService.this) {
5995 mDidUpdate = true;
5996 }
5997 systemReady(goingCallback);
5998 }
5999 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006000 }
6001 };
6002 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006003 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006004 broadcastIntentLocked(null, null, intent, null, finisher,
6005 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006006 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006007 mWaitingUpdate = true;
6008 }
6009 }
6010 }
6011 if (mWaitingUpdate) {
6012 return;
6013 }
6014 mDidUpdate = true;
6015 }
6016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017 mSystemReady = true;
6018 if (!mStartRunning) {
6019 return;
6020 }
6021 }
6022
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006023 ArrayList<ProcessRecord> procsToKill = null;
6024 synchronized(mPidsSelfLocked) {
6025 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6026 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6027 if (!isAllowedWhileBooting(proc.info)){
6028 if (procsToKill == null) {
6029 procsToKill = new ArrayList<ProcessRecord>();
6030 }
6031 procsToKill.add(proc);
6032 }
6033 }
6034 }
6035
6036 if (procsToKill != null) {
6037 synchronized(this) {
6038 for (int i=procsToKill.size()-1; i>=0; i--) {
6039 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006040 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006041 removeProcessLocked(proc, true);
6042 }
6043 }
6044 }
6045
Joe Onorato8a9b2202010-02-26 18:56:32 -08006046 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006047 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 SystemClock.uptimeMillis());
6049
6050 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006051 // Make sure we have no pre-ready processes sitting around.
6052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6054 ResolveInfo ri = mContext.getPackageManager()
6055 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006056 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006057 CharSequence errorMsg = null;
6058 if (ri != null) {
6059 ActivityInfo ai = ri.activityInfo;
6060 ApplicationInfo app = ai.applicationInfo;
6061 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6062 mTopAction = Intent.ACTION_FACTORY_TEST;
6063 mTopData = null;
6064 mTopComponent = new ComponentName(app.packageName,
6065 ai.name);
6066 } else {
6067 errorMsg = mContext.getResources().getText(
6068 com.android.internal.R.string.factorytest_not_system);
6069 }
6070 } else {
6071 errorMsg = mContext.getResources().getText(
6072 com.android.internal.R.string.factorytest_no_action);
6073 }
6074 if (errorMsg != null) {
6075 mTopAction = null;
6076 mTopData = null;
6077 mTopComponent = null;
6078 Message msg = Message.obtain();
6079 msg.what = SHOW_FACTORY_ERROR_MSG;
6080 msg.getData().putCharSequence("msg", errorMsg);
6081 mHandler.sendMessage(msg);
6082 }
6083 }
6084 }
6085
6086 retrieveSettings();
6087
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006088 if (goingCallback != null) goingCallback.run();
6089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 synchronized (this) {
6091 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6092 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006093 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006094 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006095 if (apps != null) {
6096 int N = apps.size();
6097 int i;
6098 for (i=0; i<N; i++) {
6099 ApplicationInfo info
6100 = (ApplicationInfo)apps.get(i);
6101 if (info != null &&
6102 !info.packageName.equals("android")) {
6103 addAppLocked(info);
6104 }
6105 }
6106 }
6107 } catch (RemoteException ex) {
6108 // pm is in same process, this will never happen.
6109 }
6110 }
6111
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006112 // Start up initial activity.
6113 mBooting = true;
6114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006116 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006117 Message msg = Message.obtain();
6118 msg.what = SHOW_UID_ERROR_MSG;
6119 mHandler.sendMessage(msg);
6120 }
6121 } catch (RemoteException e) {
6122 }
6123
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006124 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006125 }
6126 }
6127
Dan Egnorb7f03672009-12-09 16:22:32 -08006128 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006129 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006130 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006131 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006132 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006133 startAppProblemLocked(app);
6134 app.stopFreezingAllLocked();
6135 return handleAppCrashLocked(app);
6136 }
6137
Dan Egnorb7f03672009-12-09 16:22:32 -08006138 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006139 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006140 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006141 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006142 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6143 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006144 startAppProblemLocked(app);
6145 app.stopFreezingAllLocked();
6146 }
6147
6148 /**
6149 * Generate a process error record, suitable for attachment to a ProcessRecord.
6150 *
6151 * @param app The ProcessRecord in which the error occurred.
6152 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6153 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006154 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006155 * @param shortMsg Short message describing the crash.
6156 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006157 * @param stackTrace Full crash stack trace, may be null.
6158 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006159 * @return Returns a fully-formed AppErrorStateInfo record.
6160 */
6161 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006162 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006163 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006165 report.condition = condition;
6166 report.processName = app.processName;
6167 report.pid = app.pid;
6168 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006169 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006170 report.shortMsg = shortMsg;
6171 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006172 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006173
6174 return report;
6175 }
6176
Dan Egnor42471dd2010-01-07 17:25:22 -08006177 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006178 synchronized (this) {
6179 app.crashing = false;
6180 app.crashingReport = null;
6181 app.notResponding = false;
6182 app.notRespondingReport = null;
6183 if (app.anrDialog == fromDialog) {
6184 app.anrDialog = null;
6185 }
6186 if (app.waitDialog == fromDialog) {
6187 app.waitDialog = null;
6188 }
6189 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006190 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006191 Slog.i(ActivityManagerService.TAG, "Killing "
6192 + app.processName + " (pid=" + app.pid + "): user's request");
6193 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6194 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006195 Process.killProcess(app.pid);
6196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006197 }
6198 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006199
Dan Egnorb7f03672009-12-09 16:22:32 -08006200 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 long now = SystemClock.uptimeMillis();
6202
6203 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6204 app.info.uid);
6205 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6206 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006207 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006208 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006209 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006210 app.info.processName, app.info.uid);
6211 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006212 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6213 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006214 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006215 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006216 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006217 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 }
6219 }
6220 if (!app.persistent) {
6221 // We don't want to start this process again until the user
6222 // explicitly does so... but for persistent process, we really
6223 // need to keep it running. If a persistent process is actually
6224 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006225 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006226 app.info.processName);
6227 mBadProcesses.put(app.info.processName, app.info.uid, now);
6228 app.bad = true;
6229 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6230 app.removed = true;
6231 removeProcessLocked(app, false);
6232 return false;
6233 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006234 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006235 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006236 if (r.app == app) {
6237 // If the top running activity is from this crashing
6238 // process, then terminate it to avoid getting in a loop.
6239 Slog.w(TAG, " Force finishing activity "
6240 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006241 int index = mMainStack.indexOfTokenLocked(r);
6242 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006243 Activity.RESULT_CANCELED, null, "crashed");
6244 // Also terminate an activities below it that aren't yet
6245 // stopped, to avoid a situation where one will get
6246 // re-start our crashing activity once it gets resumed again.
6247 index--;
6248 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006249 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006250 if (r.state == ActivityState.RESUMED
6251 || r.state == ActivityState.PAUSING
6252 || r.state == ActivityState.PAUSED) {
6253 if (!r.isHomeActivity) {
6254 Slog.w(TAG, " Force finishing activity "
6255 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006256 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006257 Activity.RESULT_CANCELED, null, "crashed");
6258 }
6259 }
6260 }
6261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006262 }
6263
6264 // Bump up the crash count of any services currently running in the proc.
6265 if (app.services.size() != 0) {
6266 // Any services running in the application need to be placed
6267 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006268 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006269 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006270 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 sr.crashCount++;
6272 }
6273 }
6274
6275 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6276 return true;
6277 }
6278
6279 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006280 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6281 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006282 skipCurrentReceiverLocked(app);
6283 }
6284
6285 void skipCurrentReceiverLocked(ProcessRecord app) {
6286 boolean reschedule = false;
6287 BroadcastRecord r = app.curReceiver;
6288 if (r != null) {
6289 // The current broadcast is waiting for this app's receiver
6290 // to be finished. Looks like that's not going to happen, so
6291 // let the broadcast continue.
6292 logBroadcastReceiverDiscard(r);
6293 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6294 r.resultExtras, r.resultAbort, true);
6295 reschedule = true;
6296 }
6297 r = mPendingBroadcast;
6298 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006299 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006300 "skip & discard pending app " + r);
6301 logBroadcastReceiverDiscard(r);
6302 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6303 r.resultExtras, r.resultAbort, true);
6304 reschedule = true;
6305 }
6306 if (reschedule) {
6307 scheduleBroadcastsLocked();
6308 }
6309 }
6310
Dan Egnor60d87622009-12-16 16:32:58 -08006311 /**
6312 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6313 * The application process will exit immediately after this call returns.
6314 * @param app object of the crashing app, null for the system server
6315 * @param crashInfo describing the exception
6316 */
6317 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6318 ProcessRecord r = findAppProcess(app);
6319
6320 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6321 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006322 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006323 crashInfo.exceptionClassName,
6324 crashInfo.exceptionMessage,
6325 crashInfo.throwFileName,
6326 crashInfo.throwLineNumber);
6327
Dan Egnor42471dd2010-01-07 17:25:22 -08006328 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006329
6330 crashApplication(r, crashInfo);
6331 }
6332
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006333 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006334 IBinder app,
6335 int violationMask,
6336 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006337 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006338
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006339 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006340 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006341 boolean logIt = true;
6342 synchronized (mAlreadyLoggedViolatedStacks) {
6343 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6344 logIt = false;
6345 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006346 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006347 // the relative pain numbers, without logging all
6348 // the stack traces repeatedly. We'd want to do
6349 // likewise in the client code, which also does
6350 // dup suppression, before the Binder call.
6351 } else {
6352 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6353 mAlreadyLoggedViolatedStacks.clear();
6354 }
6355 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6356 }
6357 }
6358 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006359 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006360 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006361 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006362
6363 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6364 AppErrorResult result = new AppErrorResult();
6365 synchronized (this) {
6366 final long origId = Binder.clearCallingIdentity();
6367
6368 Message msg = Message.obtain();
6369 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6370 HashMap<String, Object> data = new HashMap<String, Object>();
6371 data.put("result", result);
6372 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006373 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006374 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006375 msg.obj = data;
6376 mHandler.sendMessage(msg);
6377
6378 Binder.restoreCallingIdentity(origId);
6379 }
6380 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006381 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006382 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006383 }
6384
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006385 // Depending on the policy in effect, there could be a bunch of
6386 // these in quick succession so we try to batch these together to
6387 // minimize disk writes, number of dropbox entries, and maximize
6388 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006389 private void logStrictModeViolationToDropBox(
6390 ProcessRecord process,
6391 StrictMode.ViolationInfo info) {
6392 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006393 return;
6394 }
6395 final boolean isSystemApp = process == null ||
6396 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6397 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6398 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6399 final DropBoxManager dbox = (DropBoxManager)
6400 mContext.getSystemService(Context.DROPBOX_SERVICE);
6401
6402 // Exit early if the dropbox isn't configured to accept this report type.
6403 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6404
6405 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006406 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006407 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6408 synchronized (sb) {
6409 bufferWasEmpty = sb.length() == 0;
6410 appendDropBoxProcessHeaders(process, sb);
6411 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6412 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006413 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6414 if (info.violationNumThisLoop != 0) {
6415 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6416 }
6417 if (info != null && info.durationMillis != -1) {
6418 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006419 }
6420 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006421 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6422 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006423 }
6424 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006425
6426 // Only buffer up to ~64k. Various logging bits truncate
6427 // things at 128k.
6428 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006429 }
6430
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006431 // Flush immediately if the buffer's grown too large, or this
6432 // is a non-system app. Non-system apps are isolated with a
6433 // different tag & policy and not batched.
6434 //
6435 // Batching is useful during internal testing with
6436 // StrictMode settings turned up high. Without batching,
6437 // thousands of separate files could be created on boot.
6438 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006439 new Thread("Error dump: " + dropboxTag) {
6440 @Override
6441 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006442 String report;
6443 synchronized (sb) {
6444 report = sb.toString();
6445 sb.delete(0, sb.length());
6446 sb.trimToSize();
6447 }
6448 if (report.length() != 0) {
6449 dbox.addText(dropboxTag, report);
6450 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006451 }
6452 }.start();
6453 return;
6454 }
6455
6456 // System app batching:
6457 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006458 // An existing dropbox-writing thread is outstanding, so
6459 // we don't need to start it up. The existing thread will
6460 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006461 return;
6462 }
6463
6464 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6465 // (After this point, we shouldn't access AMS internal data structures.)
6466 new Thread("Error dump: " + dropboxTag) {
6467 @Override
6468 public void run() {
6469 // 5 second sleep to let stacks arrive and be batched together
6470 try {
6471 Thread.sleep(5000); // 5 seconds
6472 } catch (InterruptedException e) {}
6473
6474 String errorReport;
6475 synchronized (mStrictModeBuffer) {
6476 errorReport = mStrictModeBuffer.toString();
6477 if (errorReport.length() == 0) {
6478 return;
6479 }
6480 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6481 mStrictModeBuffer.trimToSize();
6482 }
6483 dbox.addText(dropboxTag, errorReport);
6484 }
6485 }.start();
6486 }
6487
Dan Egnor60d87622009-12-16 16:32:58 -08006488 /**
6489 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6490 * @param app object of the crashing app, null for the system server
6491 * @param tag reported by the caller
6492 * @param crashInfo describing the context of the error
6493 * @return true if the process should exit immediately (WTF is fatal)
6494 */
6495 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006496 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006497 ProcessRecord r = findAppProcess(app);
6498
6499 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6500 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006501 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006502 tag, crashInfo.exceptionMessage);
6503
Dan Egnor42471dd2010-01-07 17:25:22 -08006504 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006505
Doug Zongker43866e02010-01-07 12:09:54 -08006506 if (Settings.Secure.getInt(mContext.getContentResolver(),
6507 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006508 crashApplication(r, crashInfo);
6509 return true;
6510 } else {
6511 return false;
6512 }
6513 }
6514
6515 /**
6516 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6517 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6518 */
6519 private ProcessRecord findAppProcess(IBinder app) {
6520 if (app == null) {
6521 return null;
6522 }
6523
6524 synchronized (this) {
6525 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6526 final int NA = apps.size();
6527 for (int ia=0; ia<NA; ia++) {
6528 ProcessRecord p = apps.valueAt(ia);
6529 if (p.thread != null && p.thread.asBinder() == app) {
6530 return p;
6531 }
6532 }
6533 }
6534
Joe Onorato8a9b2202010-02-26 18:56:32 -08006535 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006536 return null;
6537 }
6538 }
6539
6540 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006541 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6542 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006543 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006544 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6545 // Note: ProcessRecord 'process' is guarded by the service
6546 // instance. (notably process.pkgList, which could otherwise change
6547 // concurrently during execution of this method)
6548 synchronized (this) {
6549 if (process == null || process.pid == MY_PID) {
6550 sb.append("Process: system_server\n");
6551 } else {
6552 sb.append("Process: ").append(process.processName).append("\n");
6553 }
6554 if (process == null) {
6555 return;
6556 }
Dan Egnora455d192010-03-12 08:52:28 -08006557 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006558 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006559 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6560 for (String pkg : process.pkgList) {
6561 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006562 try {
Dan Egnora455d192010-03-12 08:52:28 -08006563 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6564 if (pi != null) {
6565 sb.append(" v").append(pi.versionCode);
6566 if (pi.versionName != null) {
6567 sb.append(" (").append(pi.versionName).append(")");
6568 }
6569 }
6570 } catch (RemoteException e) {
6571 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006572 }
Dan Egnora455d192010-03-12 08:52:28 -08006573 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006574 }
Dan Egnora455d192010-03-12 08:52:28 -08006575 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006576 }
6577
6578 private static String processClass(ProcessRecord process) {
6579 if (process == null || process.pid == MY_PID) {
6580 return "system_server";
6581 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6582 return "system_app";
6583 } else {
6584 return "data_app";
6585 }
6586 }
6587
6588 /**
6589 * Write a description of an error (crash, WTF, ANR) to the drop box.
6590 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6591 * @param process which caused the error, null means the system server
6592 * @param activity which triggered the error, null if unknown
6593 * @param parent activity related to the error, null if unknown
6594 * @param subject line related to the error, null if absent
6595 * @param report in long form describing the error, null if absent
6596 * @param logFile to include in the report, null if none
6597 * @param crashInfo giving an application stack trace, null if absent
6598 */
6599 public void addErrorToDropBox(String eventType,
6600 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6601 final String report, final File logFile,
6602 final ApplicationErrorReport.CrashInfo crashInfo) {
6603 // NOTE -- this must never acquire the ActivityManagerService lock,
6604 // otherwise the watchdog may be prevented from resetting the system.
6605
6606 final String dropboxTag = processClass(process) + "_" + eventType;
6607 final DropBoxManager dbox = (DropBoxManager)
6608 mContext.getSystemService(Context.DROPBOX_SERVICE);
6609
6610 // Exit early if the dropbox isn't configured to accept this report type.
6611 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6612
6613 final StringBuilder sb = new StringBuilder(1024);
6614 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006615 if (activity != null) {
6616 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6617 }
6618 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6619 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6620 }
6621 if (parent != null && parent != activity) {
6622 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6623 }
6624 if (subject != null) {
6625 sb.append("Subject: ").append(subject).append("\n");
6626 }
6627 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6628 sb.append("\n");
6629
6630 // Do the rest in a worker thread to avoid blocking the caller on I/O
6631 // (After this point, we shouldn't access AMS internal data structures.)
6632 Thread worker = new Thread("Error dump: " + dropboxTag) {
6633 @Override
6634 public void run() {
6635 if (report != null) {
6636 sb.append(report);
6637 }
6638 if (logFile != null) {
6639 try {
6640 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6641 } catch (IOException e) {
6642 Slog.e(TAG, "Error reading " + logFile, e);
6643 }
6644 }
6645 if (crashInfo != null && crashInfo.stackTrace != null) {
6646 sb.append(crashInfo.stackTrace);
6647 }
6648
6649 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6650 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6651 if (lines > 0) {
6652 sb.append("\n");
6653
6654 // Merge several logcat streams, and take the last N lines
6655 InputStreamReader input = null;
6656 try {
6657 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6658 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6659 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6660
6661 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6662 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6663 input = new InputStreamReader(logcat.getInputStream());
6664
6665 int num;
6666 char[] buf = new char[8192];
6667 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6668 } catch (IOException e) {
6669 Slog.e(TAG, "Error running logcat", e);
6670 } finally {
6671 if (input != null) try { input.close(); } catch (IOException e) {}
6672 }
6673 }
6674
6675 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006676 }
Dan Egnora455d192010-03-12 08:52:28 -08006677 };
6678
6679 if (process == null || process.pid == MY_PID) {
6680 worker.run(); // We may be about to die -- need to run this synchronously
6681 } else {
6682 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006683 }
6684 }
6685
6686 /**
6687 * Bring up the "unexpected error" dialog box for a crashing app.
6688 * Deal with edge cases (intercepts from instrumented applications,
6689 * ActivityController, error intent receivers, that sort of thing).
6690 * @param r the application crashing
6691 * @param crashInfo describing the failure
6692 */
6693 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006694 long timeMillis = System.currentTimeMillis();
6695 String shortMsg = crashInfo.exceptionClassName;
6696 String longMsg = crashInfo.exceptionMessage;
6697 String stackTrace = crashInfo.stackTrace;
6698 if (shortMsg != null && longMsg != null) {
6699 longMsg = shortMsg + ": " + longMsg;
6700 } else if (shortMsg != null) {
6701 longMsg = shortMsg;
6702 }
6703
Dan Egnor60d87622009-12-16 16:32:58 -08006704 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006706 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 try {
6708 String name = r != null ? r.processName : null;
6709 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006710 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006711 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006712 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006713 + " at watcher's request");
6714 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006715 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006716 }
6717 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006718 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006719 }
6720 }
6721
6722 final long origId = Binder.clearCallingIdentity();
6723
6724 // If this process is running instrumentation, finish it.
6725 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006726 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006727 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006728 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6729 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 Bundle info = new Bundle();
6731 info.putString("shortMsg", shortMsg);
6732 info.putString("longMsg", longMsg);
6733 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6734 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006735 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006736 }
6737
Dan Egnor60d87622009-12-16 16:32:58 -08006738 // If we can't identify the process or it's already exceeded its crash quota,
6739 // quit right away without showing a crash dialog.
6740 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006742 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006743 }
6744
6745 Message msg = Message.obtain();
6746 msg.what = SHOW_ERROR_MSG;
6747 HashMap data = new HashMap();
6748 data.put("result", result);
6749 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006750 msg.obj = data;
6751 mHandler.sendMessage(msg);
6752
6753 Binder.restoreCallingIdentity(origId);
6754 }
6755
6756 int res = result.get();
6757
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006758 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006759 synchronized (this) {
6760 if (r != null) {
6761 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6762 SystemClock.uptimeMillis());
6763 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006764 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006765 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006766 }
6767 }
6768
6769 if (appErrorIntent != null) {
6770 try {
6771 mContext.startActivity(appErrorIntent);
6772 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006773 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006777
6778 Intent createAppErrorIntentLocked(ProcessRecord r,
6779 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6780 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006781 if (report == null) {
6782 return null;
6783 }
6784 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6785 result.setComponent(r.errorReportReceiver);
6786 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6787 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6788 return result;
6789 }
6790
Dan Egnorb7f03672009-12-09 16:22:32 -08006791 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6792 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006793 if (r.errorReportReceiver == null) {
6794 return null;
6795 }
6796
6797 if (!r.crashing && !r.notResponding) {
6798 return null;
6799 }
6800
Dan Egnorb7f03672009-12-09 16:22:32 -08006801 ApplicationErrorReport report = new ApplicationErrorReport();
6802 report.packageName = r.info.packageName;
6803 report.installerPackageName = r.errorReportReceiver.getPackageName();
6804 report.processName = r.processName;
6805 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006806 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006807
Dan Egnorb7f03672009-12-09 16:22:32 -08006808 if (r.crashing) {
6809 report.type = ApplicationErrorReport.TYPE_CRASH;
6810 report.crashInfo = crashInfo;
6811 } else if (r.notResponding) {
6812 report.type = ApplicationErrorReport.TYPE_ANR;
6813 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006814
Dan Egnorb7f03672009-12-09 16:22:32 -08006815 report.anrInfo.activity = r.notRespondingReport.tag;
6816 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6817 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006818 }
6819
Dan Egnorb7f03672009-12-09 16:22:32 -08006820 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006821 }
6822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6824 // assume our apps are happy - lazy create the list
6825 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6826
6827 synchronized (this) {
6828
6829 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006830 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6831 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006832 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6833 // This one's in trouble, so we'll generate a report for it
6834 // crashes are higher priority (in case there's a crash *and* an anr)
6835 ActivityManager.ProcessErrorStateInfo report = null;
6836 if (app.crashing) {
6837 report = app.crashingReport;
6838 } else if (app.notResponding) {
6839 report = app.notRespondingReport;
6840 }
6841
6842 if (report != null) {
6843 if (errList == null) {
6844 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6845 }
6846 errList.add(report);
6847 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006848 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006849 " crashing = " + app.crashing +
6850 " notResponding = " + app.notResponding);
6851 }
6852 }
6853 }
6854 }
6855
6856 return errList;
6857 }
6858
6859 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6860 // Lazy instantiation of list
6861 List<ActivityManager.RunningAppProcessInfo> runList = null;
6862 synchronized (this) {
6863 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006864 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6865 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006866 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6867 // Generate process state info for running application
6868 ActivityManager.RunningAppProcessInfo currApp =
6869 new ActivityManager.RunningAppProcessInfo(app.processName,
6870 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006871 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006872 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07006873 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006874 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006875 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006876 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006877 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6878 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6879 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006880 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6881 } else if (adj >= HOME_APP_ADJ) {
6882 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6883 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006884 } else if (adj >= SECONDARY_SERVER_ADJ) {
6885 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006886 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6887 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6888 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6889 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006890 } else if (adj >= VISIBLE_APP_ADJ) {
6891 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6892 } else {
6893 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6894 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006895 currApp.importanceReasonCode = app.adjTypeCode;
6896 if (app.adjSource instanceof ProcessRecord) {
6897 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006898 } else if (app.adjSource instanceof ActivityRecord) {
6899 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006900 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6901 }
6902 if (app.adjTarget instanceof ComponentName) {
6903 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6904 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006905 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906 // + " lru=" + currApp.lru);
6907 if (runList == null) {
6908 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6909 }
6910 runList.add(currApp);
6911 }
6912 }
6913 }
6914 return runList;
6915 }
6916
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006917 public List<ApplicationInfo> getRunningExternalApplications() {
6918 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6919 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6920 if (runningApps != null && runningApps.size() > 0) {
6921 Set<String> extList = new HashSet<String>();
6922 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6923 if (app.pkgList != null) {
6924 for (String pkg : app.pkgList) {
6925 extList.add(pkg);
6926 }
6927 }
6928 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006929 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006930 for (String pkg : extList) {
6931 try {
6932 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6933 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6934 retList.add(info);
6935 }
6936 } catch (RemoteException e) {
6937 }
6938 }
6939 }
6940 return retList;
6941 }
6942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006943 @Override
6944 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006945 if (checkCallingPermission(android.Manifest.permission.DUMP)
6946 != PackageManager.PERMISSION_GRANTED) {
6947 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6948 + Binder.getCallingPid()
6949 + ", uid=" + Binder.getCallingUid()
6950 + " without permission "
6951 + android.Manifest.permission.DUMP);
6952 return;
6953 }
6954
6955 boolean dumpAll = false;
6956
6957 int opti = 0;
6958 while (opti < args.length) {
6959 String opt = args[opti];
6960 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6961 break;
6962 }
6963 opti++;
6964 if ("-a".equals(opt)) {
6965 dumpAll = true;
6966 } else if ("-h".equals(opt)) {
6967 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006968 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006969 pw.println(" cmd may be one of:");
6970 pw.println(" activities: activity stack state");
6971 pw.println(" broadcasts: broadcast state");
6972 pw.println(" intents: pending intent state");
6973 pw.println(" processes: process state");
6974 pw.println(" providers: content provider state");
6975 pw.println(" services: service state");
6976 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006977 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006978 } else {
6979 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006980 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006981 }
6982
6983 // Is the caller requesting to dump a particular piece of data?
6984 if (opti < args.length) {
6985 String cmd = args[opti];
6986 opti++;
6987 if ("activities".equals(cmd) || "a".equals(cmd)) {
6988 synchronized (this) {
6989 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006990 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006991 return;
6992 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6993 synchronized (this) {
6994 dumpBroadcastsLocked(fd, pw, args, opti, true);
6995 }
6996 return;
6997 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6998 synchronized (this) {
6999 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7000 }
7001 return;
7002 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7003 synchronized (this) {
7004 dumpProcessesLocked(fd, pw, args, opti, true);
7005 }
7006 return;
7007 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7008 synchronized (this) {
7009 dumpProvidersLocked(fd, pw, args, opti, true);
7010 }
7011 return;
7012 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007013 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007014 return;
7015 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7016 synchronized (this) {
7017 dumpServicesLocked(fd, pw, args, opti, true);
7018 }
7019 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007020 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007021 }
7022
7023 // No piece of data specified, dump everything.
7024 synchronized (this) {
7025 boolean needSep;
7026 if (dumpAll) {
7027 pw.println("Providers in Current Activity Manager State:");
7028 }
7029 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7030 if (needSep) {
7031 pw.println(" ");
7032 }
7033 if (dumpAll) {
7034 pw.println("-------------------------------------------------------------------------------");
7035 pw.println("Broadcasts in Current Activity Manager State:");
7036 }
7037 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7038 if (needSep) {
7039 pw.println(" ");
7040 }
7041 if (dumpAll) {
7042 pw.println("-------------------------------------------------------------------------------");
7043 pw.println("Services in Current Activity Manager State:");
7044 }
7045 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7046 if (needSep) {
7047 pw.println(" ");
7048 }
7049 if (dumpAll) {
7050 pw.println("-------------------------------------------------------------------------------");
7051 pw.println("PendingIntents in Current Activity Manager State:");
7052 }
7053 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7054 if (needSep) {
7055 pw.println(" ");
7056 }
7057 if (dumpAll) {
7058 pw.println("-------------------------------------------------------------------------------");
7059 pw.println("Activities in Current Activity Manager State:");
7060 }
7061 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7062 if (needSep) {
7063 pw.println(" ");
7064 }
7065 if (dumpAll) {
7066 pw.println("-------------------------------------------------------------------------------");
7067 pw.println("Processes in Current Activity Manager State:");
7068 }
7069 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7070 }
7071 }
7072
7073 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7074 int opti, boolean dumpAll, boolean needHeader) {
7075 if (needHeader) {
7076 pw.println(" Activity stack:");
7077 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007078 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007079 pw.println(" ");
7080 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007081 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7082 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007083 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007084 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007085 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007086 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007087 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007088 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007089 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007090 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007091 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007092 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007093 pw.println(" ");
7094 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007095 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007097
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007098 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007099 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7100 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007101 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007102 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007103
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007104 if (dumpAll && mRecentTasks.size() > 0) {
7105 pw.println(" ");
7106 pw.println("Recent tasks in Current Activity Manager State:");
7107
7108 final int N = mRecentTasks.size();
7109 for (int i=0; i<N; i++) {
7110 TaskRecord tr = mRecentTasks.get(i);
7111 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7112 pw.println(tr);
7113 mRecentTasks.get(i).dump(pw, " ");
7114 }
7115 }
7116
7117 pw.println(" ");
7118 pw.println(" mCurTask: " + mCurTask);
7119
7120 return true;
7121 }
7122
7123 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7124 int opti, boolean dumpAll) {
7125 boolean needSep = false;
7126 int numPers = 0;
7127
7128 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007129 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7130 final int NA = procs.size();
7131 for (int ia=0; ia<NA; ia++) {
7132 if (!needSep) {
7133 pw.println(" All known processes:");
7134 needSep = true;
7135 }
7136 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007137 pw.print(r.persistent ? " *PERS*" : " *APP*");
7138 pw.print(" UID "); pw.print(procs.keyAt(ia));
7139 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 r.dump(pw, " ");
7141 if (r.persistent) {
7142 numPers++;
7143 }
7144 }
7145 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007146 }
7147
7148 if (mLruProcesses.size() > 0) {
7149 if (needSep) pw.println(" ");
7150 needSep = true;
7151 pw.println(" Running processes (most recent first):");
7152 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007153 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007154 needSep = true;
7155 }
7156
7157 synchronized (mPidsSelfLocked) {
7158 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007159 if (needSep) pw.println(" ");
7160 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007161 pw.println(" PID mappings:");
7162 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7163 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7164 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 }
7166 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007167 }
7168
7169 if (mForegroundProcesses.size() > 0) {
7170 if (needSep) pw.println(" ");
7171 needSep = true;
7172 pw.println(" Foreground Processes:");
7173 for (int i=0; i<mForegroundProcesses.size(); i++) {
7174 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7175 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007176 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007177 }
7178
7179 if (mPersistentStartingProcesses.size() > 0) {
7180 if (needSep) pw.println(" ");
7181 needSep = true;
7182 pw.println(" Persisent processes that are starting:");
7183 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
7184 "Starting Norm", "Restarting PERS", false);
7185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007187 if (mStartingProcesses.size() > 0) {
7188 if (needSep) pw.println(" ");
7189 needSep = true;
7190 pw.println(" Processes that are starting:");
7191 dumpProcessList(pw, this, mStartingProcesses, " ",
7192 "Starting Norm", "Starting PERS", false);
7193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007195 if (mRemovedProcesses.size() > 0) {
7196 if (needSep) pw.println(" ");
7197 needSep = true;
7198 pw.println(" Processes that are being removed:");
7199 dumpProcessList(pw, this, mRemovedProcesses, " ",
7200 "Removed Norm", "Removed PERS", false);
7201 }
7202
7203 if (mProcessesOnHold.size() > 0) {
7204 if (needSep) pw.println(" ");
7205 needSep = true;
7206 pw.println(" Processes that are on old until the system is ready:");
7207 dumpProcessList(pw, this, mProcessesOnHold, " ",
7208 "OnHold Norm", "OnHold PERS", false);
7209 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007210
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007211 if (mProcessesToGc.size() > 0) {
7212 if (needSep) pw.println(" ");
7213 needSep = true;
7214 pw.println(" Processes that are waiting to GC:");
7215 long now = SystemClock.uptimeMillis();
7216 for (int i=0; i<mProcessesToGc.size(); i++) {
7217 ProcessRecord proc = mProcessesToGc.get(i);
7218 pw.print(" Process "); pw.println(proc);
7219 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7220 pw.print(", last gced=");
7221 pw.print(now-proc.lastRequestedGc);
7222 pw.print(" ms ago, last lowMem=");
7223 pw.print(now-proc.lastLowMemory);
7224 pw.println(" ms ago");
7225
7226 }
7227 }
7228
7229 if (mProcessCrashTimes.getMap().size() > 0) {
7230 if (needSep) pw.println(" ");
7231 needSep = true;
7232 pw.println(" Time since processes crashed:");
7233 long now = SystemClock.uptimeMillis();
7234 for (Map.Entry<String, SparseArray<Long>> procs
7235 : mProcessCrashTimes.getMap().entrySet()) {
7236 SparseArray<Long> uids = procs.getValue();
7237 final int N = uids.size();
7238 for (int i=0; i<N; i++) {
7239 pw.print(" Process "); pw.print(procs.getKey());
7240 pw.print(" uid "); pw.print(uids.keyAt(i));
7241 pw.print(": last crashed ");
7242 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007243 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007244 }
7245 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007247
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007248 if (mBadProcesses.getMap().size() > 0) {
7249 if (needSep) pw.println(" ");
7250 needSep = true;
7251 pw.println(" Bad processes:");
7252 for (Map.Entry<String, SparseArray<Long>> procs
7253 : mBadProcesses.getMap().entrySet()) {
7254 SparseArray<Long> uids = procs.getValue();
7255 final int N = uids.size();
7256 for (int i=0; i<N; i++) {
7257 pw.print(" Bad process "); pw.print(procs.getKey());
7258 pw.print(" uid "); pw.print(uids.keyAt(i));
7259 pw.print(": crashed at time ");
7260 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007261 }
7262 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007264
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007265 pw.println(" ");
7266 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007267 if (mHeavyWeightProcess != null) {
7268 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7269 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007270 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007271 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007272 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7273 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7274 || mOrigWaitForDebugger) {
7275 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7276 + " mDebugTransient=" + mDebugTransient
7277 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7278 }
7279 if (mAlwaysFinishActivities || mController != null) {
7280 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7281 + " mController=" + mController);
7282 }
7283 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007284 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007285 pw.println(" mStartRunning=" + mStartRunning
7286 + " mSystemReady=" + mSystemReady
7287 + " mBooting=" + mBooting
7288 + " mBooted=" + mBooted
7289 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007290 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7291 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007292 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007293 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007294
7295 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296 }
7297
7298 /**
7299 * There are three ways to call this:
7300 * - no service specified: dump all the services
7301 * - a flattened component name that matched an existing service was specified as the
7302 * first arg: dump that one service
7303 * - the first arg isn't the flattened component name of an existing service:
7304 * dump all services whose component contains the first arg as a substring
7305 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007306 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7307 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 String[] newArgs;
7309 String componentNameString;
7310 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007311 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007312 componentNameString = null;
7313 newArgs = EMPTY_STRING_ARRAY;
7314 r = null;
7315 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007316 componentNameString = args[opti];
7317 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007318 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007319 synchronized (this) {
7320 r = componentName != null ? mServices.get(componentName) : null;
7321 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007322 newArgs = new String[args.length - opti];
7323 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 }
7325
7326 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007327 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007328 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007329 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7330 synchronized (this) {
7331 for (ServiceRecord r1 : mServices.values()) {
7332 if (componentNameString == null
7333 || r1.name.flattenToString().contains(componentNameString)) {
7334 services.add(r1);
7335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 }
7337 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007338 for (int i=0; i<services.size(); i++) {
7339 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341 }
7342 }
7343
7344 /**
7345 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7346 * there is a thread associated with the service.
7347 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007348 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7349 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007351 if (dumpAll) {
7352 synchronized (this) {
7353 pw.print(" * "); pw.println(r);
7354 r.dump(pw, " ");
7355 }
7356 pw.println("");
7357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007358 if (r.app != null && r.app.thread != null) {
7359 try {
7360 // flush anything that is already in the PrintWriter since the thread is going
7361 // to write to the file descriptor directly
7362 pw.flush();
7363 r.app.thread.dumpService(fd, r, args);
7364 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007365 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007366 } catch (RemoteException e) {
7367 pw.println("got a RemoteException while dumping the service");
7368 }
7369 }
7370 }
7371
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007372 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7373 int opti, boolean dumpAll) {
7374 boolean needSep = false;
7375
7376 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007377 if (mRegisteredReceivers.size() > 0) {
7378 pw.println(" ");
7379 pw.println(" Registered Receivers:");
7380 Iterator it = mRegisteredReceivers.values().iterator();
7381 while (it.hasNext()) {
7382 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007383 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 r.dump(pw, " ");
7385 }
7386 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 pw.println(" ");
7389 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007390 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007391 needSep = true;
7392 }
7393
7394 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7395 || mPendingBroadcast != null) {
7396 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007397 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007398 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007399 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007400 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7401 pw.println(" Broadcast #" + i + ":");
7402 mParallelBroadcasts.get(i).dump(pw, " ");
7403 }
7404 if (mOrderedBroadcasts.size() > 0) {
7405 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007406 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007407 }
7408 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7409 pw.println(" Serialized Broadcast #" + i + ":");
7410 mOrderedBroadcasts.get(i).dump(pw, " ");
7411 }
7412 pw.println(" ");
7413 pw.println(" Pending broadcast:");
7414 if (mPendingBroadcast != null) {
7415 mPendingBroadcast.dump(pw, " ");
7416 } else {
7417 pw.println(" (null)");
7418 }
7419 needSep = true;
7420 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007422 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007424 pw.println(" Historical broadcasts:");
7425 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7426 BroadcastRecord r = mBroadcastHistory[i];
7427 if (r == null) {
7428 break;
7429 }
7430 pw.println(" Historical Broadcast #" + i + ":");
7431 r.dump(pw, " ");
7432 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007433 needSep = true;
7434 }
7435
7436 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007437 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007438 pw.println(" Sticky broadcasts:");
7439 StringBuilder sb = new StringBuilder(128);
7440 for (Map.Entry<String, ArrayList<Intent>> ent
7441 : mStickyBroadcasts.entrySet()) {
7442 pw.print(" * Sticky action "); pw.print(ent.getKey());
7443 pw.println(":");
7444 ArrayList<Intent> intents = ent.getValue();
7445 final int N = intents.size();
7446 for (int i=0; i<N; i++) {
7447 sb.setLength(0);
7448 sb.append(" Intent: ");
7449 intents.get(i).toShortString(sb, true, false);
7450 pw.println(sb.toString());
7451 Bundle bundle = intents.get(i).getExtras();
7452 if (bundle != null) {
7453 pw.print(" ");
7454 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455 }
7456 }
7457 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007458 needSep = true;
7459 }
7460
7461 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007462 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007463 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007464 pw.println(" mHandler:");
7465 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007466 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007467 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007468
7469 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 }
7471
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007472 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7473 int opti, boolean dumpAll) {
7474 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007476 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007477 if (mServices.size() > 0) {
7478 pw.println(" Active services:");
7479 Iterator<ServiceRecord> it = mServices.values().iterator();
7480 while (it.hasNext()) {
7481 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007482 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007483 r.dump(pw, " ");
7484 }
7485 needSep = true;
7486 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007488
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007489 if (mPendingServices.size() > 0) {
7490 if (needSep) pw.println(" ");
7491 pw.println(" Pending services:");
7492 for (int i=0; i<mPendingServices.size(); i++) {
7493 ServiceRecord r = mPendingServices.get(i);
7494 pw.print(" * Pending "); pw.println(r);
7495 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007496 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007497 needSep = true;
7498 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007499
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007500 if (mRestartingServices.size() > 0) {
7501 if (needSep) pw.println(" ");
7502 pw.println(" Restarting services:");
7503 for (int i=0; i<mRestartingServices.size(); i++) {
7504 ServiceRecord r = mRestartingServices.get(i);
7505 pw.print(" * Restarting "); pw.println(r);
7506 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007507 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007508 needSep = true;
7509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007510
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007511 if (mStoppingServices.size() > 0) {
7512 if (needSep) pw.println(" ");
7513 pw.println(" Stopping services:");
7514 for (int i=0; i<mStoppingServices.size(); i++) {
7515 ServiceRecord r = mStoppingServices.get(i);
7516 pw.print(" * Stopping "); pw.println(r);
7517 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007519 needSep = true;
7520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007521
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007522 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 if (mServiceConnections.size() > 0) {
7524 if (needSep) pw.println(" ");
7525 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007526 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007527 = mServiceConnections.values().iterator();
7528 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007529 ArrayList<ConnectionRecord> r = it.next();
7530 for (int i=0; i<r.size(); i++) {
7531 pw.print(" * "); pw.println(r.get(i));
7532 r.get(i).dump(pw, " ");
7533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007535 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007536 }
7537 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007538
7539 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007540 }
7541
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007542 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7543 int opti, boolean dumpAll) {
7544 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007546 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007547 if (mProvidersByClass.size() > 0) {
7548 if (needSep) pw.println(" ");
7549 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007550 Iterator<Map.Entry<String, ContentProviderRecord>> it
7551 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007552 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007553 Map.Entry<String, ContentProviderRecord> e = it.next();
7554 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007555 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007556 r.dump(pw, " ");
7557 }
7558 needSep = true;
7559 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007560
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007561 if (mProvidersByName.size() > 0) {
7562 pw.println(" ");
7563 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007564 Iterator<Map.Entry<String, ContentProviderRecord>> it
7565 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007566 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007567 Map.Entry<String, ContentProviderRecord> e = it.next();
7568 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007569 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7570 pw.println(r);
7571 }
7572 needSep = true;
7573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007574 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007575
7576 if (mLaunchingProviders.size() > 0) {
7577 if (needSep) pw.println(" ");
7578 pw.println(" Launching content providers:");
7579 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7580 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7581 pw.println(mLaunchingProviders.get(i));
7582 }
7583 needSep = true;
7584 }
7585
7586 if (mGrantedUriPermissions.size() > 0) {
7587 pw.println();
7588 pw.println("Granted Uri Permissions:");
7589 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7590 int uid = mGrantedUriPermissions.keyAt(i);
7591 HashMap<Uri, UriPermission> perms
7592 = mGrantedUriPermissions.valueAt(i);
7593 pw.print(" * UID "); pw.print(uid);
7594 pw.println(" holds:");
7595 for (UriPermission perm : perms.values()) {
7596 pw.print(" "); pw.println(perm);
7597 perm.dump(pw, " ");
7598 }
7599 }
7600 needSep = true;
7601 }
7602
7603 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604 }
7605
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007606 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7607 int opti, boolean dumpAll) {
7608 boolean needSep = false;
7609
7610 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007611 if (this.mIntentSenderRecords.size() > 0) {
7612 Iterator<WeakReference<PendingIntentRecord>> it
7613 = mIntentSenderRecords.values().iterator();
7614 while (it.hasNext()) {
7615 WeakReference<PendingIntentRecord> ref = it.next();
7616 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007617 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007619 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007620 rec.dump(pw, " ");
7621 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007622 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007623 }
7624 }
7625 }
7626 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007627
7628 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 }
7630
7631 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007632 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 TaskRecord lastTask = null;
7634 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007635 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007636 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007637 if (lastTask != r.task) {
7638 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007639 pw.print(prefix);
7640 pw.print(full ? "* " : " ");
7641 pw.println(lastTask);
7642 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007643 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007644 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007645 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007646 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7647 pw.print(" #"); pw.print(i); pw.print(": ");
7648 pw.println(r);
7649 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007650 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 }
7653 }
7654
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007655 private static String buildOomTag(String prefix, String space, int val, int base) {
7656 if (val == base) {
7657 if (space == null) return prefix;
7658 return prefix + " ";
7659 }
7660 return prefix + "+" + Integer.toString(val-base);
7661 }
7662
7663 private static final int dumpProcessList(PrintWriter pw,
7664 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 String prefix, String normalLabel, String persistentLabel,
7666 boolean inclOomAdj) {
7667 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007668 final int N = list.size()-1;
7669 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007670 ProcessRecord r = (ProcessRecord)list.get(i);
7671 if (false) {
7672 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7673 + " #" + i + ":");
7674 r.dump(pw, prefix + " ");
7675 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007676 String oomAdj;
7677 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007678 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007679 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007680 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7681 } else if (r.setAdj >= HOME_APP_ADJ) {
7682 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7683 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7684 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7685 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7686 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007687 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7688 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7689 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7690 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007691 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7692 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7693 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7694 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007695 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007696 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007697 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007698 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007699 } else {
7700 oomAdj = Integer.toString(r.setAdj);
7701 }
7702 String schedGroup;
7703 switch (r.setSchedGroup) {
7704 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7705 schedGroup = "B";
7706 break;
7707 case Process.THREAD_GROUP_DEFAULT:
7708 schedGroup = "F";
7709 break;
7710 default:
7711 schedGroup = Integer.toString(r.setSchedGroup);
7712 break;
7713 }
7714 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007715 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007716 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007717 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007718 pw.print(prefix);
7719 pw.print(" ");
7720 if (r.adjTarget instanceof ComponentName) {
7721 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7722 } else if (r.adjTarget != null) {
7723 pw.print(r.adjTarget.toString());
7724 } else {
7725 pw.print("{null}");
7726 }
7727 pw.print("<=");
7728 if (r.adjSource instanceof ProcessRecord) {
7729 pw.print("Proc{");
7730 pw.print(((ProcessRecord)r.adjSource).toShortString());
7731 pw.println("}");
7732 } else if (r.adjSource != null) {
7733 pw.println(r.adjSource.toString());
7734 } else {
7735 pw.println("{null}");
7736 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007738 } else {
7739 pw.println(String.format("%s%s #%2d: %s",
7740 prefix, (r.persistent ? persistentLabel : normalLabel),
7741 i, r.toString()));
7742 }
7743 if (r.persistent) {
7744 numPers++;
7745 }
7746 }
7747 return numPers;
7748 }
7749
Dianne Hackborn472ad872010-04-07 17:31:48 -07007750 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007752 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007753 long uptime = SystemClock.uptimeMillis();
7754 long realtime = SystemClock.elapsedRealtime();
7755
7756 if (isCheckinRequest) {
7757 // short checkin version
7758 pw.println(uptime + "," + realtime);
7759 pw.flush();
7760 } else {
7761 pw.println("Applications Memory Usage (kB):");
7762 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7763 }
7764 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7765 ProcessRecord r = (ProcessRecord)list.get(i);
7766 if (r.thread != null) {
7767 if (!isCheckinRequest) {
7768 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7769 pw.flush();
7770 }
7771 try {
7772 r.thread.asBinder().dump(fd, args);
7773 } catch (RemoteException e) {
7774 if (!isCheckinRequest) {
7775 pw.println("Got RemoteException!");
7776 pw.flush();
7777 }
7778 }
7779 }
7780 }
7781 }
7782
7783 /**
7784 * Searches array of arguments for the specified string
7785 * @param args array of argument strings
7786 * @param value value to search for
7787 * @return true if the value is contained in the array
7788 */
7789 private static boolean scanArgs(String[] args, String value) {
7790 if (args != null) {
7791 for (String arg : args) {
7792 if (value.equals(arg)) {
7793 return true;
7794 }
7795 }
7796 }
7797 return false;
7798 }
7799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 private final void killServicesLocked(ProcessRecord app,
7801 boolean allowRestart) {
7802 // Report disconnected services.
7803 if (false) {
7804 // XXX we are letting the client link to the service for
7805 // death notifications.
7806 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007807 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007809 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007811 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007812 = r.connections.values().iterator();
7813 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007814 ArrayList<ConnectionRecord> cl = jt.next();
7815 for (int i=0; i<cl.size(); i++) {
7816 ConnectionRecord c = cl.get(i);
7817 if (c.binding.client != app) {
7818 try {
7819 //c.conn.connected(r.className, null);
7820 } catch (Exception e) {
7821 // todo: this should be asynchronous!
7822 Slog.w(TAG, "Exception thrown disconnected servce "
7823 + r.shortName
7824 + " from app " + app.processName, e);
7825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007826 }
7827 }
7828 }
7829 }
7830 }
7831 }
7832 }
7833
7834 // Clean up any connections this application has to other services.
7835 if (app.connections.size() > 0) {
7836 Iterator<ConnectionRecord> it = app.connections.iterator();
7837 while (it.hasNext()) {
7838 ConnectionRecord r = it.next();
7839 removeConnectionLocked(r, app, null);
7840 }
7841 }
7842 app.connections.clear();
7843
7844 if (app.services.size() != 0) {
7845 // Any services running in the application need to be placed
7846 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007847 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007848 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007849 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007850 synchronized (sr.stats.getBatteryStats()) {
7851 sr.stats.stopLaunchedLocked();
7852 }
7853 sr.app = null;
7854 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007855 if (mStoppingServices.remove(sr)) {
7856 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
7857 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007858
7859 boolean hasClients = sr.bindings.size() > 0;
7860 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007861 Iterator<IntentBindRecord> bindings
7862 = sr.bindings.values().iterator();
7863 while (bindings.hasNext()) {
7864 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007865 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007866 + ": shouldUnbind=" + b.hasBound);
7867 b.binder = null;
7868 b.requested = b.received = b.hasBound = false;
7869 }
7870 }
7871
7872 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007873 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007874 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007875 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 sr.crashCount, sr.shortName, app.pid);
7877 bringDownServiceLocked(sr, true);
7878 } else if (!allowRestart) {
7879 bringDownServiceLocked(sr, true);
7880 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007881 boolean canceled = scheduleServiceRestartLocked(sr, true);
7882
7883 // Should the service remain running? Note that in the
7884 // extreme case of so many attempts to deliver a command
7885 // that it failed, that we also will stop it here.
7886 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7887 if (sr.pendingStarts.size() == 0) {
7888 sr.startRequested = false;
7889 if (!hasClients) {
7890 // Whoops, no reason to restart!
7891 bringDownServiceLocked(sr, true);
7892 }
7893 }
7894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 }
7896 }
7897
7898 if (!allowRestart) {
7899 app.services.clear();
7900 }
7901 }
7902
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007903 // Make sure we have no more records on the stopping list.
7904 int i = mStoppingServices.size();
7905 while (i > 0) {
7906 i--;
7907 ServiceRecord sr = mStoppingServices.get(i);
7908 if (sr.app == app) {
7909 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007910 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007911 }
7912 }
7913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914 app.executingServices.clear();
7915 }
7916
7917 private final void removeDyingProviderLocked(ProcessRecord proc,
7918 ContentProviderRecord cpr) {
7919 synchronized (cpr) {
7920 cpr.launchingApp = null;
7921 cpr.notifyAll();
7922 }
7923
7924 mProvidersByClass.remove(cpr.info.name);
7925 String names[] = cpr.info.authority.split(";");
7926 for (int j = 0; j < names.length; j++) {
7927 mProvidersByName.remove(names[j]);
7928 }
7929
7930 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7931 while (cit.hasNext()) {
7932 ProcessRecord capp = cit.next();
7933 if (!capp.persistent && capp.thread != null
7934 && capp.pid != 0
7935 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007936 Slog.i(TAG, "Kill " + capp.processName
7937 + " (pid " + capp.pid + "): provider " + cpr.info.name
7938 + " in dying process " + proc.processName);
7939 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7940 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941 Process.killProcess(capp.pid);
7942 }
7943 }
7944
7945 mLaunchingProviders.remove(cpr);
7946 }
7947
7948 /**
7949 * Main code for cleaning up a process when it has gone away. This is
7950 * called both as a result of the process dying, or directly when stopping
7951 * a process when running in single process mode.
7952 */
7953 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7954 boolean restarting, int index) {
7955 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007956 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957 }
7958
Dianne Hackborn36124872009-10-08 16:22:03 -07007959 mProcessesToGc.remove(app);
7960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007961 // Dismiss any open dialogs.
7962 if (app.crashDialog != null) {
7963 app.crashDialog.dismiss();
7964 app.crashDialog = null;
7965 }
7966 if (app.anrDialog != null) {
7967 app.anrDialog.dismiss();
7968 app.anrDialog = null;
7969 }
7970 if (app.waitDialog != null) {
7971 app.waitDialog.dismiss();
7972 app.waitDialog = null;
7973 }
7974
7975 app.crashing = false;
7976 app.notResponding = false;
7977
7978 app.resetPackageList();
7979 app.thread = null;
7980 app.forcingToForeground = null;
7981 app.foregroundServices = false;
7982
7983 killServicesLocked(app, true);
7984
7985 boolean restart = false;
7986
7987 int NL = mLaunchingProviders.size();
7988
7989 // Remove published content providers.
7990 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007991 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007992 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007993 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007994 cpr.provider = null;
7995 cpr.app = null;
7996
7997 // See if someone is waiting for this provider... in which
7998 // case we don't remove it, but just let it restart.
7999 int i = 0;
8000 if (!app.bad) {
8001 for (; i<NL; i++) {
8002 if (mLaunchingProviders.get(i) == cpr) {
8003 restart = true;
8004 break;
8005 }
8006 }
8007 } else {
8008 i = NL;
8009 }
8010
8011 if (i >= NL) {
8012 removeDyingProviderLocked(app, cpr);
8013 NL = mLaunchingProviders.size();
8014 }
8015 }
8016 app.pubProviders.clear();
8017 }
8018
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008019 // Take care of any launching providers waiting for this process.
8020 if (checkAppInLaunchingProvidersLocked(app, false)) {
8021 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 // Unregister from connected content providers.
8025 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008026 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008027 while (it.hasNext()) {
8028 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8029 cpr.clients.remove(app);
8030 }
8031 app.conProviders.clear();
8032 }
8033
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008034 // At this point there may be remaining entries in mLaunchingProviders
8035 // where we were the only one waiting, so they are no longer of use.
8036 // Look for these and clean up if found.
8037 // XXX Commented out for now. Trying to figure out a way to reproduce
8038 // the actual situation to identify what is actually going on.
8039 if (false) {
8040 for (int i=0; i<NL; i++) {
8041 ContentProviderRecord cpr = (ContentProviderRecord)
8042 mLaunchingProviders.get(i);
8043 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8044 synchronized (cpr) {
8045 cpr.launchingApp = null;
8046 cpr.notifyAll();
8047 }
8048 }
8049 }
8050 }
8051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 skipCurrentReceiverLocked(app);
8053
8054 // Unregister any receivers.
8055 if (app.receivers.size() > 0) {
8056 Iterator<ReceiverList> it = app.receivers.iterator();
8057 while (it.hasNext()) {
8058 removeReceiverLocked(it.next());
8059 }
8060 app.receivers.clear();
8061 }
8062
Christopher Tate181fafa2009-05-14 11:12:14 -07008063 // If the app is undergoing backup, tell the backup manager about it
8064 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008065 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008066 try {
8067 IBackupManager bm = IBackupManager.Stub.asInterface(
8068 ServiceManager.getService(Context.BACKUP_SERVICE));
8069 bm.agentDisconnected(app.info.packageName);
8070 } catch (RemoteException e) {
8071 // can't happen; backup manager is local
8072 }
8073 }
8074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008075 // If the caller is restarting this app, then leave it in its
8076 // current lists and let the caller take care of it.
8077 if (restarting) {
8078 return;
8079 }
8080
8081 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008082 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008083 "Removing non-persistent process during cleanup: " + app);
8084 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008085 if (mHeavyWeightProcess == app) {
8086 mHeavyWeightProcess = null;
8087 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008089 } else if (!app.removed) {
8090 // This app is persistent, so we need to keep its record around.
8091 // If it is not already on the pending app list, add it there
8092 // and start a new process for it.
8093 app.thread = null;
8094 app.forcingToForeground = null;
8095 app.foregroundServices = false;
8096 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8097 mPersistentStartingProcesses.add(app);
8098 restart = true;
8099 }
8100 }
8101 mProcessesOnHold.remove(app);
8102
The Android Open Source Project4df24232009-03-05 14:34:35 -08008103 if (app == mHomeProcess) {
8104 mHomeProcess = null;
8105 }
8106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008107 if (restart) {
8108 // We have components that still need to be running in the
8109 // process, so re-launch it.
8110 mProcessNames.put(app.processName, app.info.uid, app);
8111 startProcessLocked(app, "restart", app.processName);
8112 } else if (app.pid > 0 && app.pid != MY_PID) {
8113 // Goodbye!
8114 synchronized (mPidsSelfLocked) {
8115 mPidsSelfLocked.remove(app.pid);
8116 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8117 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008118 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119 }
8120 }
8121
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008122 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8123 // Look through the content providers we are waiting to have launched,
8124 // and if any run in this process then either schedule a restart of
8125 // the process or kill the client waiting for it if this process has
8126 // gone bad.
8127 int NL = mLaunchingProviders.size();
8128 boolean restart = false;
8129 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008130 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008131 if (cpr.launchingApp == app) {
8132 if (!alwaysBad && !app.bad) {
8133 restart = true;
8134 } else {
8135 removeDyingProviderLocked(app, cpr);
8136 NL = mLaunchingProviders.size();
8137 }
8138 }
8139 }
8140 return restart;
8141 }
8142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 // =========================================================
8144 // SERVICES
8145 // =========================================================
8146
8147 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8148 ActivityManager.RunningServiceInfo info =
8149 new ActivityManager.RunningServiceInfo();
8150 info.service = r.name;
8151 if (r.app != null) {
8152 info.pid = r.app.pid;
8153 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008154 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008155 info.process = r.processName;
8156 info.foreground = r.isForeground;
8157 info.activeSince = r.createTime;
8158 info.started = r.startRequested;
8159 info.clientCount = r.connections.size();
8160 info.crashCount = r.crashCount;
8161 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008162 if (r.isForeground) {
8163 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8164 }
8165 if (r.startRequested) {
8166 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8167 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008168 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008169 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8170 }
8171 if (r.app != null && r.app.persistent) {
8172 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8173 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008174
8175 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8176 for (int i=0; i<connl.size(); i++) {
8177 ConnectionRecord conn = connl.get(i);
8178 if (conn.clientLabel != 0) {
8179 info.clientPackage = conn.binding.client.info.packageName;
8180 info.clientLabel = conn.clientLabel;
8181 return info;
8182 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008183 }
8184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 return info;
8186 }
8187
8188 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8189 int flags) {
8190 synchronized (this) {
8191 ArrayList<ActivityManager.RunningServiceInfo> res
8192 = new ArrayList<ActivityManager.RunningServiceInfo>();
8193
8194 if (mServices.size() > 0) {
8195 Iterator<ServiceRecord> it = mServices.values().iterator();
8196 while (it.hasNext() && res.size() < maxNum) {
8197 res.add(makeRunningServiceInfoLocked(it.next()));
8198 }
8199 }
8200
8201 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8202 ServiceRecord r = mRestartingServices.get(i);
8203 ActivityManager.RunningServiceInfo info =
8204 makeRunningServiceInfoLocked(r);
8205 info.restarting = r.nextRestartTime;
8206 res.add(info);
8207 }
8208
8209 return res;
8210 }
8211 }
8212
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008213 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8214 synchronized (this) {
8215 ServiceRecord r = mServices.get(name);
8216 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008217 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8218 for (int i=0; i<conn.size(); i++) {
8219 if (conn.get(i).clientIntent != null) {
8220 return conn.get(i).clientIntent;
8221 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008222 }
8223 }
8224 }
8225 }
8226 return null;
8227 }
8228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008229 private final ServiceRecord findServiceLocked(ComponentName name,
8230 IBinder token) {
8231 ServiceRecord r = mServices.get(name);
8232 return r == token ? r : null;
8233 }
8234
8235 private final class ServiceLookupResult {
8236 final ServiceRecord record;
8237 final String permission;
8238
8239 ServiceLookupResult(ServiceRecord _record, String _permission) {
8240 record = _record;
8241 permission = _permission;
8242 }
8243 };
8244
8245 private ServiceLookupResult findServiceLocked(Intent service,
8246 String resolvedType) {
8247 ServiceRecord r = null;
8248 if (service.getComponent() != null) {
8249 r = mServices.get(service.getComponent());
8250 }
8251 if (r == null) {
8252 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8253 r = mServicesByIntent.get(filter);
8254 }
8255
8256 if (r == null) {
8257 try {
8258 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008259 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 service, resolvedType, 0);
8261 ServiceInfo sInfo =
8262 rInfo != null ? rInfo.serviceInfo : null;
8263 if (sInfo == null) {
8264 return null;
8265 }
8266
8267 ComponentName name = new ComponentName(
8268 sInfo.applicationInfo.packageName, sInfo.name);
8269 r = mServices.get(name);
8270 } catch (RemoteException ex) {
8271 // pm is in same process, this will never happen.
8272 }
8273 }
8274 if (r != null) {
8275 int callingPid = Binder.getCallingPid();
8276 int callingUid = Binder.getCallingUid();
8277 if (checkComponentPermission(r.permission,
8278 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8279 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008280 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008281 + " from pid=" + callingPid
8282 + ", uid=" + callingUid
8283 + " requires " + r.permission);
8284 return new ServiceLookupResult(null, r.permission);
8285 }
8286 return new ServiceLookupResult(r, null);
8287 }
8288 return null;
8289 }
8290
8291 private class ServiceRestarter implements Runnable {
8292 private ServiceRecord mService;
8293
8294 void setService(ServiceRecord service) {
8295 mService = service;
8296 }
8297
8298 public void run() {
8299 synchronized(ActivityManagerService.this) {
8300 performServiceRestartLocked(mService);
8301 }
8302 }
8303 }
8304
8305 private ServiceLookupResult retrieveServiceLocked(Intent service,
8306 String resolvedType, int callingPid, int callingUid) {
8307 ServiceRecord r = null;
8308 if (service.getComponent() != null) {
8309 r = mServices.get(service.getComponent());
8310 }
8311 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8312 r = mServicesByIntent.get(filter);
8313 if (r == null) {
8314 try {
8315 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008316 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008317 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 ServiceInfo sInfo =
8319 rInfo != null ? rInfo.serviceInfo : null;
8320 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008321 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008322 ": not found");
8323 return null;
8324 }
8325
8326 ComponentName name = new ComponentName(
8327 sInfo.applicationInfo.packageName, sInfo.name);
8328 r = mServices.get(name);
8329 if (r == null) {
8330 filter = new Intent.FilterComparison(service.cloneFilter());
8331 ServiceRestarter res = new ServiceRestarter();
8332 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8333 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8334 synchronized (stats) {
8335 ss = stats.getServiceStatsLocked(
8336 sInfo.applicationInfo.uid, sInfo.packageName,
8337 sInfo.name);
8338 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008339 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008340 res.setService(r);
8341 mServices.put(name, r);
8342 mServicesByIntent.put(filter, r);
8343
8344 // Make sure this component isn't in the pending list.
8345 int N = mPendingServices.size();
8346 for (int i=0; i<N; i++) {
8347 ServiceRecord pr = mPendingServices.get(i);
8348 if (pr.name.equals(name)) {
8349 mPendingServices.remove(i);
8350 i--;
8351 N--;
8352 }
8353 }
8354 }
8355 } catch (RemoteException ex) {
8356 // pm is in same process, this will never happen.
8357 }
8358 }
8359 if (r != null) {
8360 if (checkComponentPermission(r.permission,
8361 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8362 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008363 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008364 + " from pid=" + Binder.getCallingPid()
8365 + ", uid=" + Binder.getCallingUid()
8366 + " requires " + r.permission);
8367 return new ServiceLookupResult(null, r.permission);
8368 }
8369 return new ServiceLookupResult(r, null);
8370 }
8371 return null;
8372 }
8373
8374 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8375 long now = SystemClock.uptimeMillis();
8376 if (r.executeNesting == 0 && r.app != null) {
8377 if (r.app.executingServices.size() == 0) {
8378 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8379 msg.obj = r.app;
8380 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8381 }
8382 r.app.executingServices.add(r);
8383 }
8384 r.executeNesting++;
8385 r.executingStart = now;
8386 }
8387
8388 private final void sendServiceArgsLocked(ServiceRecord r,
8389 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008390 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008391 if (N == 0) {
8392 return;
8393 }
8394
Dianne Hackborn39792d22010-08-19 18:01:52 -07008395 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008396 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008397 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008398 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8399 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008400 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008401 // If somehow we got a dummy start at the front, then
8402 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008403 continue;
8404 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008405 si.deliveredTime = SystemClock.uptimeMillis();
8406 r.deliveredStarts.add(si);
8407 si.deliveryCount++;
8408 if (si.targetPermissionUid >= 0) {
8409 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008410 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008411 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008412 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008413 bumpServiceExecutingLocked(r);
8414 if (!oomAdjusted) {
8415 oomAdjusted = true;
8416 updateOomAdjLocked(r.app);
8417 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008418 int flags = 0;
8419 if (si.deliveryCount > 0) {
8420 flags |= Service.START_FLAG_RETRY;
8421 }
8422 if (si.doneExecutingCount > 0) {
8423 flags |= Service.START_FLAG_REDELIVERY;
8424 }
8425 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008426 } catch (RemoteException e) {
8427 // Remote process gone... we'll let the normal cleanup take
8428 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008429 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008430 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008431 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008432 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008433 break;
8434 }
8435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 }
8437
8438 private final boolean requestServiceBindingLocked(ServiceRecord r,
8439 IntentBindRecord i, boolean rebind) {
8440 if (r.app == null || r.app.thread == null) {
8441 // If service is not currently running, can't yet bind.
8442 return false;
8443 }
8444 if ((!i.requested || rebind) && i.apps.size() > 0) {
8445 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008446 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
8447 + " in " + i + ": shouldUnbind=" + i.hasBound);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008448 bumpServiceExecutingLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008449 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8450 if (!rebind) {
8451 i.requested = true;
8452 }
8453 i.hasBound = true;
8454 i.doRebind = false;
8455 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008456 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008457 return false;
8458 }
8459 }
8460 return true;
8461 }
8462
8463 private final void requestServiceBindingsLocked(ServiceRecord r) {
8464 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8465 while (bindings.hasNext()) {
8466 IntentBindRecord i = bindings.next();
8467 if (!requestServiceBindingLocked(r, i, false)) {
8468 break;
8469 }
8470 }
8471 }
8472
8473 private final void realStartServiceLocked(ServiceRecord r,
8474 ProcessRecord app) throws RemoteException {
8475 if (app.thread == null) {
8476 throw new RemoteException();
8477 }
8478
8479 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008480 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008481
8482 app.services.add(r);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008483 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008484 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008485 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486
8487 boolean created = false;
8488 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008489 mStringBuilder.setLength(0);
8490 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008491 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008493 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008494 synchronized (r.stats.getBatteryStats()) {
8495 r.stats.startLaunchedLocked();
8496 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008497 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008498 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008499 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008500 created = true;
8501 } finally {
8502 if (!created) {
8503 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008504 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008505 }
8506 }
8507
8508 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008509
8510 // If the service is in the started state, and there are no
8511 // pending arguments, then fake up one so its onStartCommand() will
8512 // be called.
8513 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8514 r.lastStartId++;
8515 if (r.lastStartId < 1) {
8516 r.lastStartId = 1;
8517 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008518 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008519 }
8520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521 sendServiceArgsLocked(r, true);
8522 }
8523
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008524 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8525 boolean allowCancel) {
8526 boolean canceled = false;
8527
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008528 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008529 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008530 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008531
8532 // Any delivered but not yet finished starts should be put back
8533 // on the pending list.
8534 final int N = r.deliveredStarts.size();
8535 if (N > 0) {
8536 for (int i=N-1; i>=0; i--) {
8537 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008538 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008539 if (si.intent == null) {
8540 // We'll generate this again if needed.
8541 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8542 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8543 r.pendingStarts.add(0, si);
8544 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8545 dur *= 2;
8546 if (minDuration < dur) minDuration = dur;
8547 if (resetTime < dur) resetTime = dur;
8548 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008549 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008550 + r.name);
8551 canceled = true;
8552 }
8553 }
8554 r.deliveredStarts.clear();
8555 }
8556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008557 r.totalRestartCount++;
8558 if (r.restartDelay == 0) {
8559 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008560 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008561 } else {
8562 // If it has been a "reasonably long time" since the service
8563 // was started, then reset our restart duration back to
8564 // the beginning, so we don't infinitely increase the duration
8565 // on a service that just occasionally gets killed (which is
8566 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008567 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008569 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008571 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008572 if (r.restartDelay < minDuration) {
8573 r.restartDelay = minDuration;
8574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008575 }
8576 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008577
8578 r.nextRestartTime = now + r.restartDelay;
8579
8580 // Make sure that we don't end up restarting a bunch of services
8581 // all at the same time.
8582 boolean repeat;
8583 do {
8584 repeat = false;
8585 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8586 ServiceRecord r2 = mRestartingServices.get(i);
8587 if (r2 != r && r.nextRestartTime
8588 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8589 && r.nextRestartTime
8590 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8591 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8592 r.restartDelay = r.nextRestartTime - now;
8593 repeat = true;
8594 break;
8595 }
8596 }
8597 } while (repeat);
8598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 if (!mRestartingServices.contains(r)) {
8600 mRestartingServices.add(r);
8601 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008602
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008603 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008605 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008606 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008608 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008609 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008610 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008611 r.shortName, r.restartDelay);
8612
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008613 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 }
8615
8616 final void performServiceRestartLocked(ServiceRecord r) {
8617 if (!mRestartingServices.contains(r)) {
8618 return;
8619 }
8620 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8621 }
8622
8623 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8624 if (r.restartDelay == 0) {
8625 return false;
8626 }
8627 r.resetRestartCounter();
8628 mRestartingServices.remove(r);
8629 mHandler.removeCallbacks(r.restarter);
8630 return true;
8631 }
8632
8633 private final boolean bringUpServiceLocked(ServiceRecord r,
8634 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008635 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 //r.dump(" ");
8637
Dianne Hackborn36124872009-10-08 16:22:03 -07008638 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 sendServiceArgsLocked(r, false);
8640 return true;
8641 }
8642
8643 if (!whileRestarting && r.restartDelay > 0) {
8644 // If waiting for a restart, then do nothing.
8645 return true;
8646 }
8647
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008648 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008650 // We are now bringing the service up, so no longer in the
8651 // restarting state.
8652 mRestartingServices.remove(r);
8653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008654 final String appName = r.processName;
8655 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8656 if (app != null && app.thread != null) {
8657 try {
8658 realStartServiceLocked(r, app);
8659 return true;
8660 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008661 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008662 }
8663
8664 // If a dead object exception was thrown -- fall through to
8665 // restart the application.
8666 }
8667
Dianne Hackborn36124872009-10-08 16:22:03 -07008668 // Not running -- get it started, and enqueue this service record
8669 // to be executed when the app comes up.
8670 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8671 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008672 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008673 + r.appInfo.packageName + "/"
8674 + r.appInfo.uid + " for service "
8675 + r.intent.getIntent() + ": process is bad");
8676 bringDownServiceLocked(r, true);
8677 return false;
8678 }
8679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008680 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008681 mPendingServices.add(r);
8682 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008684 return true;
8685 }
8686
8687 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008688 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 //r.dump(" ");
8690
8691 // Does it still need to run?
8692 if (!force && r.startRequested) {
8693 return;
8694 }
8695 if (r.connections.size() > 0) {
8696 if (!force) {
8697 // XXX should probably keep a count of the number of auto-create
8698 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008699 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008700 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008701 ArrayList<ConnectionRecord> cr = it.next();
8702 for (int i=0; i<cr.size(); i++) {
8703 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8704 return;
8705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008706 }
8707 }
8708 }
8709
8710 // Report to all of the connections that the service is no longer
8711 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008712 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008713 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008714 ArrayList<ConnectionRecord> c = it.next();
8715 for (int i=0; i<c.size(); i++) {
8716 try {
8717 c.get(i).conn.connected(r.name, null);
8718 } catch (Exception e) {
8719 Slog.w(TAG, "Failure disconnecting service " + r.name +
8720 " to connection " + c.get(i).conn.asBinder() +
8721 " (in " + c.get(i).binding.client.processName + ")", e);
8722 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 }
8724 }
8725 }
8726
8727 // Tell the service that it has been unbound.
8728 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8729 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8730 while (it.hasNext()) {
8731 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008732 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008733 + ": hasBound=" + ibr.hasBound);
8734 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8735 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008736 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
8737 + " for " + ibr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 bumpServiceExecutingLocked(r);
8739 updateOomAdjLocked(r.app);
8740 ibr.hasBound = false;
8741 r.app.thread.scheduleUnbindService(r,
8742 ibr.intent.getIntent());
8743 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008744 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 + r.shortName, e);
8746 serviceDoneExecutingLocked(r, true);
8747 }
8748 }
8749 }
8750 }
8751
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008752 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008753 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008754 System.identityHashCode(r), r.shortName,
8755 (r.app != null) ? r.app.pid : -1);
8756
8757 mServices.remove(r.name);
8758 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 r.totalRestartCount = 0;
8760 unscheduleServiceRestartLocked(r);
8761
8762 // Also make sure it is not on the pending list.
8763 int N = mPendingServices.size();
8764 for (int i=0; i<N; i++) {
8765 if (mPendingServices.get(i) == r) {
8766 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008767 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008768 i--;
8769 N--;
8770 }
8771 }
8772
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008773 r.cancelNotification();
8774 r.isForeground = false;
8775 r.foregroundId = 0;
8776 r.foregroundNoti = null;
8777
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008778 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008779 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008780 r.pendingStarts.clear();
8781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 if (r.app != null) {
8783 synchronized (r.stats.getBatteryStats()) {
8784 r.stats.stopLaunchedLocked();
8785 }
8786 r.app.services.remove(r);
8787 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008789 if (DEBUG_SERVICE) {
8790 RuntimeException here = new RuntimeException();
8791 here.fillInStackTrace();
8792 Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
8793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 bumpServiceExecutingLocked(r);
8795 mStoppingServices.add(r);
8796 updateOomAdjLocked(r.app);
8797 r.app.thread.scheduleStopService(r);
8798 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008799 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008800 + r.shortName, e);
8801 serviceDoneExecutingLocked(r, true);
8802 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008803 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008804 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008805 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008806 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 }
8808 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008809 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008810 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008811 }
8812 }
8813
8814 ComponentName startServiceLocked(IApplicationThread caller,
8815 Intent service, String resolvedType,
8816 int callingPid, int callingUid) {
8817 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008818 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 + " type=" + resolvedType + " args=" + service.getExtras());
8820
8821 if (caller != null) {
8822 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8823 if (callerApp == null) {
8824 throw new SecurityException(
8825 "Unable to find app for caller " + caller
8826 + " (pid=" + Binder.getCallingPid()
8827 + ") when starting service " + service);
8828 }
8829 }
8830
8831 ServiceLookupResult res =
8832 retrieveServiceLocked(service, resolvedType,
8833 callingPid, callingUid);
8834 if (res == null) {
8835 return null;
8836 }
8837 if (res.record == null) {
8838 return new ComponentName("!", res.permission != null
8839 ? res.permission : "private to package");
8840 }
8841 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07008842 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
8843 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008845 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008846 }
8847 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008848 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 r.lastStartId++;
8850 if (r.lastStartId < 1) {
8851 r.lastStartId = 1;
8852 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008853 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
8854 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008855 r.lastActivity = SystemClock.uptimeMillis();
8856 synchronized (r.stats.getBatteryStats()) {
8857 r.stats.startRunningLocked();
8858 }
8859 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8860 return new ComponentName("!", "Service process is bad");
8861 }
8862 return r.name;
8863 }
8864 }
8865
8866 public ComponentName startService(IApplicationThread caller, Intent service,
8867 String resolvedType) {
8868 // Refuse possible leaked file descriptors
8869 if (service != null && service.hasFileDescriptors() == true) {
8870 throw new IllegalArgumentException("File descriptors passed in Intent");
8871 }
8872
8873 synchronized(this) {
8874 final int callingPid = Binder.getCallingPid();
8875 final int callingUid = Binder.getCallingUid();
8876 final long origId = Binder.clearCallingIdentity();
8877 ComponentName res = startServiceLocked(caller, service,
8878 resolvedType, callingPid, callingUid);
8879 Binder.restoreCallingIdentity(origId);
8880 return res;
8881 }
8882 }
8883
8884 ComponentName startServiceInPackage(int uid,
8885 Intent service, String resolvedType) {
8886 synchronized(this) {
8887 final long origId = Binder.clearCallingIdentity();
8888 ComponentName res = startServiceLocked(null, service,
8889 resolvedType, -1, uid);
8890 Binder.restoreCallingIdentity(origId);
8891 return res;
8892 }
8893 }
8894
8895 public int stopService(IApplicationThread caller, Intent service,
8896 String resolvedType) {
8897 // Refuse possible leaked file descriptors
8898 if (service != null && service.hasFileDescriptors() == true) {
8899 throw new IllegalArgumentException("File descriptors passed in Intent");
8900 }
8901
8902 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008903 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008904 + " type=" + resolvedType);
8905
8906 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8907 if (caller != null && callerApp == null) {
8908 throw new SecurityException(
8909 "Unable to find app for caller " + caller
8910 + " (pid=" + Binder.getCallingPid()
8911 + ") when stopping service " + service);
8912 }
8913
8914 // If this service is active, make sure it is stopped.
8915 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8916 if (r != null) {
8917 if (r.record != null) {
8918 synchronized (r.record.stats.getBatteryStats()) {
8919 r.record.stats.stopRunningLocked();
8920 }
8921 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008922 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008923 final long origId = Binder.clearCallingIdentity();
8924 bringDownServiceLocked(r.record, false);
8925 Binder.restoreCallingIdentity(origId);
8926 return 1;
8927 }
8928 return -1;
8929 }
8930 }
8931
8932 return 0;
8933 }
8934
8935 public IBinder peekService(Intent service, String resolvedType) {
8936 // Refuse possible leaked file descriptors
8937 if (service != null && service.hasFileDescriptors() == true) {
8938 throw new IllegalArgumentException("File descriptors passed in Intent");
8939 }
8940
8941 IBinder ret = null;
8942
8943 synchronized(this) {
8944 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8945
8946 if (r != null) {
8947 // r.record is null if findServiceLocked() failed the caller permission check
8948 if (r.record == null) {
8949 throw new SecurityException(
8950 "Permission Denial: Accessing service " + r.record.name
8951 + " from pid=" + Binder.getCallingPid()
8952 + ", uid=" + Binder.getCallingUid()
8953 + " requires " + r.permission);
8954 }
8955 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8956 if (ib != null) {
8957 ret = ib.binder;
8958 }
8959 }
8960 }
8961
8962 return ret;
8963 }
8964
8965 public boolean stopServiceToken(ComponentName className, IBinder token,
8966 int startId) {
8967 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008968 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008969 + " " + token + " startId=" + startId);
8970 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008971 if (r != null) {
8972 if (startId >= 0) {
8973 // Asked to only stop if done with all work. Note that
8974 // to avoid leaks, we will take this as dropping all
8975 // start items up to and including this one.
8976 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8977 if (si != null) {
8978 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008979 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
8980 cur.removeUriPermissionsLocked();
8981 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008982 break;
8983 }
8984 }
8985 }
8986
8987 if (r.lastStartId != startId) {
8988 return false;
8989 }
8990
8991 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008992 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008993 + " is last, but have " + r.deliveredStarts.size()
8994 + " remaining args");
8995 }
8996 }
8997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 synchronized (r.stats.getBatteryStats()) {
8999 r.stats.stopRunningLocked();
9000 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009001 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009002 }
9003 final long origId = Binder.clearCallingIdentity();
9004 bringDownServiceLocked(r, false);
9005 Binder.restoreCallingIdentity(origId);
9006 return true;
9007 }
9008 }
9009 return false;
9010 }
9011
9012 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009013 int id, Notification notification, boolean removeNotification) {
9014 final long origId = Binder.clearCallingIdentity();
9015 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009016 synchronized(this) {
9017 ServiceRecord r = findServiceLocked(className, token);
9018 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009019 if (id != 0) {
9020 if (notification == null) {
9021 throw new IllegalArgumentException("null notification");
9022 }
9023 if (r.foregroundId != id) {
9024 r.cancelNotification();
9025 r.foregroundId = id;
9026 }
9027 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9028 r.foregroundNoti = notification;
9029 r.isForeground = true;
9030 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 if (r.app != null) {
9032 updateServiceForegroundLocked(r.app, true);
9033 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009034 } else {
9035 if (r.isForeground) {
9036 r.isForeground = false;
9037 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009038 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009039 updateServiceForegroundLocked(r.app, true);
9040 }
9041 }
9042 if (removeNotification) {
9043 r.cancelNotification();
9044 r.foregroundId = 0;
9045 r.foregroundNoti = null;
9046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009047 }
9048 }
9049 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009050 } finally {
9051 Binder.restoreCallingIdentity(origId);
9052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009053 }
9054
9055 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9056 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009057 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 if (sr.isForeground) {
9059 anyForeground = true;
9060 break;
9061 }
9062 }
9063 if (anyForeground != proc.foregroundServices) {
9064 proc.foregroundServices = anyForeground;
9065 if (oomAdj) {
9066 updateOomAdjLocked();
9067 }
9068 }
9069 }
9070
9071 public int bindService(IApplicationThread caller, IBinder token,
9072 Intent service, String resolvedType,
9073 IServiceConnection connection, int flags) {
9074 // Refuse possible leaked file descriptors
9075 if (service != null && service.hasFileDescriptors() == true) {
9076 throw new IllegalArgumentException("File descriptors passed in Intent");
9077 }
9078
9079 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009080 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 + " type=" + resolvedType + " conn=" + connection.asBinder()
9082 + " flags=0x" + Integer.toHexString(flags));
9083 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9084 if (callerApp == null) {
9085 throw new SecurityException(
9086 "Unable to find app for caller " + caller
9087 + " (pid=" + Binder.getCallingPid()
9088 + ") when binding service " + service);
9089 }
9090
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009091 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009093 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009094 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009095 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009096 return 0;
9097 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009098 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009099 }
9100
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009101 int clientLabel = 0;
9102 PendingIntent clientIntent = null;
9103
9104 if (callerApp.info.uid == Process.SYSTEM_UID) {
9105 // Hacky kind of thing -- allow system stuff to tell us
9106 // what they are, so we can report this elsewhere for
9107 // others to know why certain services are running.
9108 try {
9109 clientIntent = (PendingIntent)service.getParcelableExtra(
9110 Intent.EXTRA_CLIENT_INTENT);
9111 } catch (RuntimeException e) {
9112 }
9113 if (clientIntent != null) {
9114 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9115 if (clientLabel != 0) {
9116 // There are no useful extras in the intent, trash them.
9117 // System code calling with this stuff just needs to know
9118 // this will happen.
9119 service = service.cloneFilter();
9120 }
9121 }
9122 }
9123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009124 ServiceLookupResult res =
9125 retrieveServiceLocked(service, resolvedType,
9126 Binder.getCallingPid(), Binder.getCallingUid());
9127 if (res == null) {
9128 return 0;
9129 }
9130 if (res.record == null) {
9131 return -1;
9132 }
9133 ServiceRecord s = res.record;
9134
9135 final long origId = Binder.clearCallingIdentity();
9136
9137 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009138 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009139 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 }
9141
9142 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9143 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009144 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009145
9146 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009147 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9148 if (clist == null) {
9149 clist = new ArrayList<ConnectionRecord>();
9150 s.connections.put(binder, clist);
9151 }
9152 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 b.connections.add(c);
9154 if (activity != null) {
9155 if (activity.connections == null) {
9156 activity.connections = new HashSet<ConnectionRecord>();
9157 }
9158 activity.connections.add(c);
9159 }
9160 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009161 clist = mServiceConnections.get(binder);
9162 if (clist == null) {
9163 clist = new ArrayList<ConnectionRecord>();
9164 mServiceConnections.put(binder, clist);
9165 }
9166 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009167
9168 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9169 s.lastActivity = SystemClock.uptimeMillis();
9170 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9171 return 0;
9172 }
9173 }
9174
9175 if (s.app != null) {
9176 // This could have made the service more important.
9177 updateOomAdjLocked(s.app);
9178 }
9179
Joe Onorato8a9b2202010-02-26 18:56:32 -08009180 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 + ": received=" + b.intent.received
9182 + " apps=" + b.intent.apps.size()
9183 + " doRebind=" + b.intent.doRebind);
9184
9185 if (s.app != null && b.intent.received) {
9186 // Service is already running, so we can immediately
9187 // publish the connection.
9188 try {
9189 c.conn.connected(s.name, b.intent.binder);
9190 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009191 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 + " to connection " + c.conn.asBinder()
9193 + " (in " + c.binding.client.processName + ")", e);
9194 }
9195
9196 // If this is the first app connected back to this binding,
9197 // and the service had previously asked to be told when
9198 // rebound, then do so.
9199 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9200 requestServiceBindingLocked(s, b.intent, true);
9201 }
9202 } else if (!b.intent.requested) {
9203 requestServiceBindingLocked(s, b.intent, false);
9204 }
9205
9206 Binder.restoreCallingIdentity(origId);
9207 }
9208
9209 return 1;
9210 }
9211
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009212 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009213 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009214 IBinder binder = c.conn.asBinder();
9215 AppBindRecord b = c.binding;
9216 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009217 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9218 if (clist != null) {
9219 clist.remove(c);
9220 if (clist.size() == 0) {
9221 s.connections.remove(binder);
9222 }
9223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009224 b.connections.remove(c);
9225 if (c.activity != null && c.activity != skipAct) {
9226 if (c.activity.connections != null) {
9227 c.activity.connections.remove(c);
9228 }
9229 }
9230 if (b.client != skipApp) {
9231 b.client.connections.remove(c);
9232 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009233 clist = mServiceConnections.get(binder);
9234 if (clist != null) {
9235 clist.remove(c);
9236 if (clist.size() == 0) {
9237 mServiceConnections.remove(binder);
9238 }
9239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240
9241 if (b.connections.size() == 0) {
9242 b.intent.apps.remove(b.client);
9243 }
9244
Joe Onorato8a9b2202010-02-26 18:56:32 -08009245 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009246 + ": shouldUnbind=" + b.intent.hasBound);
9247 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9248 && b.intent.hasBound) {
9249 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009250 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
9251 + " from " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009252 bumpServiceExecutingLocked(s);
9253 updateOomAdjLocked(s.app);
9254 b.intent.hasBound = false;
9255 // Assume the client doesn't want to know about a rebind;
9256 // we will deal with that later if it asks for one.
9257 b.intent.doRebind = false;
9258 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9259 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009260 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009261 serviceDoneExecutingLocked(s, true);
9262 }
9263 }
9264
9265 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9266 bringDownServiceLocked(s, false);
9267 }
9268 }
9269
9270 public boolean unbindService(IServiceConnection connection) {
9271 synchronized (this) {
9272 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009273 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009274 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9275 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009276 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009277 + connection.asBinder());
9278 return false;
9279 }
9280
9281 final long origId = Binder.clearCallingIdentity();
9282
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009283 while (clist.size() > 0) {
9284 ConnectionRecord r = clist.get(0);
9285 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009287 if (r.binding.service.app != null) {
9288 // This could have made the service less important.
9289 updateOomAdjLocked(r.binding.service.app);
9290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 }
9292
9293 Binder.restoreCallingIdentity(origId);
9294 }
9295
9296 return true;
9297 }
9298
9299 public void publishService(IBinder token, Intent intent, IBinder service) {
9300 // Refuse possible leaked file descriptors
9301 if (intent != null && intent.hasFileDescriptors() == true) {
9302 throw new IllegalArgumentException("File descriptors passed in Intent");
9303 }
9304
9305 synchronized(this) {
9306 if (!(token instanceof ServiceRecord)) {
9307 throw new IllegalArgumentException("Invalid service token");
9308 }
9309 ServiceRecord r = (ServiceRecord)token;
9310
9311 final long origId = Binder.clearCallingIdentity();
9312
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009313 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009314 + " " + intent + ": " + service);
9315 if (r != null) {
9316 Intent.FilterComparison filter
9317 = new Intent.FilterComparison(intent);
9318 IntentBindRecord b = r.bindings.get(filter);
9319 if (b != null && !b.received) {
9320 b.binder = service;
9321 b.requested = true;
9322 b.received = true;
9323 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009324 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009325 = r.connections.values().iterator();
9326 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009327 ArrayList<ConnectionRecord> clist = it.next();
9328 for (int i=0; i<clist.size(); i++) {
9329 ConnectionRecord c = clist.get(i);
9330 if (!filter.equals(c.binding.intent.intent)) {
9331 if (DEBUG_SERVICE) Slog.v(
9332 TAG, "Not publishing to: " + c);
9333 if (DEBUG_SERVICE) Slog.v(
9334 TAG, "Bound intent: " + c.binding.intent.intent);
9335 if (DEBUG_SERVICE) Slog.v(
9336 TAG, "Published intent: " + intent);
9337 continue;
9338 }
9339 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9340 try {
9341 c.conn.connected(r.name, service);
9342 } catch (Exception e) {
9343 Slog.w(TAG, "Failure sending service " + r.name +
9344 " to connection " + c.conn.asBinder() +
9345 " (in " + c.binding.client.processName + ")", e);
9346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009347 }
9348 }
9349 }
9350 }
9351
9352 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9353
9354 Binder.restoreCallingIdentity(origId);
9355 }
9356 }
9357 }
9358
9359 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9360 // Refuse possible leaked file descriptors
9361 if (intent != null && intent.hasFileDescriptors() == true) {
9362 throw new IllegalArgumentException("File descriptors passed in Intent");
9363 }
9364
9365 synchronized(this) {
9366 if (!(token instanceof ServiceRecord)) {
9367 throw new IllegalArgumentException("Invalid service token");
9368 }
9369 ServiceRecord r = (ServiceRecord)token;
9370
9371 final long origId = Binder.clearCallingIdentity();
9372
9373 if (r != null) {
9374 Intent.FilterComparison filter
9375 = new Intent.FilterComparison(intent);
9376 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009377 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009378 + " at " + b + ": apps="
9379 + (b != null ? b.apps.size() : 0));
9380 if (b != null) {
9381 if (b.apps.size() > 0) {
9382 // Applications have already bound since the last
9383 // unbind, so just rebind right here.
9384 requestServiceBindingLocked(r, b, true);
9385 } else {
9386 // Note to tell the service the next time there is
9387 // a new client.
9388 b.doRebind = true;
9389 }
9390 }
9391
9392 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9393
9394 Binder.restoreCallingIdentity(origId);
9395 }
9396 }
9397 }
9398
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009399 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009400 synchronized(this) {
9401 if (!(token instanceof ServiceRecord)) {
9402 throw new IllegalArgumentException("Invalid service token");
9403 }
9404 ServiceRecord r = (ServiceRecord)token;
9405 boolean inStopping = mStoppingServices.contains(token);
9406 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009407 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009408 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009409 + " with incorrect token: given " + token
9410 + ", expected " + r);
9411 return;
9412 }
9413
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009414 if (type == 1) {
9415 // This is a call from a service start... take care of
9416 // book-keeping.
9417 r.callStart = true;
9418 switch (res) {
9419 case Service.START_STICKY_COMPATIBILITY:
9420 case Service.START_STICKY: {
9421 // We are done with the associated start arguments.
9422 r.findDeliveredStart(startId, true);
9423 // Don't stop if killed.
9424 r.stopIfKilled = false;
9425 break;
9426 }
9427 case Service.START_NOT_STICKY: {
9428 // We are done with the associated start arguments.
9429 r.findDeliveredStart(startId, true);
9430 if (r.lastStartId == startId) {
9431 // There is no more work, and this service
9432 // doesn't want to hang around if killed.
9433 r.stopIfKilled = true;
9434 }
9435 break;
9436 }
9437 case Service.START_REDELIVER_INTENT: {
9438 // We'll keep this item until they explicitly
9439 // call stop for it, but keep track of the fact
9440 // that it was delivered.
9441 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9442 if (si != null) {
9443 si.deliveryCount = 0;
9444 si.doneExecutingCount++;
9445 // Don't stop if killed.
9446 r.stopIfKilled = true;
9447 }
9448 break;
9449 }
9450 default:
9451 throw new IllegalArgumentException(
9452 "Unknown service start result: " + res);
9453 }
9454 if (res == Service.START_STICKY_COMPATIBILITY) {
9455 r.callStart = false;
9456 }
9457 }
9458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009459 final long origId = Binder.clearCallingIdentity();
9460 serviceDoneExecutingLocked(r, inStopping);
9461 Binder.restoreCallingIdentity(origId);
9462 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009463 Slog.w(TAG, "Done executing unknown service from pid "
9464 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 }
9466 }
9467 }
9468
9469 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009470 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9471 + ": nesting=" + r.executeNesting
9472 + ", inStopping=" + inStopping + ", app=" + r.app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009473 r.executeNesting--;
9474 if (r.executeNesting <= 0 && r.app != null) {
9475 r.app.executingServices.remove(r);
9476 if (r.app.executingServices.size() == 0) {
9477 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9478 }
9479 if (inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009480 if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009481 mStoppingServices.remove(r);
9482 }
9483 updateOomAdjLocked(r.app);
9484 }
9485 }
9486
9487 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009488 String anrMessage = null;
9489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009490 synchronized(this) {
9491 if (proc.executingServices.size() == 0 || proc.thread == null) {
9492 return;
9493 }
9494 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9495 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9496 ServiceRecord timeout = null;
9497 long nextTime = 0;
9498 while (it.hasNext()) {
9499 ServiceRecord sr = it.next();
9500 if (sr.executingStart < maxTime) {
9501 timeout = sr;
9502 break;
9503 }
9504 if (sr.executingStart > nextTime) {
9505 nextTime = sr.executingStart;
9506 }
9507 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009508 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009509 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009510 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009511 } else {
9512 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9513 msg.obj = proc;
9514 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9515 }
9516 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009517
9518 if (anrMessage != null) {
9519 appNotResponding(proc, null, null, anrMessage);
9520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521 }
9522
9523 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009524 // BACKUP AND RESTORE
9525 // =========================================================
9526
9527 // Cause the target app to be launched if necessary and its backup agent
9528 // instantiated. The backup agent will invoke backupAgentCreated() on the
9529 // activity manager to announce its creation.
9530 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009531 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009532 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9533
9534 synchronized(this) {
9535 // !!! TODO: currently no check here that we're already bound
9536 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9537 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9538 synchronized (stats) {
9539 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9540 }
9541
9542 BackupRecord r = new BackupRecord(ss, app, backupMode);
9543 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9544 // startProcessLocked() returns existing proc's record if it's already running
9545 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009546 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009547 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009548 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009549 return false;
9550 }
9551
9552 r.app = proc;
9553 mBackupTarget = r;
9554 mBackupAppName = app.packageName;
9555
Christopher Tate6fa95972009-06-05 18:43:55 -07009556 // Try not to kill the process during backup
9557 updateOomAdjLocked(proc);
9558
Christopher Tate181fafa2009-05-14 11:12:14 -07009559 // If the process is already attached, schedule the creation of the backup agent now.
9560 // If it is not yet live, this will be done when it attaches to the framework.
9561 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009562 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009563 try {
9564 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9565 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009566 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009567 }
9568 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009569 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009570 }
9571 // Invariants: at this point, the target app process exists and the application
9572 // is either already running or in the process of coming up. mBackupTarget and
9573 // mBackupAppName describe the app, so that when it binds back to the AM we
9574 // know that it's scheduled for a backup-agent operation.
9575 }
9576
9577 return true;
9578 }
9579
9580 // A backup agent has just come up
9581 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009582 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009583 + " = " + agent);
9584
9585 synchronized(this) {
9586 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009587 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009588 return;
9589 }
9590
Christopher Tate043dadc2009-06-02 16:11:00 -07009591 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009592 try {
9593 IBackupManager bm = IBackupManager.Stub.asInterface(
9594 ServiceManager.getService(Context.BACKUP_SERVICE));
9595 bm.agentConnected(agentPackageName, agent);
9596 } catch (RemoteException e) {
9597 // can't happen; the backup manager service is local
9598 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009599 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009600 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009601 } finally {
9602 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009603 }
9604 }
9605 }
9606
9607 // done with this agent
9608 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009609 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009610 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009611 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009612 return;
9613 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009614
9615 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009616 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009617 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009618 return;
9619 }
9620
Christopher Tate181fafa2009-05-14 11:12:14 -07009621 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009622 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009623 return;
9624 }
9625
Christopher Tate6fa95972009-06-05 18:43:55 -07009626 ProcessRecord proc = mBackupTarget.app;
9627 mBackupTarget = null;
9628 mBackupAppName = null;
9629
9630 // Not backing this app up any more; reset its OOM adjustment
9631 updateOomAdjLocked(proc);
9632
Christopher Tatec7b31e32009-06-10 15:49:30 -07009633 // If the app crashed during backup, 'thread' will be null here
9634 if (proc.thread != null) {
9635 try {
9636 proc.thread.scheduleDestroyBackupAgent(appInfo);
9637 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009638 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009639 e.printStackTrace();
9640 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009641 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009642 }
9643 }
9644 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 // BROADCASTS
9646 // =========================================================
9647
Josh Bartel7f208742010-02-25 11:01:44 -06009648 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009649 List cur) {
9650 final ContentResolver resolver = mContext.getContentResolver();
9651 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9652 if (list == null) {
9653 return cur;
9654 }
9655 int N = list.size();
9656 for (int i=0; i<N; i++) {
9657 Intent intent = list.get(i);
9658 if (filter.match(resolver, intent, true, TAG) >= 0) {
9659 if (cur == null) {
9660 cur = new ArrayList<Intent>();
9661 }
9662 cur.add(intent);
9663 }
9664 }
9665 return cur;
9666 }
9667
9668 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009669 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009670 + mBroadcastsScheduled);
9671
9672 if (mBroadcastsScheduled) {
9673 return;
9674 }
9675 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9676 mBroadcastsScheduled = true;
9677 }
9678
9679 public Intent registerReceiver(IApplicationThread caller,
9680 IIntentReceiver receiver, IntentFilter filter, String permission) {
9681 synchronized(this) {
9682 ProcessRecord callerApp = null;
9683 if (caller != null) {
9684 callerApp = getRecordForAppLocked(caller);
9685 if (callerApp == null) {
9686 throw new SecurityException(
9687 "Unable to find app for caller " + caller
9688 + " (pid=" + Binder.getCallingPid()
9689 + ") when registering receiver " + receiver);
9690 }
9691 }
9692
9693 List allSticky = null;
9694
9695 // Look for any matching sticky broadcasts...
9696 Iterator actions = filter.actionsIterator();
9697 if (actions != null) {
9698 while (actions.hasNext()) {
9699 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009700 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009701 }
9702 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009703 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704 }
9705
9706 // The first sticky in the list is returned directly back to
9707 // the client.
9708 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9709
Joe Onorato8a9b2202010-02-26 18:56:32 -08009710 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009711 + ": " + sticky);
9712
9713 if (receiver == null) {
9714 return sticky;
9715 }
9716
9717 ReceiverList rl
9718 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9719 if (rl == null) {
9720 rl = new ReceiverList(this, callerApp,
9721 Binder.getCallingPid(),
9722 Binder.getCallingUid(), receiver);
9723 if (rl.app != null) {
9724 rl.app.receivers.add(rl);
9725 } else {
9726 try {
9727 receiver.asBinder().linkToDeath(rl, 0);
9728 } catch (RemoteException e) {
9729 return sticky;
9730 }
9731 rl.linkedToDeath = true;
9732 }
9733 mRegisteredReceivers.put(receiver.asBinder(), rl);
9734 }
9735 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9736 rl.add(bf);
9737 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009738 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009739 }
9740 mReceiverResolver.addFilter(bf);
9741
9742 // Enqueue broadcasts for all existing stickies that match
9743 // this filter.
9744 if (allSticky != null) {
9745 ArrayList receivers = new ArrayList();
9746 receivers.add(bf);
9747
9748 int N = allSticky.size();
9749 for (int i=0; i<N; i++) {
9750 Intent intent = (Intent)allSticky.get(i);
9751 BroadcastRecord r = new BroadcastRecord(intent, null,
9752 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009753 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009754 if (mParallelBroadcasts.size() == 0) {
9755 scheduleBroadcastsLocked();
9756 }
9757 mParallelBroadcasts.add(r);
9758 }
9759 }
9760
9761 return sticky;
9762 }
9763 }
9764
9765 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009766 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767
9768 boolean doNext = false;
9769
9770 synchronized(this) {
9771 ReceiverList rl
9772 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9773 if (rl != null) {
9774 if (rl.curBroadcast != null) {
9775 BroadcastRecord r = rl.curBroadcast;
9776 doNext = finishReceiverLocked(
9777 receiver.asBinder(), r.resultCode, r.resultData,
9778 r.resultExtras, r.resultAbort, true);
9779 }
9780
9781 if (rl.app != null) {
9782 rl.app.receivers.remove(rl);
9783 }
9784 removeReceiverLocked(rl);
9785 if (rl.linkedToDeath) {
9786 rl.linkedToDeath = false;
9787 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9788 }
9789 }
9790 }
9791
9792 if (!doNext) {
9793 return;
9794 }
9795
9796 final long origId = Binder.clearCallingIdentity();
9797 processNextBroadcast(false);
9798 trimApplications();
9799 Binder.restoreCallingIdentity(origId);
9800 }
9801
9802 void removeReceiverLocked(ReceiverList rl) {
9803 mRegisteredReceivers.remove(rl.receiver.asBinder());
9804 int N = rl.size();
9805 for (int i=0; i<N; i++) {
9806 mReceiverResolver.removeFilter(rl.get(i));
9807 }
9808 }
9809
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009810 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9811 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9812 ProcessRecord r = mLruProcesses.get(i);
9813 if (r.thread != null) {
9814 try {
9815 r.thread.dispatchPackageBroadcast(cmd, packages);
9816 } catch (RemoteException ex) {
9817 }
9818 }
9819 }
9820 }
9821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009822 private final int broadcastIntentLocked(ProcessRecord callerApp,
9823 String callerPackage, Intent intent, String resolvedType,
9824 IIntentReceiver resultTo, int resultCode, String resultData,
9825 Bundle map, String requiredPermission,
9826 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9827 intent = new Intent(intent);
9828
Joe Onorato8a9b2202010-02-26 18:56:32 -08009829 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9831 + " ordered=" + ordered);
9832 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009833 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009834 }
9835
9836 // Handle special intents: if this broadcast is from the package
9837 // manager about a package being removed, we need to remove all of
9838 // its activities from the history stack.
9839 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9840 intent.getAction());
9841 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9842 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009843 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009844 || uidRemoved) {
9845 if (checkComponentPermission(
9846 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9847 callingPid, callingUid, -1)
9848 == PackageManager.PERMISSION_GRANTED) {
9849 if (uidRemoved) {
9850 final Bundle intentExtras = intent.getExtras();
9851 final int uid = intentExtras != null
9852 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9853 if (uid >= 0) {
9854 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9855 synchronized (bs) {
9856 bs.removeUidStatsLocked(uid);
9857 }
9858 }
9859 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009860 // If resources are unvailble just force stop all
9861 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009862 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009863 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9864 if (list != null && (list.length > 0)) {
9865 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009866 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009867 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009868 sendPackageBroadcastLocked(
9869 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009870 }
9871 } else {
9872 Uri data = intent.getData();
9873 String ssp;
9874 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9875 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9876 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009877 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009878 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009879 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9880 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9881 new String[] {ssp});
9882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883 }
9884 }
9885 }
9886 } else {
9887 String msg = "Permission Denial: " + intent.getAction()
9888 + " broadcast from " + callerPackage + " (pid=" + callingPid
9889 + ", uid=" + callingUid + ")"
9890 + " requires "
9891 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009892 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009893 throw new SecurityException(msg);
9894 }
9895 }
9896
9897 /*
9898 * If this is the time zone changed action, queue up a message that will reset the timezone
9899 * of all currently running processes. This message will get queued up before the broadcast
9900 * happens.
9901 */
9902 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9903 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9904 }
9905
Dianne Hackborn854060af2009-07-09 18:14:31 -07009906 /*
9907 * Prevent non-system code (defined here to be non-persistent
9908 * processes) from sending protected broadcasts.
9909 */
9910 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9911 || callingUid == Process.SHELL_UID || callingUid == 0) {
9912 // Always okay.
9913 } else if (callerApp == null || !callerApp.persistent) {
9914 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009915 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009916 intent.getAction())) {
9917 String msg = "Permission Denial: not allowed to send broadcast "
9918 + intent.getAction() + " from pid="
9919 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009920 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009921 throw new SecurityException(msg);
9922 }
9923 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009924 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009925 return BROADCAST_SUCCESS;
9926 }
9927 }
9928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009929 // Add to the sticky list if requested.
9930 if (sticky) {
9931 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9932 callingPid, callingUid)
9933 != PackageManager.PERMISSION_GRANTED) {
9934 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9935 + callingPid + ", uid=" + callingUid
9936 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009937 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009938 throw new SecurityException(msg);
9939 }
9940 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009941 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009942 + " and enforce permission " + requiredPermission);
9943 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9944 }
9945 if (intent.getComponent() != null) {
9946 throw new SecurityException(
9947 "Sticky broadcasts can't target a specific component");
9948 }
9949 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9950 if (list == null) {
9951 list = new ArrayList<Intent>();
9952 mStickyBroadcasts.put(intent.getAction(), list);
9953 }
9954 int N = list.size();
9955 int i;
9956 for (i=0; i<N; i++) {
9957 if (intent.filterEquals(list.get(i))) {
9958 // This sticky already exists, replace it.
9959 list.set(i, new Intent(intent));
9960 break;
9961 }
9962 }
9963 if (i >= N) {
9964 list.add(new Intent(intent));
9965 }
9966 }
9967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009968 // Figure out who all will receive this broadcast.
9969 List receivers = null;
9970 List<BroadcastFilter> registeredReceivers = null;
9971 try {
9972 if (intent.getComponent() != null) {
9973 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009974 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009975 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 if (ai != null) {
9977 receivers = new ArrayList();
9978 ResolveInfo ri = new ResolveInfo();
9979 ri.activityInfo = ai;
9980 receivers.add(ri);
9981 }
9982 } else {
9983 // Need to resolve the intent to interested receivers...
9984 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9985 == 0) {
9986 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009987 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009988 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009989 }
Mihai Preda074edef2009-05-18 17:13:31 +02009990 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991 }
9992 } catch (RemoteException ex) {
9993 // pm is in same process, this will never happen.
9994 }
9995
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009996 final boolean replacePending =
9997 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9998
Joe Onorato8a9b2202010-02-26 18:56:32 -08009999 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010000 + " replacePending=" + replacePending);
10001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10003 if (!ordered && NR > 0) {
10004 // If we are not serializing this broadcast, then send the
10005 // registered receivers separately so they don't wait for the
10006 // components to be launched.
10007 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10008 callerPackage, callingPid, callingUid, requiredPermission,
10009 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010010 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010011 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010012 TAG, "Enqueueing parallel broadcast " + r
10013 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010014 boolean replaced = false;
10015 if (replacePending) {
10016 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10017 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010018 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010019 "***** DROPPING PARALLEL: " + intent);
10020 mParallelBroadcasts.set(i, r);
10021 replaced = true;
10022 break;
10023 }
10024 }
10025 }
10026 if (!replaced) {
10027 mParallelBroadcasts.add(r);
10028 scheduleBroadcastsLocked();
10029 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 registeredReceivers = null;
10031 NR = 0;
10032 }
10033
10034 // Merge into one list.
10035 int ir = 0;
10036 if (receivers != null) {
10037 // A special case for PACKAGE_ADDED: do not allow the package
10038 // being added to see this broadcast. This prevents them from
10039 // using this as a back door to get run as soon as they are
10040 // installed. Maybe in the future we want to have a special install
10041 // broadcast or such for apps, but we'd like to deliberately make
10042 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010043 String skipPackages[] = null;
10044 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10045 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10046 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10047 Uri data = intent.getData();
10048 if (data != null) {
10049 String pkgName = data.getSchemeSpecificPart();
10050 if (pkgName != null) {
10051 skipPackages = new String[] { pkgName };
10052 }
10053 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010054 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010055 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010056 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010057 if (skipPackages != null && (skipPackages.length > 0)) {
10058 for (String skipPackage : skipPackages) {
10059 if (skipPackage != null) {
10060 int NT = receivers.size();
10061 for (int it=0; it<NT; it++) {
10062 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10063 if (curt.activityInfo.packageName.equals(skipPackage)) {
10064 receivers.remove(it);
10065 it--;
10066 NT--;
10067 }
10068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010069 }
10070 }
10071 }
10072
10073 int NT = receivers != null ? receivers.size() : 0;
10074 int it = 0;
10075 ResolveInfo curt = null;
10076 BroadcastFilter curr = null;
10077 while (it < NT && ir < NR) {
10078 if (curt == null) {
10079 curt = (ResolveInfo)receivers.get(it);
10080 }
10081 if (curr == null) {
10082 curr = registeredReceivers.get(ir);
10083 }
10084 if (curr.getPriority() >= curt.priority) {
10085 // Insert this broadcast record into the final list.
10086 receivers.add(it, curr);
10087 ir++;
10088 curr = null;
10089 it++;
10090 NT++;
10091 } else {
10092 // Skip to the next ResolveInfo in the final list.
10093 it++;
10094 curt = null;
10095 }
10096 }
10097 }
10098 while (ir < NR) {
10099 if (receivers == null) {
10100 receivers = new ArrayList();
10101 }
10102 receivers.add(registeredReceivers.get(ir));
10103 ir++;
10104 }
10105
10106 if ((receivers != null && receivers.size() > 0)
10107 || resultTo != null) {
10108 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10109 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010110 receivers, resultTo, resultCode, resultData, map, ordered,
10111 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010112 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010113 TAG, "Enqueueing ordered broadcast " + r
10114 + ": prev had " + mOrderedBroadcasts.size());
10115 if (DEBUG_BROADCAST) {
10116 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010117 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010118 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010119 boolean replaced = false;
10120 if (replacePending) {
10121 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10122 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010123 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010124 "***** DROPPING ORDERED: " + intent);
10125 mOrderedBroadcasts.set(i, r);
10126 replaced = true;
10127 break;
10128 }
10129 }
10130 }
10131 if (!replaced) {
10132 mOrderedBroadcasts.add(r);
10133 scheduleBroadcastsLocked();
10134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010135 }
10136
10137 return BROADCAST_SUCCESS;
10138 }
10139
10140 public final int broadcastIntent(IApplicationThread caller,
10141 Intent intent, String resolvedType, IIntentReceiver resultTo,
10142 int resultCode, String resultData, Bundle map,
10143 String requiredPermission, boolean serialized, boolean sticky) {
10144 // Refuse possible leaked file descriptors
10145 if (intent != null && intent.hasFileDescriptors() == true) {
10146 throw new IllegalArgumentException("File descriptors passed in Intent");
10147 }
10148
10149 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010150 int flags = intent.getFlags();
10151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010152 if (!mSystemReady) {
10153 // if the caller really truly claims to know what they're doing, go
10154 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10156 intent = new Intent(intent);
10157 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10158 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080010159 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010160 + " before boot completion");
10161 throw new IllegalStateException("Cannot broadcast before boot completed");
10162 }
10163 }
10164
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010165 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10166 throw new IllegalArgumentException(
10167 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10168 }
10169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010170 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10171 final int callingPid = Binder.getCallingPid();
10172 final int callingUid = Binder.getCallingUid();
10173 final long origId = Binder.clearCallingIdentity();
10174 int res = broadcastIntentLocked(callerApp,
10175 callerApp != null ? callerApp.info.packageName : null,
10176 intent, resolvedType, resultTo,
10177 resultCode, resultData, map, requiredPermission, serialized,
10178 sticky, callingPid, callingUid);
10179 Binder.restoreCallingIdentity(origId);
10180 return res;
10181 }
10182 }
10183
10184 int broadcastIntentInPackage(String packageName, int uid,
10185 Intent intent, String resolvedType, IIntentReceiver resultTo,
10186 int resultCode, String resultData, Bundle map,
10187 String requiredPermission, boolean serialized, boolean sticky) {
10188 synchronized(this) {
10189 final long origId = Binder.clearCallingIdentity();
10190 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10191 resultTo, resultCode, resultData, map, requiredPermission,
10192 serialized, sticky, -1, uid);
10193 Binder.restoreCallingIdentity(origId);
10194 return res;
10195 }
10196 }
10197
10198 public final void unbroadcastIntent(IApplicationThread caller,
10199 Intent intent) {
10200 // Refuse possible leaked file descriptors
10201 if (intent != null && intent.hasFileDescriptors() == true) {
10202 throw new IllegalArgumentException("File descriptors passed in Intent");
10203 }
10204
10205 synchronized(this) {
10206 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10207 != PackageManager.PERMISSION_GRANTED) {
10208 String msg = "Permission Denial: unbroadcastIntent() from pid="
10209 + Binder.getCallingPid()
10210 + ", uid=" + Binder.getCallingUid()
10211 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010212 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 throw new SecurityException(msg);
10214 }
10215 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10216 if (list != null) {
10217 int N = list.size();
10218 int i;
10219 for (i=0; i<N; i++) {
10220 if (intent.filterEquals(list.get(i))) {
10221 list.remove(i);
10222 break;
10223 }
10224 }
10225 }
10226 }
10227 }
10228
10229 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10230 String resultData, Bundle resultExtras, boolean resultAbort,
10231 boolean explicit) {
10232 if (mOrderedBroadcasts.size() == 0) {
10233 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010234 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010235 }
10236 return false;
10237 }
10238 BroadcastRecord r = mOrderedBroadcasts.get(0);
10239 if (r.receiver == null) {
10240 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010241 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 }
10243 return false;
10244 }
10245 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010246 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010247 return false;
10248 }
10249 int state = r.state;
10250 r.state = r.IDLE;
10251 if (state == r.IDLE) {
10252 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010253 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 }
10255 }
10256 r.receiver = null;
10257 r.intent.setComponent(null);
10258 if (r.curApp != null) {
10259 r.curApp.curReceiver = null;
10260 }
10261 if (r.curFilter != null) {
10262 r.curFilter.receiverList.curBroadcast = null;
10263 }
10264 r.curFilter = null;
10265 r.curApp = null;
10266 r.curComponent = null;
10267 r.curReceiver = null;
10268 mPendingBroadcast = null;
10269
10270 r.resultCode = resultCode;
10271 r.resultData = resultData;
10272 r.resultExtras = resultExtras;
10273 r.resultAbort = resultAbort;
10274
10275 // We will process the next receiver right now if this is finishing
10276 // an app receiver (which is always asynchronous) or after we have
10277 // come back from calling a receiver.
10278 return state == BroadcastRecord.APP_RECEIVE
10279 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10280 }
10281
10282 public void finishReceiver(IBinder who, int resultCode, String resultData,
10283 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010284 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010285
10286 // Refuse possible leaked file descriptors
10287 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10288 throw new IllegalArgumentException("File descriptors passed in Bundle");
10289 }
10290
10291 boolean doNext;
10292
10293 final long origId = Binder.clearCallingIdentity();
10294
10295 synchronized(this) {
10296 doNext = finishReceiverLocked(
10297 who, resultCode, resultData, resultExtras, resultAbort, true);
10298 }
10299
10300 if (doNext) {
10301 processNextBroadcast(false);
10302 }
10303 trimApplications();
10304
10305 Binder.restoreCallingIdentity(origId);
10306 }
10307
10308 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10309 if (r.nextReceiver > 0) {
10310 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10311 if (curReceiver instanceof BroadcastFilter) {
10312 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010313 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 System.identityHashCode(r),
10315 r.intent.getAction(),
10316 r.nextReceiver - 1,
10317 System.identityHashCode(bf));
10318 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010319 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 System.identityHashCode(r),
10321 r.intent.getAction(),
10322 r.nextReceiver - 1,
10323 ((ResolveInfo)curReceiver).toString());
10324 }
10325 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010326 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010328 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 System.identityHashCode(r),
10330 r.intent.getAction(),
10331 r.nextReceiver,
10332 "NONE");
10333 }
10334 }
10335
10336 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010337 ProcessRecord app = null;
10338 String anrMessage = null;
10339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340 synchronized (this) {
10341 if (mOrderedBroadcasts.size() == 0) {
10342 return;
10343 }
10344 long now = SystemClock.uptimeMillis();
10345 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010346 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010347 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010348 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010349 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010350 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010351 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010352 return;
10353 }
10354
Joe Onorato8a9b2202010-02-26 18:56:32 -080010355 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010356 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 r.anrCount++;
10358
10359 // Current receiver has passed its expiration date.
10360 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010361 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010362 return;
10363 }
10364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010365 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010366 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010367 logBroadcastReceiverDiscard(r);
10368 if (curReceiver instanceof BroadcastFilter) {
10369 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10370 if (bf.receiverList.pid != 0
10371 && bf.receiverList.pid != MY_PID) {
10372 synchronized (this.mPidsSelfLocked) {
10373 app = this.mPidsSelfLocked.get(
10374 bf.receiverList.pid);
10375 }
10376 }
10377 } else {
10378 app = r.curApp;
10379 }
10380
10381 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010382 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 }
10384
10385 if (mPendingBroadcast == r) {
10386 mPendingBroadcast = null;
10387 }
10388
10389 // Move on to the next receiver.
10390 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10391 r.resultExtras, r.resultAbort, true);
10392 scheduleBroadcastsLocked();
10393 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010394
10395 if (anrMessage != null) {
10396 appNotResponding(app, null, null, anrMessage);
10397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010398 }
10399
10400 private final void processCurBroadcastLocked(BroadcastRecord r,
10401 ProcessRecord app) throws RemoteException {
10402 if (app.thread == null) {
10403 throw new RemoteException();
10404 }
10405 r.receiver = app.thread.asBinder();
10406 r.curApp = app;
10407 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010408 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010409
10410 // Tell the application to launch this receiver.
10411 r.intent.setComponent(r.curComponent);
10412
10413 boolean started = false;
10414 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010415 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010416 "Delivering to component " + r.curComponent
10417 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010418 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010419 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10420 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10421 started = true;
10422 } finally {
10423 if (!started) {
10424 r.receiver = null;
10425 r.curApp = null;
10426 app.curReceiver = null;
10427 }
10428 }
10429
10430 }
10431
10432 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010433 Intent intent, int resultCode, String data, Bundle extras,
10434 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 if (app != null && app.thread != null) {
10436 // If we have an app thread, do the call through that so it is
10437 // correctly ordered with other one-way calls.
10438 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010439 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010440 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010441 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010442 }
10443 }
10444
10445 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10446 BroadcastFilter filter, boolean ordered) {
10447 boolean skip = false;
10448 if (filter.requiredPermission != null) {
10449 int perm = checkComponentPermission(filter.requiredPermission,
10450 r.callingPid, r.callingUid, -1);
10451 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010452 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010453 + r.intent.toString()
10454 + " from " + r.callerPackage + " (pid="
10455 + r.callingPid + ", uid=" + r.callingUid + ")"
10456 + " requires " + filter.requiredPermission
10457 + " due to registered receiver " + filter);
10458 skip = true;
10459 }
10460 }
10461 if (r.requiredPermission != null) {
10462 int perm = checkComponentPermission(r.requiredPermission,
10463 filter.receiverList.pid, filter.receiverList.uid, -1);
10464 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010465 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010466 + r.intent.toString()
10467 + " to " + filter.receiverList.app
10468 + " (pid=" + filter.receiverList.pid
10469 + ", uid=" + filter.receiverList.uid + ")"
10470 + " requires " + r.requiredPermission
10471 + " due to sender " + r.callerPackage
10472 + " (uid " + r.callingUid + ")");
10473 skip = true;
10474 }
10475 }
10476
10477 if (!skip) {
10478 // If this is not being sent as an ordered broadcast, then we
10479 // don't want to touch the fields that keep track of the current
10480 // state of ordered broadcasts.
10481 if (ordered) {
10482 r.receiver = filter.receiverList.receiver.asBinder();
10483 r.curFilter = filter;
10484 filter.receiverList.curBroadcast = r;
10485 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010486 if (filter.receiverList.app != null) {
10487 // Bump hosting application to no longer be in background
10488 // scheduling class. Note that we can't do that if there
10489 // isn't an app... but we can only be in that case for
10490 // things that directly call the IActivityManager API, which
10491 // are already core system stuff so don't matter for this.
10492 r.curApp = filter.receiverList.app;
10493 filter.receiverList.app.curReceiver = r;
10494 updateOomAdjLocked();
10495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010496 }
10497 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010498 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010499 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010500 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010501 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010502 }
10503 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10504 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010505 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010506 if (ordered) {
10507 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10508 }
10509 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010510 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010511 if (ordered) {
10512 r.receiver = null;
10513 r.curFilter = null;
10514 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010515 if (filter.receiverList.app != null) {
10516 filter.receiverList.app.curReceiver = null;
10517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518 }
10519 }
10520 }
10521 }
10522
Dianne Hackborn12527f92009-11-11 17:39:50 -080010523 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10524 if (r.callingUid < 0) {
10525 // This was from a registerReceiver() call; ignore it.
10526 return;
10527 }
10528 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10529 MAX_BROADCAST_HISTORY-1);
10530 r.finishTime = SystemClock.uptimeMillis();
10531 mBroadcastHistory[0] = r;
10532 }
10533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010534 private final void processNextBroadcast(boolean fromMsg) {
10535 synchronized(this) {
10536 BroadcastRecord r;
10537
Joe Onorato8a9b2202010-02-26 18:56:32 -080010538 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010540 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010541
10542 updateCpuStats();
10543
10544 if (fromMsg) {
10545 mBroadcastsScheduled = false;
10546 }
10547
10548 // First, deliver any non-serialized broadcasts right away.
10549 while (mParallelBroadcasts.size() > 0) {
10550 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010551 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010552 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010553 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010554 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010555 for (int i=0; i<N; i++) {
10556 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010557 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010558 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010559 + target + ": " + r);
10560 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10561 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010562 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010563 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010564 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010565 }
10566
10567 // Now take care of the next serialized one...
10568
10569 // If we are waiting for a process to come up to handle the next
10570 // broadcast, then do nothing at this point. Just in case, we
10571 // check that the process we're waiting for still exists.
10572 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010573 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010574 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010575 + mPendingBroadcast.curApp);
10576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010577
10578 boolean isDead;
10579 synchronized (mPidsSelfLocked) {
10580 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10581 }
10582 if (!isDead) {
10583 // It's still alive, so keep waiting
10584 return;
10585 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010586 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010587 + " died before responding to broadcast");
10588 mPendingBroadcast = null;
10589 }
10590 }
10591
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010592 boolean looped = false;
10593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010594 do {
10595 if (mOrderedBroadcasts.size() == 0) {
10596 // No more broadcasts pending, so all done!
10597 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010598 if (looped) {
10599 // If we had finished the last ordered broadcast, then
10600 // make sure all processes have correct oom and sched
10601 // adjustments.
10602 updateOomAdjLocked();
10603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010604 return;
10605 }
10606 r = mOrderedBroadcasts.get(0);
10607 boolean forceReceive = false;
10608
10609 // Ensure that even if something goes awry with the timeout
10610 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010611 // and continue to make progress.
10612 //
10613 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10614 // receivers don't get executed with with timeouts. They're intended for
10615 // one time heavy lifting after system upgrades and can take
10616 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010617 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010618 if (mSystemReady && r.dispatchTime > 0) {
10619 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 if ((numReceivers > 0) &&
10621 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010622 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010623 + " now=" + now
10624 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010625 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010626 + " intent=" + r.intent
10627 + " numReceivers=" + numReceivers
10628 + " nextReceiver=" + r.nextReceiver
10629 + " state=" + r.state);
10630 broadcastTimeout(); // forcibly finish this broadcast
10631 forceReceive = true;
10632 r.state = BroadcastRecord.IDLE;
10633 }
10634 }
10635
10636 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010637 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010638 "processNextBroadcast() called when not idle (state="
10639 + r.state + ")");
10640 return;
10641 }
10642
10643 if (r.receivers == null || r.nextReceiver >= numReceivers
10644 || r.resultAbort || forceReceive) {
10645 // No more receivers for this broadcast! Send the final
10646 // result if requested...
10647 if (r.resultTo != null) {
10648 try {
10649 if (DEBUG_BROADCAST) {
10650 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010651 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 + " seq=" + seq + " app=" + r.callerApp);
10653 }
10654 performReceive(r.callerApp, r.resultTo,
10655 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010656 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010657 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010658 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010659 }
10660 }
10661
Joe Onorato8a9b2202010-02-26 18:56:32 -080010662 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010663 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10664
Joe Onorato8a9b2202010-02-26 18:56:32 -080010665 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010666 + r);
10667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010668 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010669 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010670 mOrderedBroadcasts.remove(0);
10671 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010672 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673 continue;
10674 }
10675 } while (r == null);
10676
10677 // Get the next receiver...
10678 int recIdx = r.nextReceiver++;
10679
10680 // Keep track of when this receiver started, and make sure there
10681 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010682 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010683 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010684 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010685
Joe Onorato8a9b2202010-02-26 18:56:32 -080010686 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010687 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010688 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010689 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010690 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010692 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010693 }
10694
10695 Object nextReceiver = r.receivers.get(recIdx);
10696 if (nextReceiver instanceof BroadcastFilter) {
10697 // Simple case: this is a registered receiver who gets
10698 // a direct call.
10699 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010700 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010701 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 + filter + ": " + r);
10703 deliverToRegisteredReceiver(r, filter, r.ordered);
10704 if (r.receiver == null || !r.ordered) {
10705 // The receiver has already finished, so schedule to
10706 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010707 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10708 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010709 r.state = BroadcastRecord.IDLE;
10710 scheduleBroadcastsLocked();
10711 }
10712 return;
10713 }
10714
10715 // Hard case: need to instantiate the receiver, possibly
10716 // starting its application process to host it.
10717
10718 ResolveInfo info =
10719 (ResolveInfo)nextReceiver;
10720
10721 boolean skip = false;
10722 int perm = checkComponentPermission(info.activityInfo.permission,
10723 r.callingPid, r.callingUid,
10724 info.activityInfo.exported
10725 ? -1 : info.activityInfo.applicationInfo.uid);
10726 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010727 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010728 + r.intent.toString()
10729 + " from " + r.callerPackage + " (pid=" + r.callingPid
10730 + ", uid=" + r.callingUid + ")"
10731 + " requires " + info.activityInfo.permission
10732 + " due to receiver " + info.activityInfo.packageName
10733 + "/" + info.activityInfo.name);
10734 skip = true;
10735 }
10736 if (r.callingUid != Process.SYSTEM_UID &&
10737 r.requiredPermission != null) {
10738 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010739 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010740 checkPermission(r.requiredPermission,
10741 info.activityInfo.applicationInfo.packageName);
10742 } catch (RemoteException e) {
10743 perm = PackageManager.PERMISSION_DENIED;
10744 }
10745 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010746 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010747 + r.intent + " to "
10748 + info.activityInfo.applicationInfo.packageName
10749 + " requires " + r.requiredPermission
10750 + " due to sender " + r.callerPackage
10751 + " (uid " + r.callingUid + ")");
10752 skip = true;
10753 }
10754 }
10755 if (r.curApp != null && r.curApp.crashing) {
10756 // If the target process is crashing, just skip it.
10757 skip = true;
10758 }
10759
10760 if (skip) {
10761 r.receiver = null;
10762 r.curFilter = null;
10763 r.state = BroadcastRecord.IDLE;
10764 scheduleBroadcastsLocked();
10765 return;
10766 }
10767
10768 r.state = BroadcastRecord.APP_RECEIVE;
10769 String targetProcess = info.activityInfo.processName;
10770 r.curComponent = new ComponentName(
10771 info.activityInfo.applicationInfo.packageName,
10772 info.activityInfo.name);
10773 r.curReceiver = info.activityInfo;
10774
10775 // Is this receiver's application already running?
10776 ProcessRecord app = getProcessRecordLocked(targetProcess,
10777 info.activityInfo.applicationInfo.uid);
10778 if (app != null && app.thread != null) {
10779 try {
10780 processCurBroadcastLocked(r, app);
10781 return;
10782 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010783 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784 + r.curComponent, e);
10785 }
10786
10787 // If a dead object exception was thrown -- fall through to
10788 // restart the application.
10789 }
10790
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010791 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010792 if ((r.curApp=startProcessLocked(targetProcess,
10793 info.activityInfo.applicationInfo, true,
10794 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010795 "broadcast", r.curComponent,
10796 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10797 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010798 // Ah, this recipient is unavailable. Finish it if necessary,
10799 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010800 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 + info.activityInfo.applicationInfo.packageName + "/"
10802 + info.activityInfo.applicationInfo.uid + " for broadcast "
10803 + r.intent + ": process is bad");
10804 logBroadcastReceiverDiscard(r);
10805 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10806 r.resultExtras, r.resultAbort, true);
10807 scheduleBroadcastsLocked();
10808 r.state = BroadcastRecord.IDLE;
10809 return;
10810 }
10811
10812 mPendingBroadcast = r;
10813 }
10814 }
10815
10816 // =========================================================
10817 // INSTRUMENTATION
10818 // =========================================================
10819
10820 public boolean startInstrumentation(ComponentName className,
10821 String profileFile, int flags, Bundle arguments,
10822 IInstrumentationWatcher watcher) {
10823 // Refuse possible leaked file descriptors
10824 if (arguments != null && arguments.hasFileDescriptors()) {
10825 throw new IllegalArgumentException("File descriptors passed in Bundle");
10826 }
10827
10828 synchronized(this) {
10829 InstrumentationInfo ii = null;
10830 ApplicationInfo ai = null;
10831 try {
10832 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010833 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010834 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010835 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 } catch (PackageManager.NameNotFoundException e) {
10837 }
10838 if (ii == null) {
10839 reportStartInstrumentationFailure(watcher, className,
10840 "Unable to find instrumentation info for: " + className);
10841 return false;
10842 }
10843 if (ai == null) {
10844 reportStartInstrumentationFailure(watcher, className,
10845 "Unable to find instrumentation target package: " + ii.targetPackage);
10846 return false;
10847 }
10848
10849 int match = mContext.getPackageManager().checkSignatures(
10850 ii.targetPackage, ii.packageName);
10851 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10852 String msg = "Permission Denial: starting instrumentation "
10853 + className + " from pid="
10854 + Binder.getCallingPid()
10855 + ", uid=" + Binder.getCallingPid()
10856 + " not allowed because package " + ii.packageName
10857 + " does not have a signature matching the target "
10858 + ii.targetPackage;
10859 reportStartInstrumentationFailure(watcher, className, msg);
10860 throw new SecurityException(msg);
10861 }
10862
10863 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010864 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010865 ProcessRecord app = addAppLocked(ai);
10866 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010867 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010868 app.instrumentationProfileFile = profileFile;
10869 app.instrumentationArguments = arguments;
10870 app.instrumentationWatcher = watcher;
10871 app.instrumentationResultClass = className;
10872 Binder.restoreCallingIdentity(origId);
10873 }
10874
10875 return true;
10876 }
10877
10878 /**
10879 * Report errors that occur while attempting to start Instrumentation. Always writes the
10880 * error to the logs, but if somebody is watching, send the report there too. This enables
10881 * the "am" command to report errors with more information.
10882 *
10883 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10884 * @param cn The component name of the instrumentation.
10885 * @param report The error report.
10886 */
10887 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10888 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010889 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010890 try {
10891 if (watcher != null) {
10892 Bundle results = new Bundle();
10893 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10894 results.putString("Error", report);
10895 watcher.instrumentationStatus(cn, -1, results);
10896 }
10897 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010898 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010899 }
10900 }
10901
10902 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10903 if (app.instrumentationWatcher != null) {
10904 try {
10905 // NOTE: IInstrumentationWatcher *must* be oneway here
10906 app.instrumentationWatcher.instrumentationFinished(
10907 app.instrumentationClass,
10908 resultCode,
10909 results);
10910 } catch (RemoteException e) {
10911 }
10912 }
10913 app.instrumentationWatcher = null;
10914 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010915 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010916 app.instrumentationProfileFile = null;
10917 app.instrumentationArguments = null;
10918
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010919 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010920 }
10921
10922 public void finishInstrumentation(IApplicationThread target,
10923 int resultCode, Bundle results) {
10924 // Refuse possible leaked file descriptors
10925 if (results != null && results.hasFileDescriptors()) {
10926 throw new IllegalArgumentException("File descriptors passed in Intent");
10927 }
10928
10929 synchronized(this) {
10930 ProcessRecord app = getRecordForAppLocked(target);
10931 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010932 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010933 return;
10934 }
10935 final long origId = Binder.clearCallingIdentity();
10936 finishInstrumentationLocked(app, resultCode, results);
10937 Binder.restoreCallingIdentity(origId);
10938 }
10939 }
10940
10941 // =========================================================
10942 // CONFIGURATION
10943 // =========================================================
10944
10945 public ConfigurationInfo getDeviceConfigurationInfo() {
10946 ConfigurationInfo config = new ConfigurationInfo();
10947 synchronized (this) {
10948 config.reqTouchScreen = mConfiguration.touchscreen;
10949 config.reqKeyboardType = mConfiguration.keyboard;
10950 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010951 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10952 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010953 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10954 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010955 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10956 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10958 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010959 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 }
10961 return config;
10962 }
10963
10964 public Configuration getConfiguration() {
10965 Configuration ci;
10966 synchronized(this) {
10967 ci = new Configuration(mConfiguration);
10968 }
10969 return ci;
10970 }
10971
10972 public void updateConfiguration(Configuration values) {
10973 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10974 "updateConfiguration()");
10975
10976 synchronized(this) {
10977 if (values == null && mWindowManager != null) {
10978 // sentinel: fetch the current configuration from the window manager
10979 values = mWindowManager.computeNewConfiguration();
10980 }
10981
10982 final long origId = Binder.clearCallingIdentity();
10983 updateConfigurationLocked(values, null);
10984 Binder.restoreCallingIdentity(origId);
10985 }
10986 }
10987
10988 /**
10989 * Do either or both things: (1) change the current configuration, and (2)
10990 * make sure the given activity is running with the (now) current
10991 * configuration. Returns true if the activity has been left running, or
10992 * false if <var>starting</var> is being destroyed to match the new
10993 * configuration.
10994 */
10995 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010996 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 int changes = 0;
10998
10999 boolean kept = true;
11000
11001 if (values != null) {
11002 Configuration newConfig = new Configuration(mConfiguration);
11003 changes = newConfig.updateFrom(values);
11004 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011005 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011006 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 }
11008
Doug Zongker2bec3d42009-12-04 12:52:44 -080011009 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011010
11011 if (values.locale != null) {
11012 saveLocaleLocked(values.locale,
11013 !values.locale.equals(mConfiguration.locale),
11014 values.userSetLocale);
11015 }
11016
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011017 mConfigurationSeq++;
11018 if (mConfigurationSeq <= 0) {
11019 mConfigurationSeq = 1;
11020 }
11021 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011022 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011023 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011024
11025 AttributeCache ac = AttributeCache.instance();
11026 if (ac != null) {
11027 ac.updateConfiguration(mConfiguration);
11028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011030 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11031 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11032 msg.obj = new Configuration(mConfiguration);
11033 mHandler.sendMessage(msg);
11034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011035
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011036 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11037 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011038 try {
11039 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011040 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011041 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 app.thread.scheduleConfigurationChanged(mConfiguration);
11043 }
11044 } catch (Exception e) {
11045 }
11046 }
11047 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011048 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11049 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011050 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11051 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011052 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11053 broadcastIntentLocked(null, null,
11054 new Intent(Intent.ACTION_LOCALE_CHANGED),
11055 null, null, 0, null, null,
11056 null, false, false, MY_PID, Process.SYSTEM_UID);
11057 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058 }
11059 }
11060
11061 if (changes != 0 && starting == null) {
11062 // If the configuration changed, and the caller is not already
11063 // in the process of starting an activity, then find the top
11064 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011065 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011066 }
11067
11068 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011069 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 if (kept) {
11071 // If this didn't result in the starting activity being
11072 // destroyed, then we need to make sure at this point that all
11073 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011074 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011076 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 }
11078 }
11079
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011080 if (values != null && mWindowManager != null) {
11081 mWindowManager.setNewConfiguration(mConfiguration);
11082 }
11083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 return kept;
11085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011086
11087 /**
11088 * Save the locale. You must be inside a synchronized (this) block.
11089 */
11090 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11091 if(isDiff) {
11092 SystemProperties.set("user.language", l.getLanguage());
11093 SystemProperties.set("user.region", l.getCountry());
11094 }
11095
11096 if(isPersist) {
11097 SystemProperties.set("persist.sys.language", l.getLanguage());
11098 SystemProperties.set("persist.sys.country", l.getCountry());
11099 SystemProperties.set("persist.sys.localevar", l.getVariant());
11100 }
11101 }
11102
11103 // =========================================================
11104 // LIFETIME MANAGEMENT
11105 // =========================================================
11106
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011107 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11108 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011110 // This adjustment has already been computed. If we are calling
11111 // from the top, we may have already computed our adjustment with
11112 // an earlier hidden adjustment that isn't really for us... if
11113 // so, use the new hidden adjustment.
11114 if (!recursed && app.hidden) {
11115 app.curAdj = hiddenAdj;
11116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 return app.curAdj;
11118 }
11119
11120 if (app.thread == null) {
11121 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011122 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011123 return (app.curAdj=EMPTY_APP_ADJ);
11124 }
11125
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011126 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11127 // The max adjustment doesn't allow this app to be anything
11128 // below foreground, so it is not worth doing work for it.
11129 app.adjType = "fixed";
11130 app.adjSeq = mAdjSeq;
11131 app.curRawAdj = app.maxAdj;
11132 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11133 return (app.curAdj=app.maxAdj);
11134 }
11135
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011136 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011137 app.adjSource = null;
11138 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011139 app.empty = false;
11140 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141
The Android Open Source Project4df24232009-03-05 14:34:35 -080011142 // Determine the importance of the process, starting with most
11143 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011145 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011146 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011147 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011148 // The last app on the list is the foreground app.
11149 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011150 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011151 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011152 } else if (app.instrumentationClass != null) {
11153 // Don't want to kill running instrumentation.
11154 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011155 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011156 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011157 } else if (app.persistentActivities > 0) {
11158 // Special persistent activities... shouldn't be used these days.
11159 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011160 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011161 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011162 } else if (app.curReceiver != null ||
11163 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11164 // An app that is currently receiving a broadcast also
11165 // counts as being in the foreground.
11166 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011167 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011168 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 } else if (app.executingServices.size() > 0) {
11170 // An app that is currently executing a service callback also
11171 // counts as being in the foreground.
11172 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011173 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011174 app.adjType = "exec-service";
11175 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011176 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011177 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011178 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011179 app.adjType = "foreground-service";
11180 } else if (app.forcingToForeground != null) {
11181 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011182 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011183 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011184 app.adjType = "force-foreground";
11185 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011186 } else if (app == mHeavyWeightProcess) {
11187 // We don't want to kill the current heavy-weight process.
11188 adj = HEAVY_WEIGHT_APP_ADJ;
11189 schedGroup = Process.THREAD_GROUP_DEFAULT;
11190 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011191 } else if (app == mHomeProcess) {
11192 // This process is hosting what we currently consider to be the
11193 // home app, so we don't want to let it go into the background.
11194 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011195 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011196 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011197 } else if ((N=app.activities.size()) != 0) {
11198 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011199 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011200 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011201 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011202 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011203 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011205 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011206 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011207 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011208 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011209 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011210 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011211 break;
11212 }
11213 }
11214 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011215 // A very not-needed process. If this is lower in the lru list,
11216 // we will push it in to the empty bucket.
11217 app.hidden = true;
11218 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011219 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011220 adj = hiddenAdj;
11221 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011222 }
11223
Joe Onorato8a9b2202010-02-26 18:56:32 -080011224 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011225
The Android Open Source Project4df24232009-03-05 14:34:35 -080011226 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 // there are applications dependent on our services or providers, but
11228 // this gives us a baseline and makes sure we don't get into an
11229 // infinite recursion.
11230 app.adjSeq = mAdjSeq;
11231 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011232
Christopher Tate6fa95972009-06-05 18:43:55 -070011233 if (mBackupTarget != null && app == mBackupTarget.app) {
11234 // If possible we want to avoid killing apps while they're being backed up
11235 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011236 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011237 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011238 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011239 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011240 }
11241 }
11242
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011243 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11244 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245 final long now = SystemClock.uptimeMillis();
11246 // This process is more important if the top activity is
11247 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011248 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011249 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011250 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011251 if (s.startRequested) {
11252 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11253 // This service has seen some activity within
11254 // recent memory, so we will keep its process ahead
11255 // of the background processes.
11256 if (adj > SECONDARY_SERVER_ADJ) {
11257 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011258 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011259 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 }
11261 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011262 // If we have let the service slide into the background
11263 // state, still have some text describing what it is doing
11264 // even though the service no longer has an impact.
11265 if (adj > SECONDARY_SERVER_ADJ) {
11266 app.adjType = "started-bg-services";
11267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011268 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011269 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11270 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011271 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 = s.connections.values().iterator();
11273 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011274 ArrayList<ConnectionRecord> clist = kt.next();
11275 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11276 // XXX should compute this based on the max of
11277 // all connected clients.
11278 ConnectionRecord cr = clist.get(i);
11279 if (cr.binding.client == app) {
11280 // Binding to ourself is not interesting.
11281 continue;
11282 }
11283 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11284 ProcessRecord client = cr.binding.client;
11285 int myHiddenAdj = hiddenAdj;
11286 if (myHiddenAdj > client.hiddenAdj) {
11287 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11288 myHiddenAdj = client.hiddenAdj;
11289 } else {
11290 myHiddenAdj = VISIBLE_APP_ADJ;
11291 }
11292 }
11293 int clientAdj = computeOomAdjLocked(
11294 client, myHiddenAdj, TOP_APP, true);
11295 if (adj > clientAdj) {
11296 adj = clientAdj >= VISIBLE_APP_ADJ
11297 ? clientAdj : VISIBLE_APP_ADJ;
11298 if (!client.hidden) {
11299 app.hidden = false;
11300 }
11301 app.adjType = "service";
11302 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11303 .REASON_SERVICE_IN_USE;
11304 app.adjSource = cr.binding.client;
11305 app.adjTarget = s.name;
11306 }
11307 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11308 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11309 schedGroup = Process.THREAD_GROUP_DEFAULT;
11310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011311 }
11312 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011313 ActivityRecord a = cr.activity;
11314 //if (a != null) {
11315 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11316 //}
11317 if (a != null && adj > FOREGROUND_APP_ADJ &&
11318 (a.state == ActivityState.RESUMED
11319 || a.state == ActivityState.PAUSING)) {
11320 adj = FOREGROUND_APP_ADJ;
11321 schedGroup = Process.THREAD_GROUP_DEFAULT;
11322 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011323 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011324 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11325 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011326 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011327 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 }
11330 }
11331 }
11332 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011333
11334 // Finally, f this process has active services running in it, we
11335 // would like to avoid killing it unless it would prevent the current
11336 // application from running. By default we put the process in
11337 // with the rest of the background processes; as we scan through
11338 // its services we may bump it up from there.
11339 if (adj > hiddenAdj) {
11340 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011341 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011342 app.adjType = "bg-services";
11343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011344 }
11345
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011346 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11347 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011348 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011349 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11350 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011351 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011352 if (cpr.clients.size() != 0) {
11353 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11354 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11355 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011356 if (client == app) {
11357 // Being our own client is not interesting.
11358 continue;
11359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 int myHiddenAdj = hiddenAdj;
11361 if (myHiddenAdj > client.hiddenAdj) {
11362 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11363 myHiddenAdj = client.hiddenAdj;
11364 } else {
11365 myHiddenAdj = FOREGROUND_APP_ADJ;
11366 }
11367 }
11368 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011369 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 if (adj > clientAdj) {
11371 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011372 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011373 if (!client.hidden) {
11374 app.hidden = false;
11375 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011376 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011377 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11378 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011379 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011380 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011381 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011382 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11383 schedGroup = Process.THREAD_GROUP_DEFAULT;
11384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011385 }
11386 }
11387 // If the provider has external (non-framework) process
11388 // dependencies, ensure that its adjustment is at least
11389 // FOREGROUND_APP_ADJ.
11390 if (cpr.externals != 0) {
11391 if (adj > FOREGROUND_APP_ADJ) {
11392 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011393 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011394 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011395 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011396 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011397 }
11398 }
11399 }
11400 }
11401
11402 app.curRawAdj = adj;
11403
Joe Onorato8a9b2202010-02-26 18:56:32 -080011404 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11406 if (adj > app.maxAdj) {
11407 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011408 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011409 schedGroup = Process.THREAD_GROUP_DEFAULT;
11410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011411 }
11412
11413 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011414 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011416 return adj;
11417 }
11418
11419 /**
11420 * Ask a given process to GC right now.
11421 */
11422 final void performAppGcLocked(ProcessRecord app) {
11423 try {
11424 app.lastRequestedGc = SystemClock.uptimeMillis();
11425 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011426 if (app.reportLowMemory) {
11427 app.reportLowMemory = false;
11428 app.thread.scheduleLowMemory();
11429 } else {
11430 app.thread.processInBackground();
11431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 }
11433 } catch (Exception e) {
11434 // whatever.
11435 }
11436 }
11437
11438 /**
11439 * Returns true if things are idle enough to perform GCs.
11440 */
Josh Bartel7f208742010-02-25 11:01:44 -060011441 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 return mParallelBroadcasts.size() == 0
11443 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011444 && (mSleeping || (mMainStack.mResumedActivity != null &&
11445 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 }
11447
11448 /**
11449 * Perform GCs on all processes that are waiting for it, but only
11450 * if things are idle.
11451 */
11452 final void performAppGcsLocked() {
11453 final int N = mProcessesToGc.size();
11454 if (N <= 0) {
11455 return;
11456 }
Josh Bartel7f208742010-02-25 11:01:44 -060011457 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011458 while (mProcessesToGc.size() > 0) {
11459 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011460 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011461 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11462 <= SystemClock.uptimeMillis()) {
11463 // To avoid spamming the system, we will GC processes one
11464 // at a time, waiting a few seconds between each.
11465 performAppGcLocked(proc);
11466 scheduleAppGcsLocked();
11467 return;
11468 } else {
11469 // It hasn't been long enough since we last GCed this
11470 // process... put it in the list to wait for its time.
11471 addProcessToGcListLocked(proc);
11472 break;
11473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 }
11475 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011476
11477 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011478 }
11479 }
11480
11481 /**
11482 * If all looks good, perform GCs on all processes waiting for them.
11483 */
11484 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011485 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011486 performAppGcsLocked();
11487 return;
11488 }
11489 // Still not idle, wait some more.
11490 scheduleAppGcsLocked();
11491 }
11492
11493 /**
11494 * Schedule the execution of all pending app GCs.
11495 */
11496 final void scheduleAppGcsLocked() {
11497 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011498
11499 if (mProcessesToGc.size() > 0) {
11500 // Schedule a GC for the time to the next process.
11501 ProcessRecord proc = mProcessesToGc.get(0);
11502 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11503
11504 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11505 long now = SystemClock.uptimeMillis();
11506 if (when < (now+GC_TIMEOUT)) {
11507 when = now + GC_TIMEOUT;
11508 }
11509 mHandler.sendMessageAtTime(msg, when);
11510 }
11511 }
11512
11513 /**
11514 * Add a process to the array of processes waiting to be GCed. Keeps the
11515 * list in sorted order by the last GC time. The process can't already be
11516 * on the list.
11517 */
11518 final void addProcessToGcListLocked(ProcessRecord proc) {
11519 boolean added = false;
11520 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11521 if (mProcessesToGc.get(i).lastRequestedGc <
11522 proc.lastRequestedGc) {
11523 added = true;
11524 mProcessesToGc.add(i+1, proc);
11525 break;
11526 }
11527 }
11528 if (!added) {
11529 mProcessesToGc.add(0, proc);
11530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011531 }
11532
11533 /**
11534 * Set up to ask a process to GC itself. This will either do it
11535 * immediately, or put it on the list of processes to gc the next
11536 * time things are idle.
11537 */
11538 final void scheduleAppGcLocked(ProcessRecord app) {
11539 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011540 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 return;
11542 }
11543 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011544 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 scheduleAppGcsLocked();
11546 }
11547 }
11548
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011549 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11550 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11551 if (mLastWakeLockCheckTime == 0) {
11552 doKills = false;
11553 }
11554 if (stats.isScreenOn()) {
11555 doKills = false;
11556 }
11557 final long curRealtime = SystemClock.elapsedRealtime();
11558 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11559 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011560 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011561 doKills = false;
11562 }
11563 int i = mLruProcesses.size();
11564 while (i > 0) {
11565 i--;
11566 ProcessRecord app = mLruProcesses.get(i);
11567 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11568 long wtime;
11569 synchronized (stats) {
11570 wtime = stats.getProcessWakeTime(app.info.uid,
11571 app.pid, curRealtime);
11572 }
11573 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011574 if (false) {
11575 StringBuilder sb = new StringBuilder(128);
11576 sb.append("Wake for ");
11577 app.toShortString(sb);
11578 sb.append(": over ");
11579 TimeUtils.formatDuration(timeSince, sb);
11580 sb.append(" used ");
11581 TimeUtils.formatDuration(timeUsed, sb);
11582 sb.append(" (");
11583 sb.append((timeUsed*100)/timeSince);
11584 sb.append("%)");
11585 Slog.i(TAG, sb.toString());
11586 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011587 // If a process has held a wake lock for more
11588 // than 50% of the time during this period,
11589 // that sounds pad. Kill!
11590 if (doKills && timeSince > 0
11591 && ((timeUsed*100)/timeSince) >= 50) {
11592 Slog.i(TAG, "Excessive wake lock in " + app.processName
11593 + " (pid " + app.pid + "): held " + timeUsed
11594 + " during " + timeSince);
11595 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11596 app.processName, app.setAdj, "excessive wake lock");
11597 Process.killProcessQuiet(app.pid);
11598 } else {
11599 app.lastWakeTime = wtime;
11600 }
11601 }
11602 }
11603 }
11604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011605 private final boolean updateOomAdjLocked(
11606 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11607 app.hiddenAdj = hiddenAdj;
11608
11609 if (app.thread == null) {
11610 return true;
11611 }
11612
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011613 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011615 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 if (app.curRawAdj != app.setRawAdj) {
11617 if (app.curRawAdj > FOREGROUND_APP_ADJ
11618 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11619 // If this app is transitioning from foreground to
11620 // non-foreground, have it do a gc.
11621 scheduleAppGcLocked(app);
11622 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11623 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11624 // Likewise do a gc when an app is moving in to the
11625 // background (such as a service stopping).
11626 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011627 // And note its current wake lock time.
11628 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11629 synchronized (stats) {
11630 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11631 app.pid, SystemClock.elapsedRealtime());
11632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 }
11634 app.setRawAdj = app.curRawAdj;
11635 }
11636 if (adj != app.setAdj) {
11637 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011638 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 TAG, "Set app " + app.processName +
11640 " oom adj to " + adj);
11641 app.setAdj = adj;
11642 } else {
11643 return false;
11644 }
11645 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011646 if (app.setSchedGroup != app.curSchedGroup) {
11647 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011648 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011649 "Setting process group of " + app.processName
11650 + " to " + app.curSchedGroup);
11651 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011652 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011653 try {
11654 Process.setProcessGroup(app.pid, app.curSchedGroup);
11655 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011656 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011657 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011658 e.printStackTrace();
11659 } finally {
11660 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011661 }
11662 }
11663 if (false) {
11664 if (app.thread != null) {
11665 try {
11666 app.thread.setSchedulingGroup(app.curSchedGroup);
11667 } catch (RemoteException e) {
11668 }
11669 }
11670 }
11671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672 }
11673
11674 return true;
11675 }
11676
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011677 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011678 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011679 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011680 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011681 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011682 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 }
11684 }
11685 return resumedActivity;
11686 }
11687
11688 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011689 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011690 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11691 int curAdj = app.curAdj;
11692 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11693 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11694
11695 mAdjSeq++;
11696
11697 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11698 if (res) {
11699 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11700 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11701 if (nowHidden != wasHidden) {
11702 // Changed to/from hidden state, so apps after it in the LRU
11703 // list may also be changed.
11704 updateOomAdjLocked();
11705 }
11706 }
11707 return res;
11708 }
11709
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011710 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011711 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011712 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011713 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11714
11715 if (false) {
11716 RuntimeException e = new RuntimeException();
11717 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011718 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011719 }
11720
11721 mAdjSeq++;
11722
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011723 // Let's determine how many processes we have running vs.
11724 // how many slots we have for background processes; we may want
11725 // to put multiple processes in a slot of there are enough of
11726 // them.
11727 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11728 int factor = (mLruProcesses.size()-4)/numSlots;
11729 if (factor < 1) factor = 1;
11730 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011731 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011733 // First try updating the OOM adjustment for each of the
11734 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011735 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011736 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11737 while (i > 0) {
11738 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011739 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011740 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011741 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011742 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011743 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011744 step++;
11745 if (step >= factor) {
11746 step = 0;
11747 curHiddenAdj++;
11748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011749 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011750 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011751 if (!app.killedBackground) {
11752 numHidden++;
11753 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011754 Slog.i(TAG, "No longer want " + app.processName
11755 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011756 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11757 app.processName, app.setAdj, "too many background");
11758 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011759 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011760 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011761 }
11762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 } else {
11764 didOomAdj = false;
11765 }
11766 }
11767
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011768 // If we return false, we will fall back on killing processes to
11769 // have a fixed limit. Do this if a limit has been requested; else
11770 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11772 }
11773
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011774 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011775 synchronized (this) {
11776 int i;
11777
11778 // First remove any unused application processes whose package
11779 // has been removed.
11780 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11781 final ProcessRecord app = mRemovedProcesses.get(i);
11782 if (app.activities.size() == 0
11783 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011784 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 TAG, "Exiting empty application process "
11786 + app.processName + " ("
11787 + (app.thread != null ? app.thread.asBinder() : null)
11788 + ")\n");
11789 if (app.pid > 0 && app.pid != MY_PID) {
11790 Process.killProcess(app.pid);
11791 } else {
11792 try {
11793 app.thread.scheduleExit();
11794 } catch (Exception e) {
11795 // Ignore exceptions.
11796 }
11797 }
11798 cleanUpApplicationRecordLocked(app, false, -1);
11799 mRemovedProcesses.remove(i);
11800
11801 if (app.persistent) {
11802 if (app.persistent) {
11803 addAppLocked(app.info);
11804 }
11805 }
11806 }
11807 }
11808
11809 // Now try updating the OOM adjustment for each of the
11810 // application processes based on their current state.
11811 // If the setOomAdj() API is not supported, then go with our
11812 // back-up plan...
11813 if (!updateOomAdjLocked()) {
11814
11815 // Count how many processes are running services.
11816 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011817 for (i=mLruProcesses.size()-1; i>=0; i--) {
11818 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011819
11820 if (app.persistent || app.services.size() != 0
11821 || app.curReceiver != null
11822 || app.persistentActivities > 0) {
11823 // Don't count processes holding services against our
11824 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011825 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826 TAG, "Not trimming app " + app + " with services: "
11827 + app.services);
11828 numServiceProcs++;
11829 }
11830 }
11831
11832 int curMaxProcs = mProcessLimit;
11833 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11834 if (mAlwaysFinishActivities) {
11835 curMaxProcs = 1;
11836 }
11837 curMaxProcs += numServiceProcs;
11838
11839 // Quit as many processes as we can to get down to the desired
11840 // process count. First remove any processes that no longer
11841 // have activites running in them.
11842 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011843 i<mLruProcesses.size()
11844 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011845 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011846 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011847 // Quit an application only if it is not currently
11848 // running any activities.
11849 if (!app.persistent && app.activities.size() == 0
11850 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011851 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011852 TAG, "Exiting empty application process "
11853 + app.processName + " ("
11854 + (app.thread != null ? app.thread.asBinder() : null)
11855 + ")\n");
11856 if (app.pid > 0 && app.pid != MY_PID) {
11857 Process.killProcess(app.pid);
11858 } else {
11859 try {
11860 app.thread.scheduleExit();
11861 } catch (Exception e) {
11862 // Ignore exceptions.
11863 }
11864 }
11865 // todo: For now we assume the application is not buggy
11866 // or evil, and will quit as a result of our request.
11867 // Eventually we need to drive this off of the death
11868 // notification, and kill the process if it takes too long.
11869 cleanUpApplicationRecordLocked(app, false, i);
11870 i--;
11871 }
11872 }
11873
11874 // If we still have too many processes, now from the least
11875 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011876 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011877 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011878 " of " + curMaxProcs + " processes");
11879 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011880 i<mLruProcesses.size()
11881 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011882 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011883 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011884 // Quit the application only if we have a state saved for
11885 // all of its activities.
11886 boolean canQuit = !app.persistent && app.curReceiver == null
11887 && app.services.size() == 0
11888 && app.persistentActivities == 0;
11889 int NUMA = app.activities.size();
11890 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011891 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011892 TAG, "Looking to quit " + app.processName);
11893 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011894 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011895 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011896 TAG, " " + r.intent.getComponent().flattenToShortString()
11897 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11898 canQuit = (r.haveState || !r.stateNotNeeded)
11899 && !r.visible && r.stopped;
11900 }
11901 if (canQuit) {
11902 // Finish all of the activities, and then the app itself.
11903 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011904 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011905 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011906 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011907 }
11908 r.resultTo = null;
11909 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011910 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011911 + app.processName + " ("
11912 + (app.thread != null ? app.thread.asBinder() : null)
11913 + ")\n");
11914 if (app.pid > 0 && app.pid != MY_PID) {
11915 Process.killProcess(app.pid);
11916 } else {
11917 try {
11918 app.thread.scheduleExit();
11919 } catch (Exception e) {
11920 // Ignore exceptions.
11921 }
11922 }
11923 // todo: For now we assume the application is not buggy
11924 // or evil, and will quit as a result of our request.
11925 // Eventually we need to drive this off of the death
11926 // notification, and kill the process if it takes too long.
11927 cleanUpApplicationRecordLocked(app, false, i);
11928 i--;
11929 //dump();
11930 }
11931 }
11932
11933 }
11934
11935 int curMaxActivities = MAX_ACTIVITIES;
11936 if (mAlwaysFinishActivities) {
11937 curMaxActivities = 1;
11938 }
11939
11940 // Finally, if there are too many activities now running, try to
11941 // finish as many as we can to get back down to the limit.
11942 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011943 i<mMainStack.mLRUActivities.size()
11944 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011945 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011946 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011947 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011948
11949 // We can finish this one if we have its icicle saved and
11950 // it is not persistent.
11951 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11952 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011953 final int origSize = mMainStack.mLRUActivities.size();
11954 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011955
11956 // This will remove it from the LRU list, so keep
11957 // our index at the same value. Note that this check to
11958 // see if the size changes is just paranoia -- if
11959 // something unexpected happens, we don't want to end up
11960 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011961 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011962 i--;
11963 }
11964 }
11965 }
11966 }
11967 }
11968
11969 /** This method sends the specified signal to each of the persistent apps */
11970 public void signalPersistentProcesses(int sig) throws RemoteException {
11971 if (sig != Process.SIGNAL_USR1) {
11972 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11973 }
11974
11975 synchronized (this) {
11976 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11977 != PackageManager.PERMISSION_GRANTED) {
11978 throw new SecurityException("Requires permission "
11979 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11980 }
11981
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011982 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11983 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011984 if (r.thread != null && r.persistent) {
11985 Process.sendSignal(r.pid, sig);
11986 }
11987 }
11988 }
11989 }
11990
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011991 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011992 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011993
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011994 try {
11995 synchronized (this) {
11996 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11997 // its own permission.
11998 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11999 != PackageManager.PERMISSION_GRANTED) {
12000 throw new SecurityException("Requires permission "
12001 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012002 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012003
12004 if (start && fd == null) {
12005 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012006 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012007
12008 ProcessRecord proc = null;
12009 try {
12010 int pid = Integer.parseInt(process);
12011 synchronized (mPidsSelfLocked) {
12012 proc = mPidsSelfLocked.get(pid);
12013 }
12014 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012015 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012016
12017 if (proc == null) {
12018 HashMap<String, SparseArray<ProcessRecord>> all
12019 = mProcessNames.getMap();
12020 SparseArray<ProcessRecord> procs = all.get(process);
12021 if (procs != null && procs.size() > 0) {
12022 proc = procs.valueAt(0);
12023 }
12024 }
12025
12026 if (proc == null || proc.thread == null) {
12027 throw new IllegalArgumentException("Unknown process: " + process);
12028 }
12029
12030 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12031 if (isSecure) {
12032 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12033 throw new SecurityException("Process not debuggable: " + proc);
12034 }
12035 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012036
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012037 proc.thread.profilerControl(start, path, fd);
12038 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012039 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012040 }
12041 } catch (RemoteException e) {
12042 throw new IllegalStateException("Process disappeared");
12043 } finally {
12044 if (fd != null) {
12045 try {
12046 fd.close();
12047 } catch (IOException e) {
12048 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012049 }
12050 }
12051 }
12052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012053 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12054 public void monitor() {
12055 synchronized (this) { }
12056 }
12057}