blob: 3142ee4548702a088881d77049a6206700114819 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755
756 Context mContext;
757
758 int mFactoryTest;
759
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700760 boolean mCheckedForSetup;
761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700763 * The time at which we will allow normal application switches again,
764 * after a call to {@link #stopAppSwitches()}.
765 */
766 long mAppSwitchesAllowedTime;
767
768 /**
769 * This is set to true after the first switch after mAppSwitchesAllowedTime
770 * is set; any switches after that will clear the time.
771 */
772 boolean mDidAppSwitch;
773
774 /**
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700775 * Last time (in realtime) at which we checked for wake lock usage.
776 */
777 long mLastWakeLockCheckTime;
778
779 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 * Set while we are wanting to sleep, to prevent any
781 * activities from being started/resumed.
782 */
783 boolean mSleeping = false;
784
785 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700786 * Set if we are shutting down the system, similar to sleeping.
787 */
788 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789
790 /**
791 * Task identifier that activities are currently being started
792 * in. Incremented each time a new task is created.
793 * todo: Replace this with a TokenSpace class that generates non-repeating
794 * integers that won't wrap.
795 */
796 int mCurTask = 1;
797
798 /**
799 * Current sequence id for oom_adj computation traversal.
800 */
801 int mAdjSeq = 0;
802
803 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700804 * Current sequence id for process LRU updating.
805 */
806 int mLruSeq = 0;
807
808 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
810 * is set, indicating the user wants processes started in such a way
811 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
812 * running in each process (thus no pre-initialized process, etc).
813 */
814 boolean mSimpleProcessManagement = false;
815
816 /**
817 * System monitoring: number of processes that died since the last
818 * N procs were started.
819 */
820 int[] mProcDeaths = new int[20];
821
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700822 /**
823 * This is set if we had to do a delayed dexopt of an app before launching
824 * it, to increasing the ANR timeouts in that case.
825 */
826 boolean mDidDexOpt;
827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 String mDebugApp = null;
829 boolean mWaitForDebugger = false;
830 boolean mDebugTransient = false;
831 String mOrigDebugApp = null;
832 boolean mOrigWaitForDebugger = false;
833 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700834 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700836 final RemoteCallbackList<IActivityWatcher> mWatchers
837 = new RemoteCallbackList<IActivityWatcher>();
838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 /**
840 * Callback of last caller to {@link #requestPss}.
841 */
842 Runnable mRequestPssCallback;
843
844 /**
845 * Remaining processes for which we are waiting results from the last
846 * call to {@link #requestPss}.
847 */
848 final ArrayList<ProcessRecord> mRequestPssList
849 = new ArrayList<ProcessRecord>();
850
851 /**
852 * Runtime statistics collection thread. This object's lock is used to
853 * protect all related state.
854 */
855 final Thread mProcessStatsThread;
856
857 /**
858 * Used to collect process stats when showing not responding dialog.
859 * Protected by mProcessStatsThread.
860 */
861 final ProcessStats mProcessStats = new ProcessStats(
862 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700863 final AtomicLong mLastCpuTime = new AtomicLong(0);
864 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 long mLastWriteTime = 0;
867
868 /**
869 * Set to true after the system has finished booting.
870 */
871 boolean mBooted = false;
872
873 int mProcessLimit = 0;
874
875 WindowManagerService mWindowManager;
876
877 static ActivityManagerService mSelf;
878 static ActivityThread mSystemThread;
879
880 private final class AppDeathRecipient implements IBinder.DeathRecipient {
881 final ProcessRecord mApp;
882 final int mPid;
883 final IApplicationThread mAppThread;
884
885 AppDeathRecipient(ProcessRecord app, int pid,
886 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800887 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 TAG, "New death recipient " + this
889 + " for thread " + thread.asBinder());
890 mApp = app;
891 mPid = pid;
892 mAppThread = thread;
893 }
894
895 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800896 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 TAG, "Death received in " + this
898 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 synchronized(ActivityManagerService.this) {
900 appDiedLocked(mApp, mPid, mAppThread);
901 }
902 }
903 }
904
905 static final int SHOW_ERROR_MSG = 1;
906 static final int SHOW_NOT_RESPONDING_MSG = 2;
907 static final int SHOW_FACTORY_ERROR_MSG = 3;
908 static final int UPDATE_CONFIGURATION_MSG = 4;
909 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
910 static final int WAIT_FOR_DEBUGGER_MSG = 6;
911 static final int BROADCAST_INTENT_MSG = 7;
912 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 static final int SERVICE_TIMEOUT_MSG = 12;
914 static final int UPDATE_TIME_ZONE = 13;
915 static final int SHOW_UID_ERROR_MSG = 14;
916 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700918 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700919 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800920 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700921 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
922 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700923 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700924 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925
926 AlertDialog mUidAlert;
927
928 final Handler mHandler = new Handler() {
929 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800930 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 //}
932
933 public void handleMessage(Message msg) {
934 switch (msg.what) {
935 case SHOW_ERROR_MSG: {
936 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 synchronized (ActivityManagerService.this) {
938 ProcessRecord proc = (ProcessRecord)data.get("app");
939 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800940 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 return;
942 }
943 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700944 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800945 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 d.show();
947 proc.crashDialog = d;
948 } else {
949 // The device is asleep, so just pretend that the user
950 // saw a crash dialog and hit "force quit".
951 res.set(0);
952 }
953 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700954
955 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 } break;
957 case SHOW_NOT_RESPONDING_MSG: {
958 synchronized (ActivityManagerService.this) {
959 HashMap data = (HashMap) msg.obj;
960 ProcessRecord proc = (ProcessRecord)data.get("app");
961 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800962 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 return;
964 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800965
966 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
967 null, null, 0, null, null, null,
968 false, false, MY_PID, Process.SYSTEM_UID);
969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700971 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 d.show();
973 proc.anrDialog = d;
974 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700975
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700976 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700978 case SHOW_STRICT_MODE_VIOLATION_MSG: {
979 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
980 synchronized (ActivityManagerService.this) {
981 ProcessRecord proc = (ProcessRecord) data.get("app");
982 if (proc == null) {
983 Slog.e(TAG, "App not found when showing strict mode dialog.");
984 break;
985 }
986 if (proc.crashDialog != null) {
987 Slog.e(TAG, "App already has strict mode dialog: " + proc);
988 return;
989 }
990 AppErrorResult res = (AppErrorResult) data.get("result");
991 if (!mSleeping && !mShuttingDown) {
992 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
993 d.show();
994 proc.crashDialog = d;
995 } else {
996 // The device is asleep, so just pretend that the user
997 // saw a crash dialog and hit "force quit".
998 res.set(0);
999 }
1000 }
1001 ensureBootCompleted();
1002 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 case SHOW_FACTORY_ERROR_MSG: {
1004 Dialog d = new FactoryErrorDialog(
1005 mContext, msg.getData().getCharSequence("msg"));
1006 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001007 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 } break;
1009 case UPDATE_CONFIGURATION_MSG: {
1010 final ContentResolver resolver = mContext.getContentResolver();
1011 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1012 } break;
1013 case GC_BACKGROUND_PROCESSES_MSG: {
1014 synchronized (ActivityManagerService.this) {
1015 performAppGcsIfAppropriateLocked();
1016 }
1017 } break;
1018 case WAIT_FOR_DEBUGGER_MSG: {
1019 synchronized (ActivityManagerService.this) {
1020 ProcessRecord app = (ProcessRecord)msg.obj;
1021 if (msg.arg1 != 0) {
1022 if (!app.waitedForDebugger) {
1023 Dialog d = new AppWaitingForDebuggerDialog(
1024 ActivityManagerService.this,
1025 mContext, app);
1026 app.waitDialog = d;
1027 app.waitedForDebugger = true;
1028 d.show();
1029 }
1030 } else {
1031 if (app.waitDialog != null) {
1032 app.waitDialog.dismiss();
1033 app.waitDialog = null;
1034 }
1035 }
1036 }
1037 } break;
1038 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001039 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 TAG, "Received BROADCAST_INTENT_MSG");
1041 processNextBroadcast(true);
1042 } break;
1043 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001044 if (mDidDexOpt) {
1045 mDidDexOpt = false;
1046 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1047 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1048 return;
1049 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001050 // Only process broadcast timeouts if the system is ready. That way
1051 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1052 // to do heavy lifting for system up
1053 if (mSystemReady) {
1054 broadcastTimeout();
1055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001058 if (mDidDexOpt) {
1059 mDidDexOpt = false;
1060 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1061 nmsg.obj = msg.obj;
1062 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1063 return;
1064 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 serviceTimeout((ProcessRecord)msg.obj);
1066 } break;
1067 case UPDATE_TIME_ZONE: {
1068 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001069 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1070 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 if (r.thread != null) {
1072 try {
1073 r.thread.updateTimeZone();
1074 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001075 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 }
1077 }
1078 }
1079 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001080 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 case SHOW_UID_ERROR_MSG: {
1082 // XXX This is a temporary dialog, no need to localize.
1083 AlertDialog d = new BaseErrorDialog(mContext);
1084 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1085 d.setCancelable(false);
1086 d.setTitle("System UIDs Inconsistent");
1087 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1088 d.setButton("I'm Feeling Lucky",
1089 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1090 mUidAlert = d;
1091 d.show();
1092 } break;
1093 case IM_FEELING_LUCKY_MSG: {
1094 if (mUidAlert != null) {
1095 mUidAlert.dismiss();
1096 mUidAlert = null;
1097 }
1098 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001100 if (mDidDexOpt) {
1101 mDidDexOpt = false;
1102 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1103 nmsg.obj = msg.obj;
1104 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1105 return;
1106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 ProcessRecord app = (ProcessRecord)msg.obj;
1108 synchronized (ActivityManagerService.this) {
1109 processStartTimedOutLocked(app);
1110 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001111 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001112 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1113 synchronized (ActivityManagerService.this) {
1114 doPendingActivityLaunchesLocked(true);
1115 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001116 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001117 case KILL_APPLICATION_MSG: {
1118 synchronized (ActivityManagerService.this) {
1119 int uid = msg.arg1;
1120 boolean restart = (msg.arg2 == 1);
1121 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001122 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001123 }
1124 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001125 case FINALIZE_PENDING_INTENT_MSG: {
1126 ((PendingIntentRecord)msg.obj).completeFinalize();
1127 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001128 case POST_HEAVY_NOTIFICATION_MSG: {
1129 INotificationManager inm = NotificationManager.getService();
1130 if (inm == null) {
1131 return;
1132 }
1133
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001134 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001135 ProcessRecord process = root.app;
1136 if (process == null) {
1137 return;
1138 }
1139
1140 try {
1141 Context context = mContext.createPackageContext(process.info.packageName, 0);
1142 String text = mContext.getString(R.string.heavy_weight_notification,
1143 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1144 Notification notification = new Notification();
1145 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1146 notification.when = 0;
1147 notification.flags = Notification.FLAG_ONGOING_EVENT;
1148 notification.tickerText = text;
1149 notification.defaults = 0; // please be quiet
1150 notification.sound = null;
1151 notification.vibrate = null;
1152 notification.setLatestEventInfo(context, text,
1153 mContext.getText(R.string.heavy_weight_notification_detail),
1154 PendingIntent.getActivity(mContext, 0, root.intent,
1155 PendingIntent.FLAG_CANCEL_CURRENT));
1156
1157 try {
1158 int[] outId = new int[1];
1159 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1160 notification, outId);
1161 } catch (RuntimeException e) {
1162 Slog.w(ActivityManagerService.TAG,
1163 "Error showing notification for heavy-weight app", e);
1164 } catch (RemoteException e) {
1165 }
1166 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001167 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001168 }
1169 } break;
1170 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1171 INotificationManager inm = NotificationManager.getService();
1172 if (inm == null) {
1173 return;
1174 }
1175 try {
1176 inm.cancelNotification("android",
1177 R.string.heavy_weight_notification);
1178 } catch (RuntimeException e) {
1179 Slog.w(ActivityManagerService.TAG,
1180 "Error canceling notification for service", e);
1181 } catch (RemoteException e) {
1182 }
1183 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001184 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1185 synchronized (ActivityManagerService.this) {
1186 checkExcessiveWakeLocksLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001187 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001188 if (mSleeping) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001189 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1190 sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001191 }
1192 }
1193 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 }
1195 }
1196 };
1197
1198 public static void setSystemProcess() {
1199 try {
1200 ActivityManagerService m = mSelf;
1201
1202 ServiceManager.addService("activity", m);
1203 ServiceManager.addService("meminfo", new MemBinder(m));
1204 if (MONITOR_CPU_USAGE) {
1205 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 ServiceManager.addService("permission", new PermissionController(m));
1208
1209 ApplicationInfo info =
1210 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001211 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001212 mSystemThread.installSystemApplicationInfo(info);
1213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 synchronized (mSelf) {
1215 ProcessRecord app = mSelf.newProcessRecordLocked(
1216 mSystemThread.getApplicationThread(), info,
1217 info.processName);
1218 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001219 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001220 app.maxAdj = SYSTEM_ADJ;
1221 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1222 synchronized (mSelf.mPidsSelfLocked) {
1223 mSelf.mPidsSelfLocked.put(app.pid, app);
1224 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001225 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 }
1227 } catch (PackageManager.NameNotFoundException e) {
1228 throw new RuntimeException(
1229 "Unable to find android system package", e);
1230 }
1231 }
1232
1233 public void setWindowManager(WindowManagerService wm) {
1234 mWindowManager = wm;
1235 }
1236
1237 public static final Context main(int factoryTest) {
1238 AThread thr = new AThread();
1239 thr.start();
1240
1241 synchronized (thr) {
1242 while (thr.mService == null) {
1243 try {
1244 thr.wait();
1245 } catch (InterruptedException e) {
1246 }
1247 }
1248 }
1249
1250 ActivityManagerService m = thr.mService;
1251 mSelf = m;
1252 ActivityThread at = ActivityThread.systemMain();
1253 mSystemThread = at;
1254 Context context = at.getSystemContext();
1255 m.mContext = context;
1256 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001257 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258
1259 m.mBatteryStatsService.publish(context);
1260 m.mUsageStatsService.publish(context);
1261
1262 synchronized (thr) {
1263 thr.mReady = true;
1264 thr.notifyAll();
1265 }
1266
1267 m.startRunning(null, null, null, null);
1268
1269 return context;
1270 }
1271
1272 public static ActivityManagerService self() {
1273 return mSelf;
1274 }
1275
1276 static class AThread extends Thread {
1277 ActivityManagerService mService;
1278 boolean mReady = false;
1279
1280 public AThread() {
1281 super("ActivityManager");
1282 }
1283
1284 public void run() {
1285 Looper.prepare();
1286
1287 android.os.Process.setThreadPriority(
1288 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001289 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001290
1291 ActivityManagerService m = new ActivityManagerService();
1292
1293 synchronized (this) {
1294 mService = m;
1295 notifyAll();
1296 }
1297
1298 synchronized (this) {
1299 while (!mReady) {
1300 try {
1301 wait();
1302 } catch (InterruptedException e) {
1303 }
1304 }
1305 }
1306
1307 Looper.loop();
1308 }
1309 }
1310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 static class MemBinder extends Binder {
1312 ActivityManagerService mActivityManagerService;
1313 MemBinder(ActivityManagerService activityManagerService) {
1314 mActivityManagerService = activityManagerService;
1315 }
1316
1317 @Override
1318 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1319 ActivityManagerService service = mActivityManagerService;
1320 ArrayList<ProcessRecord> procs;
1321 synchronized (mActivityManagerService) {
1322 if (args != null && args.length > 0
1323 && args[0].charAt(0) != '-') {
1324 procs = new ArrayList<ProcessRecord>();
1325 int pid = -1;
1326 try {
1327 pid = Integer.parseInt(args[0]);
1328 } catch (NumberFormatException e) {
1329
1330 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001331 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1332 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 if (proc.pid == pid) {
1334 procs.add(proc);
1335 } else if (proc.processName.equals(args[0])) {
1336 procs.add(proc);
1337 }
1338 }
1339 if (procs.size() <= 0) {
1340 pw.println("No process found for: " + args[0]);
1341 return;
1342 }
1343 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001344 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 }
1346 }
1347 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1348 }
1349 }
1350
1351 static class CpuBinder extends Binder {
1352 ActivityManagerService mActivityManagerService;
1353 CpuBinder(ActivityManagerService activityManagerService) {
1354 mActivityManagerService = activityManagerService;
1355 }
1356
1357 @Override
1358 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1359 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001360 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1361 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1362 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
1364 }
1365 }
1366
1367 private ActivityManagerService() {
1368 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1369 if (v != null && Integer.getInteger(v) != 0) {
1370 mSimpleProcessManagement = true;
1371 }
1372 v = System.getenv("ANDROID_DEBUG_APP");
1373 if (v != null) {
1374 mSimpleProcessManagement = true;
1375 }
1376
Joe Onorato8a9b2202010-02-26 18:56:32 -08001377 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 File dataDir = Environment.getDataDirectory();
1380 File systemDir = new File(dataDir, "system");
1381 systemDir.mkdirs();
1382 mBatteryStatsService = new BatteryStatsService(new File(
1383 systemDir, "batterystats.bin").toString());
1384 mBatteryStatsService.getActiveStatistics().readLocked();
1385 mBatteryStatsService.getActiveStatistics().writeLocked();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001386 mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
1387 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001389 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001390 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391
Jack Palevichb90d28c2009-07-22 15:35:24 -07001392 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1393 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1394
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001395 mConfiguration.setToDefaults();
1396 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 mProcessStats.init();
1398
1399 // Add ourself to the Watchdog monitors.
1400 Watchdog.getInstance().addMonitor(this);
1401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 mProcessStatsThread = new Thread("ProcessStats") {
1403 public void run() {
1404 while (true) {
1405 try {
1406 try {
1407 synchronized(this) {
1408 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001409 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001411 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 // + ", write delay=" + nextWriteDelay);
1413 if (nextWriteDelay < nextCpuDelay) {
1414 nextCpuDelay = nextWriteDelay;
1415 }
1416 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001417 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 this.wait(nextCpuDelay);
1419 }
1420 }
1421 } catch (InterruptedException e) {
1422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 updateCpuStatsNow();
1424 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001425 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 }
1427 }
1428 }
1429 };
1430 mProcessStatsThread.start();
1431 }
1432
1433 @Override
1434 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1435 throws RemoteException {
1436 try {
1437 return super.onTransact(code, data, reply, flags);
1438 } catch (RuntimeException e) {
1439 // The activity manager only throws security exceptions, so let's
1440 // log all others.
1441 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001442 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 }
1444 throw e;
1445 }
1446 }
1447
1448 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001449 final long now = SystemClock.uptimeMillis();
1450 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1451 return;
1452 }
1453 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1454 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 mProcessStatsThread.notify();
1456 }
1457 }
1458 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 void updateCpuStatsNow() {
1461 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001462 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 final long now = SystemClock.uptimeMillis();
1464 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001467 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1468 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 haveNewCpuStats = true;
1470 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001471 //Slog.i(TAG, mProcessStats.printCurrentState());
1472 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 // + mProcessStats.getTotalCpuPercent() + "%");
1474
Joe Onorato8a9b2202010-02-26 18:56:32 -08001475 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 if ("true".equals(SystemProperties.get("events.cpu"))) {
1477 int user = mProcessStats.getLastUserTime();
1478 int system = mProcessStats.getLastSystemTime();
1479 int iowait = mProcessStats.getLastIoWaitTime();
1480 int irq = mProcessStats.getLastIrqTime();
1481 int softIrq = mProcessStats.getLastSoftIrqTime();
1482 int idle = mProcessStats.getLastIdleTime();
1483
1484 int total = user + system + iowait + irq + softIrq + idle;
1485 if (total == 0) total = 1;
1486
Doug Zongker2bec3d42009-12-04 12:52:44 -08001487 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 ((user+system+iowait+irq+softIrq) * 100) / total,
1489 (user * 100) / total,
1490 (system * 100) / total,
1491 (iowait * 100) / total,
1492 (irq * 100) / total,
1493 (softIrq * 100) / total);
1494 }
1495 }
1496
Amith Yamasanie43530a2009-08-21 13:11:37 -07001497 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001498 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001499 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 synchronized(mPidsSelfLocked) {
1501 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001502 if (mOnBattery) {
1503 int perc = bstats.startAddingCpuLocked();
1504 int totalUTime = 0;
1505 int totalSTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 final int N = mProcessStats.countWorkingStats();
1507 for (int i=0; i<N; i++) {
1508 ProcessStats.Stats st
1509 = mProcessStats.getWorkingStats(i);
1510 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001511 int otherUTime = (st.rel_utime*perc)/100;
1512 int otherSTime = (st.rel_stime*perc)/100;
1513 totalUTime += otherUTime;
1514 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 if (pr != null) {
1516 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001517 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1518 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001519 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001520 } else {
1521 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001522 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001523 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001524 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1525 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001526 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 }
1529 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001530 bstats.finishAddingCpuLocked(perc, totalUTime,
1531 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 }
1533 }
1534 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1537 mLastWriteTime = now;
1538 mBatteryStatsService.getActiveStatistics().writeLocked();
1539 }
1540 }
1541 }
1542 }
1543
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001544 @Override
1545 public void batteryNeedsCpuUpdate() {
1546 updateCpuStatsNow();
1547 }
1548
1549 @Override
1550 public void batteryPowerChanged(boolean onBattery) {
1551 // When plugging in, update the CPU stats first before changing
1552 // the plug state.
1553 updateCpuStatsNow();
1554 synchronized (this) {
1555 synchronized(mPidsSelfLocked) {
1556 mOnBattery = onBattery;
1557 }
1558 }
1559 }
1560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 /**
1562 * Initialize the application bind args. These are passed to each
1563 * process when the bindApplication() IPC is sent to the process. They're
1564 * lazily setup to make sure the services are running when they're asked for.
1565 */
1566 private HashMap<String, IBinder> getCommonServicesLocked() {
1567 if (mAppBindArgs == null) {
1568 mAppBindArgs = new HashMap<String, IBinder>();
1569
1570 // Setup the application init args
1571 mAppBindArgs.put("package", ServiceManager.getService("package"));
1572 mAppBindArgs.put("window", ServiceManager.getService("window"));
1573 mAppBindArgs.put(Context.ALARM_SERVICE,
1574 ServiceManager.getService(Context.ALARM_SERVICE));
1575 }
1576 return mAppBindArgs;
1577 }
1578
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001579 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 if (mFocusedActivity != r) {
1581 mFocusedActivity = r;
1582 mWindowManager.setFocusedApp(r, true);
1583 }
1584 }
1585
Dianne Hackborn906497c2010-05-10 15:57:38 -07001586 private final void updateLruProcessInternalLocked(ProcessRecord app,
1587 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001589 int lrui = mLruProcesses.indexOf(app);
1590 if (lrui >= 0) mLruProcesses.remove(lrui);
1591
1592 int i = mLruProcesses.size()-1;
1593 int skipTop = 0;
1594
Dianne Hackborn906497c2010-05-10 15:57:38 -07001595 app.lruSeq = mLruSeq;
1596
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001597 // compute the new weight for this process.
1598 if (updateActivityTime) {
1599 app.lastActivityTime = SystemClock.uptimeMillis();
1600 }
1601 if (app.activities.size() > 0) {
1602 // If this process has activities, we more strongly want to keep
1603 // it around.
1604 app.lruWeight = app.lastActivityTime;
1605 } else if (app.pubProviders.size() > 0) {
1606 // If this process contains content providers, we want to keep
1607 // it a little more strongly.
1608 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1609 // Also don't let it kick out the first few "real" hidden processes.
1610 skipTop = MIN_HIDDEN_APPS;
1611 } else {
1612 // If this process doesn't have activities, we less strongly
1613 // want to keep it around, and generally want to avoid getting
1614 // in front of any very recently used activities.
1615 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1616 // Also don't let it kick out the first few "real" hidden processes.
1617 skipTop = MIN_HIDDEN_APPS;
1618 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001619
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001620 while (i >= 0) {
1621 ProcessRecord p = mLruProcesses.get(i);
1622 // If this app shouldn't be in front of the first N background
1623 // apps, then skip over that many that are currently hidden.
1624 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1625 skipTop--;
1626 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001627 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001628 mLruProcesses.add(i+1, app);
1629 break;
1630 }
1631 i--;
1632 }
1633 if (i < 0) {
1634 mLruProcesses.add(0, app);
1635 }
1636
Dianne Hackborn906497c2010-05-10 15:57:38 -07001637 // If the app is currently using a content provider or service,
1638 // bump those processes as well.
1639 if (app.connections.size() > 0) {
1640 for (ConnectionRecord cr : app.connections) {
1641 if (cr.binding != null && cr.binding.service != null
1642 && cr.binding.service.app != null
1643 && cr.binding.service.app.lruSeq != mLruSeq) {
1644 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1645 updateActivityTime, i+1);
1646 }
1647 }
1648 }
1649 if (app.conProviders.size() > 0) {
1650 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1651 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1652 updateLruProcessInternalLocked(cpr.app, oomAdj,
1653 updateActivityTime, i+1);
1654 }
1655 }
1656 }
1657
Joe Onorato8a9b2202010-02-26 18:56:32 -08001658 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 if (oomAdj) {
1660 updateOomAdjLocked();
1661 }
1662 }
1663
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001664 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001665 boolean oomAdj, boolean updateActivityTime) {
1666 mLruSeq++;
1667 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1668 }
1669
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001670 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 String processName, int uid) {
1672 if (uid == Process.SYSTEM_UID) {
1673 // The system gets to run in any process. If there are multiple
1674 // processes with the same uid, just pick the first (this
1675 // should never happen).
1676 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1677 processName);
1678 return procs != null ? procs.valueAt(0) : null;
1679 }
1680 ProcessRecord proc = mProcessNames.get(processName, uid);
1681 return proc;
1682 }
1683
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001684 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001685 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001686 try {
1687 if (pm.performDexOpt(packageName)) {
1688 mDidDexOpt = true;
1689 }
1690 } catch (RemoteException e) {
1691 }
1692 }
1693
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001694 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 int transit = mWindowManager.getPendingAppTransition();
1696 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1697 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1698 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1699 }
1700
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001701 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001703 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1705 // We don't have to do anything more if:
1706 // (1) There is an existing application record; and
1707 // (2) The caller doesn't think it is dead, OR there is no thread
1708 // object attached to it so we know it couldn't have crashed; and
1709 // (3) There is a pid assigned to it, so it is either starting or
1710 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001711 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 + " app=" + app + " knownToBeDead=" + knownToBeDead
1713 + " thread=" + (app != null ? app.thread : null)
1714 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001715 if (app != null && app.pid > 0) {
1716 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001717 // We already have the app running, or are waiting for it to
1718 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001719 return app;
1720 } else {
1721 // An application record is attached to a previous process,
1722 // clean it up now.
1723 handleAppDiedLocked(app, true);
1724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 String hostingNameStr = hostingName != null
1728 ? hostingName.flattenToShortString() : null;
1729
1730 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1731 // If we are in the background, then check to see if this process
1732 // is bad. If so, we will just silently fail.
1733 if (mBadProcesses.get(info.processName, info.uid) != null) {
1734 return null;
1735 }
1736 } else {
1737 // When the user is explicitly starting a process, then clear its
1738 // crash count so that we won't make it bad until they see at
1739 // least one crash dialog again, and make the process good again
1740 // if it had been bad.
1741 mProcessCrashTimes.remove(info.processName, info.uid);
1742 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001743 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 info.processName);
1745 mBadProcesses.remove(info.processName, info.uid);
1746 if (app != null) {
1747 app.bad = false;
1748 }
1749 }
1750 }
1751
1752 if (app == null) {
1753 app = newProcessRecordLocked(null, info, processName);
1754 mProcessNames.put(processName, info.uid, app);
1755 } else {
1756 // If this is a new package in the process, add the package to the list
1757 app.addPackage(info.packageName);
1758 }
1759
1760 // If the system is not ready yet, then hold off on starting this
1761 // process until it is.
1762 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001763 && !isAllowedWhileBooting(info)
1764 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 if (!mProcessesOnHold.contains(app)) {
1766 mProcessesOnHold.add(app);
1767 }
1768 return app;
1769 }
1770
1771 startProcessLocked(app, hostingType, hostingNameStr);
1772 return (app.pid != 0) ? app : null;
1773 }
1774
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001775 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1776 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1777 }
1778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 private final void startProcessLocked(ProcessRecord app,
1780 String hostingType, String hostingNameStr) {
1781 if (app.pid > 0 && app.pid != MY_PID) {
1782 synchronized (mPidsSelfLocked) {
1783 mPidsSelfLocked.remove(app.pid);
1784 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1785 }
1786 app.pid = 0;
1787 }
1788
1789 mProcessesOnHold.remove(app);
1790
1791 updateCpuStats();
1792
1793 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1794 mProcDeaths[0] = 0;
1795
1796 try {
1797 int uid = app.info.uid;
1798 int[] gids = null;
1799 try {
1800 gids = mContext.getPackageManager().getPackageGids(
1801 app.info.packageName);
1802 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001803 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 }
1805 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1806 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1807 && mTopComponent != null
1808 && app.processName.equals(mTopComponent.getPackageName())) {
1809 uid = 0;
1810 }
1811 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1812 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1813 uid = 0;
1814 }
1815 }
1816 int debugFlags = 0;
1817 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1818 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1819 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001820 // Run the app in safe mode if its manifest requests so or the
1821 // system is booted in safe mode.
1822 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1823 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001824 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1827 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1828 }
1829 if ("1".equals(SystemProperties.get("debug.assert"))) {
1830 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1831 }
1832 int pid = Process.start("android.app.ActivityThread",
1833 mSimpleProcessManagement ? app.processName : null, uid, uid,
1834 gids, debugFlags, null);
1835 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1836 synchronized (bs) {
1837 if (bs.isOnBattery()) {
1838 app.batteryStats.incStartsLocked();
1839 }
1840 }
1841
Doug Zongker2bec3d42009-12-04 12:52:44 -08001842 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 app.processName, hostingType,
1844 hostingNameStr != null ? hostingNameStr : "");
1845
1846 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001847 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 }
1849
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001850 StringBuilder buf = mStringBuilder;
1851 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 buf.append("Start proc ");
1853 buf.append(app.processName);
1854 buf.append(" for ");
1855 buf.append(hostingType);
1856 if (hostingNameStr != null) {
1857 buf.append(" ");
1858 buf.append(hostingNameStr);
1859 }
1860 buf.append(": pid=");
1861 buf.append(pid);
1862 buf.append(" uid=");
1863 buf.append(uid);
1864 buf.append(" gids={");
1865 if (gids != null) {
1866 for (int gi=0; gi<gids.length; gi++) {
1867 if (gi != 0) buf.append(", ");
1868 buf.append(gids[gi]);
1869
1870 }
1871 }
1872 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001873 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 if (pid == 0 || pid == MY_PID) {
1875 // Processes are being emulated with threads.
1876 app.pid = MY_PID;
1877 app.removed = false;
1878 mStartingProcesses.add(app);
1879 } else if (pid > 0) {
1880 app.pid = pid;
1881 app.removed = false;
1882 synchronized (mPidsSelfLocked) {
1883 this.mPidsSelfLocked.put(pid, app);
1884 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1885 msg.obj = app;
1886 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1887 }
1888 } else {
1889 app.pid = 0;
1890 RuntimeException e = new RuntimeException(
1891 "Failure starting process " + app.processName
1892 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001893 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 }
1895 } catch (RuntimeException e) {
1896 // XXX do better error recovery.
1897 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001898 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 }
1900 }
1901
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001902 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001903 if (resumed) {
1904 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1905 } else {
1906 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1907 }
1908 }
1909
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001910 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001911 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1912 && mTopAction == null) {
1913 // We are running in factory test mode, but unable to find
1914 // the factory test app, so just sit around displaying the
1915 // error message and don't try to start anything.
1916 return false;
1917 }
1918 Intent intent = new Intent(
1919 mTopAction,
1920 mTopData != null ? Uri.parse(mTopData) : null);
1921 intent.setComponent(mTopComponent);
1922 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1923 intent.addCategory(Intent.CATEGORY_HOME);
1924 }
1925 ActivityInfo aInfo =
1926 intent.resolveActivityInfo(mContext.getPackageManager(),
1927 STOCK_PM_FLAGS);
1928 if (aInfo != null) {
1929 intent.setComponent(new ComponentName(
1930 aInfo.applicationInfo.packageName, aInfo.name));
1931 // Don't do this if the home app is currently being
1932 // instrumented.
1933 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1934 aInfo.applicationInfo.uid);
1935 if (app == null || app.instrumentationClass == null) {
1936 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001937 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001938 null, null, 0, 0, 0, false, false);
1939 }
1940 }
1941
1942
1943 return true;
1944 }
1945
1946 /**
1947 * Starts the "new version setup screen" if appropriate.
1948 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001949 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001950 // Only do this once per boot.
1951 if (mCheckedForSetup) {
1952 return;
1953 }
1954
1955 // We will show this screen if the current one is a different
1956 // version than the last one shown, and we are not running in
1957 // low-level factory test mode.
1958 final ContentResolver resolver = mContext.getContentResolver();
1959 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1960 Settings.Secure.getInt(resolver,
1961 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1962 mCheckedForSetup = true;
1963
1964 // See if we should be showing the platform update setup UI.
1965 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1966 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1967 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1968
1969 // We don't allow third party apps to replace this.
1970 ResolveInfo ri = null;
1971 for (int i=0; ris != null && i<ris.size(); i++) {
1972 if ((ris.get(i).activityInfo.applicationInfo.flags
1973 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1974 ri = ris.get(i);
1975 break;
1976 }
1977 }
1978
1979 if (ri != null) {
1980 String vers = ri.activityInfo.metaData != null
1981 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1982 : null;
1983 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1984 vers = ri.activityInfo.applicationInfo.metaData.getString(
1985 Intent.METADATA_SETUP_VERSION);
1986 }
1987 String lastVers = Settings.Secure.getString(
1988 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1989 if (vers != null && !vers.equals(lastVers)) {
1990 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1991 intent.setComponent(new ComponentName(
1992 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001993 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001994 null, null, 0, 0, 0, false, false);
1995 }
1996 }
1997 }
1998 }
1999
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002000 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002001 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002002
2003 final int identHash = System.identityHashCode(r);
2004 updateUsageStats(r, true);
2005
2006 int i = mWatchers.beginBroadcast();
2007 while (i > 0) {
2008 i--;
2009 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2010 if (w != null) {
2011 try {
2012 w.activityResuming(identHash);
2013 } catch (RemoteException e) {
2014 }
2015 }
2016 }
2017 mWatchers.finishBroadcast();
2018 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002020 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002021 final int N = mPendingActivityLaunches.size();
2022 if (N <= 0) {
2023 return;
2024 }
2025 for (int i=0; i<N; i++) {
2026 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002027 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002028 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2029 doResume && i == (N-1));
2030 }
2031 mPendingActivityLaunches.clear();
2032 }
2033
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002034 public final int startActivity(IApplicationThread caller,
2035 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2036 int grantedMode, IBinder resultTo,
2037 String resultWho, int requestCode, boolean onlyIfNeeded,
2038 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002039 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002040 grantedUriPermissions, grantedMode, resultTo, resultWho,
2041 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002042 }
2043
2044 public final WaitResult startActivityAndWait(IApplicationThread caller,
2045 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2046 int grantedMode, IBinder resultTo,
2047 String resultWho, int requestCode, boolean onlyIfNeeded,
2048 boolean debug) {
2049 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002050 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002051 grantedUriPermissions, grantedMode, resultTo, resultWho,
2052 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002053 return res;
2054 }
2055
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002056 public final int startActivityWithConfig(IApplicationThread caller,
2057 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2058 int grantedMode, IBinder resultTo,
2059 String resultWho, int requestCode, boolean onlyIfNeeded,
2060 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002061 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002062 grantedUriPermissions, grantedMode, resultTo, resultWho,
2063 requestCode, onlyIfNeeded, debug, null, config);
2064 }
2065
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002066 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002067 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002068 IBinder resultTo, String resultWho, int requestCode,
2069 int flagsMask, int flagsValues) {
2070 // Refuse possible leaked file descriptors
2071 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2072 throw new IllegalArgumentException("File descriptors passed in Intent");
2073 }
2074
2075 IIntentSender sender = intent.getTarget();
2076 if (!(sender instanceof PendingIntentRecord)) {
2077 throw new IllegalArgumentException("Bad PendingIntent object");
2078 }
2079
2080 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002081
2082 synchronized (this) {
2083 // If this is coming from the currently resumed activity, it is
2084 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002085 if (mMainStack.mResumedActivity != null
2086 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002087 Binder.getCallingUid()) {
2088 mAppSwitchesAllowedTime = 0;
2089 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002090 }
2091
2092 return pir.sendInner(0, fillInIntent, resolvedType,
2093 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2094 }
2095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 public boolean startNextMatchingActivity(IBinder callingActivity,
2097 Intent intent) {
2098 // Refuse possible leaked file descriptors
2099 if (intent != null && intent.hasFileDescriptors() == true) {
2100 throw new IllegalArgumentException("File descriptors passed in Intent");
2101 }
2102
2103 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002104 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 if (index < 0) {
2106 return false;
2107 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002108 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 if (r.app == null || r.app.thread == null) {
2110 // The caller is not running... d'oh!
2111 return false;
2112 }
2113 intent = new Intent(intent);
2114 // The caller is not allowed to change the data.
2115 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2116 // And we are resetting to find the next component...
2117 intent.setComponent(null);
2118
2119 ActivityInfo aInfo = null;
2120 try {
2121 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002122 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002124 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125
2126 // Look for the original activity in the list...
2127 final int N = resolves != null ? resolves.size() : 0;
2128 for (int i=0; i<N; i++) {
2129 ResolveInfo rInfo = resolves.get(i);
2130 if (rInfo.activityInfo.packageName.equals(r.packageName)
2131 && rInfo.activityInfo.name.equals(r.info.name)) {
2132 // We found the current one... the next matching is
2133 // after it.
2134 i++;
2135 if (i<N) {
2136 aInfo = resolves.get(i).activityInfo;
2137 }
2138 break;
2139 }
2140 }
2141 } catch (RemoteException e) {
2142 }
2143
2144 if (aInfo == null) {
2145 // Nobody who is next!
2146 return false;
2147 }
2148
2149 intent.setComponent(new ComponentName(
2150 aInfo.applicationInfo.packageName, aInfo.name));
2151 intent.setFlags(intent.getFlags()&~(
2152 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2153 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2154 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2155 Intent.FLAG_ACTIVITY_NEW_TASK));
2156
2157 // Okay now we need to start the new activity, replacing the
2158 // currently running activity. This is a little tricky because
2159 // we want to start the new one as if the current one is finished,
2160 // but not finish the current one first so that there is no flicker.
2161 // And thus...
2162 final boolean wasFinishing = r.finishing;
2163 r.finishing = true;
2164
2165 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002166 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167 final String resultWho = r.resultWho;
2168 final int requestCode = r.requestCode;
2169 r.resultTo = null;
2170 if (resultTo != null) {
2171 resultTo.removeResultsLocked(r, resultWho, requestCode);
2172 }
2173
2174 final long origId = Binder.clearCallingIdentity();
2175 // XXX we are not dealing with propagating grantedUriPermissions...
2176 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002177 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002179 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 Binder.restoreCallingIdentity(origId);
2181
2182 r.finishing = wasFinishing;
2183 if (res != START_SUCCESS) {
2184 return false;
2185 }
2186 return true;
2187 }
2188 }
2189
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002190 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002191 Intent intent, String resolvedType, IBinder resultTo,
2192 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002193
2194 // This is so super not safe, that only the system (or okay root)
2195 // can do it.
2196 final int callingUid = Binder.getCallingUid();
2197 if (callingUid != 0 && callingUid != Process.myUid()) {
2198 throw new SecurityException(
2199 "startActivityInPackage only available to the system");
2200 }
2201
The Android Open Source Project4df24232009-03-05 14:34:35 -08002202 final boolean componentSpecified = intent.getComponent() != null;
2203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002204 // Don't modify the client's object!
2205 intent = new Intent(intent);
2206
2207 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208 ActivityInfo aInfo;
2209 try {
2210 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002211 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002213 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 aInfo = rInfo != null ? rInfo.activityInfo : null;
2215 } catch (RemoteException e) {
2216 aInfo = null;
2217 }
2218
2219 if (aInfo != null) {
2220 // Store the found target back into the intent, because now that
2221 // we have it we never want to do this again. For example, if the
2222 // user navigates back to this point in the history, we should
2223 // always restart the exact same activity.
2224 intent.setComponent(new ComponentName(
2225 aInfo.applicationInfo.packageName, aInfo.name));
2226 }
2227
2228 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002229 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002231 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 }
2233 }
2234
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002235 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 // Remove any existing entries that are the same kind of task.
2237 int N = mRecentTasks.size();
2238 for (int i=0; i<N; i++) {
2239 TaskRecord tr = mRecentTasks.get(i);
2240 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2241 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2242 mRecentTasks.remove(i);
2243 i--;
2244 N--;
2245 if (task.intent == null) {
2246 // If the new recent task we are adding is not fully
2247 // specified, then replace it with the existing recent task.
2248 task = tr;
2249 }
2250 }
2251 }
2252 if (N >= MAX_RECENT_TASKS) {
2253 mRecentTasks.remove(N-1);
2254 }
2255 mRecentTasks.add(0, task);
2256 }
2257
2258 public void setRequestedOrientation(IBinder token,
2259 int requestedOrientation) {
2260 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002261 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 if (index < 0) {
2263 return;
2264 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002265 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 final long origId = Binder.clearCallingIdentity();
2267 mWindowManager.setAppOrientation(r, requestedOrientation);
2268 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002269 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 r.mayFreezeScreenLocked(r.app) ? r : null);
2271 if (config != null) {
2272 r.frozenBeforeDestroy = true;
2273 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002274 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 }
2276 }
2277 Binder.restoreCallingIdentity(origId);
2278 }
2279 }
2280
2281 public int getRequestedOrientation(IBinder token) {
2282 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002283 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 if (index < 0) {
2285 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2286 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002287 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002288 return mWindowManager.getAppOrientation(r);
2289 }
2290 }
2291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292 /**
2293 * This is the internal entry point for handling Activity.finish().
2294 *
2295 * @param token The Binder token referencing the Activity we want to finish.
2296 * @param resultCode Result code, if any, from this Activity.
2297 * @param resultData Result data (Intent), if any, from this Activity.
2298 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002299 * @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 -08002300 */
2301 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2302 // Refuse possible leaked file descriptors
2303 if (resultData != null && resultData.hasFileDescriptors() == true) {
2304 throw new IllegalArgumentException("File descriptors passed in Intent");
2305 }
2306
2307 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002308 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002310 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 if (next != null) {
2312 // ask watcher if this is allowed
2313 boolean resumeOK = true;
2314 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002315 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002316 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002317 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 }
2319
2320 if (!resumeOK) {
2321 return false;
2322 }
2323 }
2324 }
2325 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002326 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002327 resultData, "app-request");
2328 Binder.restoreCallingIdentity(origId);
2329 return res;
2330 }
2331 }
2332
Dianne Hackborn860755f2010-06-03 18:47:52 -07002333 public final void finishHeavyWeightApp() {
2334 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2335 != PackageManager.PERMISSION_GRANTED) {
2336 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2337 + Binder.getCallingPid()
2338 + ", uid=" + Binder.getCallingUid()
2339 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2340 Slog.w(TAG, msg);
2341 throw new SecurityException(msg);
2342 }
2343
2344 synchronized(this) {
2345 if (mHeavyWeightProcess == null) {
2346 return;
2347 }
2348
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002349 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002350 mHeavyWeightProcess.activities);
2351 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002352 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002353 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002354 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002355 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002356 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002357 null, "finish-heavy");
2358 }
2359 }
2360 }
2361
2362 mHeavyWeightProcess = null;
2363 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2364 }
2365 }
2366
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002367 public void crashApplication(int uid, int initialPid, String packageName,
2368 String message) {
2369 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2370 != PackageManager.PERMISSION_GRANTED) {
2371 String msg = "Permission Denial: crashApplication() from pid="
2372 + Binder.getCallingPid()
2373 + ", uid=" + Binder.getCallingUid()
2374 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2375 Slog.w(TAG, msg);
2376 throw new SecurityException(msg);
2377 }
2378
2379 synchronized(this) {
2380 ProcessRecord proc = null;
2381
2382 // Figure out which process to kill. We don't trust that initialPid
2383 // still has any relation to current pids, so must scan through the
2384 // list.
2385 synchronized (mPidsSelfLocked) {
2386 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2387 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2388 if (p.info.uid != uid) {
2389 continue;
2390 }
2391 if (p.pid == initialPid) {
2392 proc = p;
2393 break;
2394 }
2395 for (String str : p.pkgList) {
2396 if (str.equals(packageName)) {
2397 proc = p;
2398 }
2399 }
2400 }
2401 }
2402
2403 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002404 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002405 + " initialPid=" + initialPid
2406 + " packageName=" + packageName);
2407 return;
2408 }
2409
2410 if (proc.thread != null) {
2411 long ident = Binder.clearCallingIdentity();
2412 try {
2413 proc.thread.scheduleCrash(message);
2414 } catch (RemoteException e) {
2415 }
2416 Binder.restoreCallingIdentity(ident);
2417 }
2418 }
2419 }
2420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002421 public final void finishSubActivity(IBinder token, String resultWho,
2422 int requestCode) {
2423 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002424 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002425 if (index < 0) {
2426 return;
2427 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002428 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429
2430 final long origId = Binder.clearCallingIdentity();
2431
2432 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002433 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2434 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002435 if (r.resultTo == self && r.requestCode == requestCode) {
2436 if ((r.resultWho == null && resultWho == null) ||
2437 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002438 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002439 Activity.RESULT_CANCELED, null, "request-sub");
2440 }
2441 }
2442 }
2443
2444 Binder.restoreCallingIdentity(origId);
2445 }
2446 }
2447
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002448 public boolean willActivityBeVisible(IBinder token) {
2449 synchronized(this) {
2450 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002451 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2452 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002453 if (r == token) {
2454 return true;
2455 }
2456 if (r.fullscreen && !r.finishing) {
2457 return false;
2458 }
2459 }
2460 return true;
2461 }
2462 }
2463
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002464 public void overridePendingTransition(IBinder token, String packageName,
2465 int enterAnim, int exitAnim) {
2466 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002467 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002468 if (index < 0) {
2469 return;
2470 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002471 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002472
2473 final long origId = Binder.clearCallingIdentity();
2474
2475 if (self.state == ActivityState.RESUMED
2476 || self.state == ActivityState.PAUSING) {
2477 mWindowManager.overridePendingAppTransition(packageName,
2478 enterAnim, exitAnim);
2479 }
2480
2481 Binder.restoreCallingIdentity(origId);
2482 }
2483 }
2484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002485 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 * Main function for removing an existing process from the activity manager
2487 * as a result of that process going away. Clears out all connections
2488 * to the process.
2489 */
2490 private final void handleAppDiedLocked(ProcessRecord app,
2491 boolean restarting) {
2492 cleanUpApplicationRecordLocked(app, restarting, -1);
2493 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002494 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 }
2496
2497 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002498 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2499 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2500 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002502 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2503 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 }
2505
2506 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002507 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002508
2509 boolean atTop = true;
2510 boolean hasVisibleActivities = false;
2511
2512 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002513 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002514 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 TAG, "Removing app " + app + " from history with " + i + " entries");
2516 while (i > 0) {
2517 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002519 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2521 if (r.app == app) {
2522 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002523 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 TAG, "Removing this entry! frozen=" + r.haveState
2525 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002526 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527
2528 r.inHistory = false;
2529 mWindowManager.removeAppToken(r);
2530 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002531 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002533 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002534
2535 } else {
2536 // We have the current state for this activity, so
2537 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002538 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002539 TAG, "Keeping entry, setting app to null");
2540 if (r.visible) {
2541 hasVisibleActivities = true;
2542 }
2543 r.app = null;
2544 r.nowVisible = false;
2545 if (!r.haveState) {
2546 r.icicle = null;
2547 }
2548 }
2549
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002550 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 r.state = ActivityState.STOPPED;
2552 }
2553 atTop = false;
2554 }
2555
2556 app.activities.clear();
2557
2558 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002559 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 + " running instrumentation " + app.instrumentationClass);
2561 Bundle info = new Bundle();
2562 info.putString("shortMsg", "Process crashed.");
2563 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2564 }
2565
2566 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002567 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 // If there was nothing to resume, and we are not already
2569 // restarting this process, but there is a visible activity that
2570 // is hosted by the process... then make sure all visible
2571 // activities are running, taking care of restarting this
2572 // process.
2573 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002574 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 }
2576 }
2577 }
2578 }
2579
2580 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2581 IBinder threadBinder = thread.asBinder();
2582
2583 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002584 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2585 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2587 return i;
2588 }
2589 }
2590 return -1;
2591 }
2592
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002593 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 IApplicationThread thread) {
2595 if (thread == null) {
2596 return null;
2597 }
2598
2599 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002600 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601 }
2602
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002603 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 IApplicationThread thread) {
2605
2606 mProcDeaths[0]++;
2607
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002608 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2609 synchronized (stats) {
2610 stats.noteProcessDiedLocked(app.info.uid, pid);
2611 }
2612
Magnus Edlund7bb25812010-02-24 15:45:06 +01002613 // Clean up already done if the process has been re-started.
2614 if (app.pid == pid && app.thread != null &&
2615 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002616 if (!app.killedBackground) {
2617 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2618 + ") has died.");
2619 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002620 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002621 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 TAG, "Dying app: " + app + ", pid: " + pid
2623 + ", thread: " + thread.asBinder());
2624 boolean doLowMem = app.instrumentationClass == null;
2625 handleAppDiedLocked(app, false);
2626
2627 if (doLowMem) {
2628 // If there are no longer any background processes running,
2629 // and the app that died was not running instrumentation,
2630 // then tell everyone we are now low on memory.
2631 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002632 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2633 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2635 haveBg = true;
2636 break;
2637 }
2638 }
2639
2640 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002641 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002642 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002643 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002644 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2645 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002646 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002647 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2648 // The low memory report is overriding any current
2649 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002650 // heavy/important/visible/foreground processes first.
2651 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002652 rec.lastRequestedGc = 0;
2653 } else {
2654 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002656 rec.reportLowMemory = true;
2657 rec.lastLowMemory = now;
2658 mProcessesToGc.remove(rec);
2659 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002660 }
2661 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002662 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002663 }
2664 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002665 } else if (app.pid != pid) {
2666 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002667 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002668 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002669 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002670 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002671 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 + thread.asBinder());
2673 }
2674 }
2675
Dan Egnor42471dd2010-01-07 17:25:22 -08002676 /**
2677 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002678 * @param clearTraces causes the dump file to be erased prior to the new
2679 * traces being written, if true; when false, the new traces will be
2680 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002681 * @param firstPids of dalvik VM processes to dump stack traces for first
2682 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002683 * @return file containing stack traces, or null if no dump file is configured
2684 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002685 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2686 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002687 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2688 if (tracesPath == null || tracesPath.length() == 0) {
2689 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002691
2692 File tracesFile = new File(tracesPath);
2693 try {
2694 File tracesDir = tracesFile.getParentFile();
2695 if (!tracesDir.exists()) tracesFile.mkdirs();
2696 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2697
Christopher Tate6ee412d2010-05-28 12:01:56 -07002698 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002699 tracesFile.createNewFile();
2700 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2701 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002702 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002703 return null;
2704 }
2705
2706 // Use a FileObserver to detect when traces finish writing.
2707 // The order of traces is considered important to maintain for legibility.
2708 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2709 public synchronized void onEvent(int event, String path) { notify(); }
2710 };
2711
2712 try {
2713 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002714
2715 // First collect all of the stacks of the most important pids.
2716 try {
2717 int num = firstPids.size();
2718 for (int i = 0; i < num; i++) {
2719 synchronized (observer) {
2720 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2721 observer.wait(200); // Wait for write-close, give up after 200msec
2722 }
2723 }
2724 } catch (InterruptedException e) {
2725 Log.wtf(TAG, e);
2726 }
2727
2728 // Next measure CPU usage.
2729 if (processStats != null) {
2730 processStats.init();
2731 System.gc();
2732 processStats.update();
2733 try {
2734 synchronized (processStats) {
2735 processStats.wait(500); // measure over 1/2 second.
2736 }
2737 } catch (InterruptedException e) {
2738 }
2739 processStats.update();
2740
2741 // We'll take the stack crawls of just the top apps using CPU.
2742 final int N = processStats.countWorkingStats();
2743 int numProcs = 0;
2744 for (int i=0; i<N && numProcs<5; i++) {
2745 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2746 if (lastPids.indexOfKey(stats.pid) >= 0) {
2747 numProcs++;
2748 try {
2749 synchronized (observer) {
2750 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2751 observer.wait(200); // Wait for write-close, give up after 200msec
2752 }
2753 } catch (InterruptedException e) {
2754 Log.wtf(TAG, e);
2755 }
2756
2757 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002758 }
2759 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002760
2761 return tracesFile;
2762
Dan Egnor42471dd2010-01-07 17:25:22 -08002763 } finally {
2764 observer.stopWatching();
2765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002766 }
2767
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002768 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2769 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002770 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2771 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2772
2773 long anrTime = SystemClock.uptimeMillis();
2774 if (MONITOR_CPU_USAGE) {
2775 updateCpuStatsNow();
2776 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002777
2778 synchronized (this) {
2779 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2780 if (mShuttingDown) {
2781 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2782 return;
2783 } else if (app.notResponding) {
2784 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2785 return;
2786 } else if (app.crashing) {
2787 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2788 return;
2789 }
2790
2791 // In case we come through here for the same app before completing
2792 // this one, mark as anring now so we will bail out.
2793 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002794
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002795 // Log the ANR to the event log.
2796 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2797 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002798
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002799 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002800 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002801
2802 int parentPid = app.pid;
2803 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002804 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002805
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002806 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002807
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002808 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2809 ProcessRecord r = mLruProcesses.get(i);
2810 if (r != null && r.thread != null) {
2811 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002812 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2813 if (r.persistent) {
2814 firstPids.add(pid);
2815 } else {
2816 lastPids.put(pid, Boolean.TRUE);
2817 }
2818 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 }
2821 }
2822
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002823 final ProcessStats processStats = new ProcessStats(true);
2824
2825 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002826
2827 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002828 StringBuilder info = mStringBuilder;
2829 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002830 info.append("ANR in ").append(app.processName);
2831 if (activity != null && activity.shortComponentName != null) {
2832 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002833 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002834 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002836 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002838 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002839 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841
Dan Egnor42471dd2010-01-07 17:25:22 -08002842 String cpuInfo = null;
2843 if (MONITOR_CPU_USAGE) {
2844 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002845 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002846 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002847 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002848 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002849 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002850 }
2851
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002852 info.append(processStats.printCurrentState(anrTime));
2853
Joe Onorato8a9b2202010-02-26 18:56:32 -08002854 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002855 if (tracesFile == null) {
2856 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2857 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2858 }
2859
2860 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2861
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002862 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002864 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2865 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002867 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2868 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 }
2870 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002871 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 }
2873 }
2874
Dan Egnor42471dd2010-01-07 17:25:22 -08002875 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2876 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2877 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002878
2879 synchronized (this) {
2880 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2881 Process.killProcess(app.pid);
2882 return;
2883 }
2884
2885 // Set the app's notResponding state, and look up the errorReportReceiver
2886 makeAppNotRespondingLocked(app,
2887 activity != null ? activity.shortComponentName : null,
2888 annotation != null ? "ANR " + annotation : "ANR",
2889 info.toString());
2890
2891 // Bring up the infamous App Not Responding dialog
2892 Message msg = Message.obtain();
2893 HashMap map = new HashMap();
2894 msg.what = SHOW_NOT_RESPONDING_MSG;
2895 msg.obj = map;
2896 map.put("app", app);
2897 if (activity != null) {
2898 map.put("activity", activity);
2899 }
2900
2901 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 }
2904
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002905 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 app.persistentActivities--;
2907 if (app.persistentActivities > 0) {
2908 // Still more of 'em...
2909 return;
2910 }
2911 if (app.persistent) {
2912 // Ah, but the application itself is persistent. Whatever!
2913 return;
2914 }
2915
2916 // App is no longer persistent... make sure it and the ones
2917 // following it in the LRU list have the correc oom_adj.
2918 updateOomAdjLocked();
2919 }
2920
2921 public void setPersistent(IBinder token, boolean isPersistent) {
2922 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2923 != PackageManager.PERMISSION_GRANTED) {
2924 String msg = "Permission Denial: setPersistent() from pid="
2925 + Binder.getCallingPid()
2926 + ", uid=" + Binder.getCallingUid()
2927 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002928 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002929 throw new SecurityException(msg);
2930 }
2931
2932 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002933 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 if (index < 0) {
2935 return;
2936 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002937 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 ProcessRecord app = r.app;
2939
Joe Onorato8a9b2202010-02-26 18:56:32 -08002940 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 TAG, "Setting persistence " + isPersistent + ": " + r);
2942
2943 if (isPersistent) {
2944 if (r.persistent) {
2945 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002946 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 return;
2948 }
2949 r.persistent = true;
2950 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002951 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952 if (app.persistentActivities > 1) {
2953 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002954 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 return;
2956 }
2957 if (app.persistent) {
2958 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002959 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 return;
2961 }
2962
2963 // App is now persistent... make sure it and the ones
2964 // following it now have the correct oom_adj.
2965 final long origId = Binder.clearCallingIdentity();
2966 updateOomAdjLocked();
2967 Binder.restoreCallingIdentity(origId);
2968
2969 } else {
2970 if (!r.persistent) {
2971 // Okay okay, I heard you already!
2972 return;
2973 }
2974 r.persistent = false;
2975 final long origId = Binder.clearCallingIdentity();
2976 decPersistentCountLocked(app);
2977 Binder.restoreCallingIdentity(origId);
2978
2979 }
2980 }
2981 }
2982
2983 public boolean clearApplicationUserData(final String packageName,
2984 final IPackageDataObserver observer) {
2985 int uid = Binder.getCallingUid();
2986 int pid = Binder.getCallingPid();
2987 long callingId = Binder.clearCallingIdentity();
2988 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002989 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 int pkgUid = -1;
2991 synchronized(this) {
2992 try {
2993 pkgUid = pm.getPackageUid(packageName);
2994 } catch (RemoteException e) {
2995 }
2996 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002997 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002998 return false;
2999 }
3000 if (uid == pkgUid || checkComponentPermission(
3001 android.Manifest.permission.CLEAR_APP_USER_DATA,
3002 pid, uid, -1)
3003 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003004 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 } else {
3006 throw new SecurityException(pid+" does not have permission:"+
3007 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3008 "for process:"+packageName);
3009 }
3010 }
3011
3012 try {
3013 //clear application user data
3014 pm.clearApplicationUserData(packageName, observer);
3015 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3016 Uri.fromParts("package", packageName, null));
3017 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06003018 synchronized (this) {
3019 broadcastIntentLocked(null, null, intent,
3020 null, null, 0, null, null, null,
3021 false, false, MY_PID, Process.SYSTEM_UID);
3022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 } catch (RemoteException e) {
3024 }
3025 } finally {
3026 Binder.restoreCallingIdentity(callingId);
3027 }
3028 return true;
3029 }
3030
Dianne Hackborn03abb812010-01-04 18:43:19 -08003031 public void killBackgroundProcesses(final String packageName) {
3032 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3033 != PackageManager.PERMISSION_GRANTED &&
3034 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3035 != PackageManager.PERMISSION_GRANTED) {
3036 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 + Binder.getCallingPid()
3038 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003039 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003040 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 throw new SecurityException(msg);
3042 }
3043
3044 long callingId = Binder.clearCallingIdentity();
3045 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003046 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 int pkgUid = -1;
3048 synchronized(this) {
3049 try {
3050 pkgUid = pm.getPackageUid(packageName);
3051 } catch (RemoteException e) {
3052 }
3053 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003054 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 return;
3056 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003057 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003058 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003059 }
3060 } finally {
3061 Binder.restoreCallingIdentity(callingId);
3062 }
3063 }
3064
3065 public void forceStopPackage(final String packageName) {
3066 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3067 != PackageManager.PERMISSION_GRANTED) {
3068 String msg = "Permission Denial: forceStopPackage() from pid="
3069 + Binder.getCallingPid()
3070 + ", uid=" + Binder.getCallingUid()
3071 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003072 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003073 throw new SecurityException(msg);
3074 }
3075
3076 long callingId = Binder.clearCallingIdentity();
3077 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003078 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003079 int pkgUid = -1;
3080 synchronized(this) {
3081 try {
3082 pkgUid = pm.getPackageUid(packageName);
3083 } catch (RemoteException e) {
3084 }
3085 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003086 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003087 return;
3088 }
3089 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 }
3091 } finally {
3092 Binder.restoreCallingIdentity(callingId);
3093 }
3094 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003095
3096 /*
3097 * The pkg name and uid have to be specified.
3098 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3099 */
3100 public void killApplicationWithUid(String pkg, int uid) {
3101 if (pkg == null) {
3102 return;
3103 }
3104 // Make sure the uid is valid.
3105 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003106 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003107 return;
3108 }
3109 int callerUid = Binder.getCallingUid();
3110 // Only the system server can kill an application
3111 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003112 // Post an aysnc message to kill the application
3113 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3114 msg.arg1 = uid;
3115 msg.arg2 = 0;
3116 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003117 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003118 } else {
3119 throw new SecurityException(callerUid + " cannot kill pkg: " +
3120 pkg);
3121 }
3122 }
3123
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003124 public void closeSystemDialogs(String reason) {
3125 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3126 if (reason != null) {
3127 intent.putExtra("reason", reason);
3128 }
3129
3130 final int uid = Binder.getCallingUid();
3131 final long origId = Binder.clearCallingIdentity();
3132 synchronized (this) {
3133 int i = mWatchers.beginBroadcast();
3134 while (i > 0) {
3135 i--;
3136 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3137 if (w != null) {
3138 try {
3139 w.closingSystemDialogs(reason);
3140 } catch (RemoteException e) {
3141 }
3142 }
3143 }
3144 mWatchers.finishBroadcast();
3145
Dianne Hackbornffa42482009-09-23 22:20:11 -07003146 mWindowManager.closeSystemDialogs(reason);
3147
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003148 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3149 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003150 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003151 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003152 Activity.RESULT_CANCELED, null, "close-sys");
3153 }
3154 }
3155
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003156 broadcastIntentLocked(null, null, intent, null,
3157 null, 0, null, null, null, false, false, -1, uid);
3158 }
3159 Binder.restoreCallingIdentity(origId);
3160 }
3161
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003162 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003163 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003164 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3165 for (int i=pids.length-1; i>=0; i--) {
3166 infos[i] = new Debug.MemoryInfo();
3167 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003168 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003169 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003170 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003171
3172 public void killApplicationProcess(String processName, int uid) {
3173 if (processName == null) {
3174 return;
3175 }
3176
3177 int callerUid = Binder.getCallingUid();
3178 // Only the system server can kill an application
3179 if (callerUid == Process.SYSTEM_UID) {
3180 synchronized (this) {
3181 ProcessRecord app = getProcessRecordLocked(processName, uid);
3182 if (app != null) {
3183 try {
3184 app.thread.scheduleSuicide();
3185 } catch (RemoteException e) {
3186 // If the other end already died, then our work here is done.
3187 }
3188 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003189 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003190 + processName + " / " + uid);
3191 }
3192 }
3193 } else {
3194 throw new SecurityException(callerUid + " cannot kill app process: " +
3195 processName);
3196 }
3197 }
3198
Dianne Hackborn03abb812010-01-04 18:43:19 -08003199 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003200 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003201 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3202 Uri.fromParts("package", packageName, null));
3203 intent.putExtra(Intent.EXTRA_UID, uid);
3204 broadcastIntentLocked(null, null, intent,
3205 null, null, 0, null, null, null,
3206 false, false, MY_PID, Process.SYSTEM_UID);
3207 }
3208
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003209 private final boolean killPackageProcessesLocked(String packageName, int uid,
3210 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003211 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212
Dianne Hackborn03abb812010-01-04 18:43:19 -08003213 // Remove all processes this package may have touched: all with the
3214 // same UID (except for the system or root user), and all whose name
3215 // matches the package name.
3216 final String procNamePrefix = packageName + ":";
3217 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3218 final int NA = apps.size();
3219 for (int ia=0; ia<NA; ia++) {
3220 ProcessRecord app = apps.valueAt(ia);
3221 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003222 if (doit) {
3223 procs.add(app);
3224 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003225 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3226 || app.processName.equals(packageName)
3227 || app.processName.startsWith(procNamePrefix)) {
3228 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003229 if (!doit) {
3230 return true;
3231 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003232 app.removed = true;
3233 procs.add(app);
3234 }
3235 }
3236 }
3237 }
3238
3239 int N = procs.size();
3240 for (int i=0; i<N; i++) {
3241 removeProcessLocked(procs.get(i), callerWillRestart);
3242 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003243 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003244 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003245
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003246 private final boolean forceStopPackageLocked(String name, int uid,
3247 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 int i, N;
3249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 if (uid < 0) {
3251 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003252 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 } catch (RemoteException e) {
3254 }
3255 }
3256
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003257 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003258 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003259
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003260 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3261 while (badApps.hasNext()) {
3262 SparseArray<Long> ba = badApps.next();
3263 if (ba.get(uid) != null) {
3264 badApps.remove();
3265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003266 }
3267 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003268
3269 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3270 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003271
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003272 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3273 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003275 if (!doit) {
3276 return true;
3277 }
3278 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003279 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003280 if (r.app != null) {
3281 r.app.removed = true;
3282 }
3283 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003284 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 }
3286 }
3287
3288 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3289 for (ServiceRecord service : mServices.values()) {
3290 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003291 if (!doit) {
3292 return true;
3293 }
3294 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003295 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296 if (service.app != null) {
3297 service.app.removed = true;
3298 }
3299 service.app = null;
3300 services.add(service);
3301 }
3302 }
3303
3304 N = services.size();
3305 for (i=0; i<N; i++) {
3306 bringDownServiceLocked(services.get(i), true);
3307 }
3308
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003309 if (doit) {
3310 if (purgeCache) {
3311 AttributeCache ac = AttributeCache.instance();
3312 if (ac != null) {
3313 ac.removePackage(name);
3314 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003315 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003316 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003317 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003318
3319 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 }
3321
3322 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3323 final String name = app.processName;
3324 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003325 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003326 TAG, "Force removing process " + app + " (" + name
3327 + "/" + uid + ")");
3328
3329 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003330 if (mHeavyWeightProcess == app) {
3331 mHeavyWeightProcess = null;
3332 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003334 boolean needRestart = false;
3335 if (app.pid > 0 && app.pid != MY_PID) {
3336 int pid = app.pid;
3337 synchronized (mPidsSelfLocked) {
3338 mPidsSelfLocked.remove(pid);
3339 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3340 }
3341 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003342 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 Process.killProcess(pid);
3344
3345 if (app.persistent) {
3346 if (!callerWillRestart) {
3347 addAppLocked(app.info);
3348 } else {
3349 needRestart = true;
3350 }
3351 }
3352 } else {
3353 mRemovedProcesses.add(app);
3354 }
3355
3356 return needRestart;
3357 }
3358
3359 private final void processStartTimedOutLocked(ProcessRecord app) {
3360 final int pid = app.pid;
3361 boolean gone = false;
3362 synchronized (mPidsSelfLocked) {
3363 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3364 if (knownApp != null && knownApp.thread == null) {
3365 mPidsSelfLocked.remove(pid);
3366 gone = true;
3367 }
3368 }
3369
3370 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003371 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003372 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003373 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003375 if (mHeavyWeightProcess == app) {
3376 mHeavyWeightProcess = null;
3377 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3378 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003379 // Take care of any launching providers waiting for this process.
3380 checkAppInLaunchingProvidersLocked(app, true);
3381 // Take care of any services that are waiting for the process.
3382 for (int i=0; i<mPendingServices.size(); i++) {
3383 ServiceRecord sr = mPendingServices.get(i);
3384 if (app.info.uid == sr.appInfo.uid
3385 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003386 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003387 mPendingServices.remove(i);
3388 i--;
3389 bringDownServiceLocked(sr, true);
3390 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003392 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003393 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003394 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003395 try {
3396 IBackupManager bm = IBackupManager.Stub.asInterface(
3397 ServiceManager.getService(Context.BACKUP_SERVICE));
3398 bm.agentDisconnected(app.info.packageName);
3399 } catch (RemoteException e) {
3400 // Can't happen; the backup manager is local
3401 }
3402 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003403 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003404 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003405 mPendingBroadcast = null;
3406 scheduleBroadcastsLocked();
3407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003409 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410 }
3411 }
3412
3413 private final boolean attachApplicationLocked(IApplicationThread thread,
3414 int pid) {
3415
3416 // Find the application record that is being attached... either via
3417 // the pid if we are running in multiple processes, or just pull the
3418 // next app record if we are emulating process with anonymous threads.
3419 ProcessRecord app;
3420 if (pid != MY_PID && pid >= 0) {
3421 synchronized (mPidsSelfLocked) {
3422 app = mPidsSelfLocked.get(pid);
3423 }
3424 } else if (mStartingProcesses.size() > 0) {
3425 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003426 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 } else {
3428 app = null;
3429 }
3430
3431 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003432 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003434 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 if (pid > 0 && pid != MY_PID) {
3436 Process.killProcess(pid);
3437 } else {
3438 try {
3439 thread.scheduleExit();
3440 } catch (Exception e) {
3441 // Ignore exceptions.
3442 }
3443 }
3444 return false;
3445 }
3446
3447 // If this application record is still attached to a previous
3448 // process, clean it up now.
3449 if (app.thread != null) {
3450 handleAppDiedLocked(app, true);
3451 }
3452
3453 // Tell the process all about itself.
3454
Joe Onorato8a9b2202010-02-26 18:56:32 -08003455 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 TAG, "Binding process pid " + pid + " to record " + app);
3457
3458 String processName = app.processName;
3459 try {
3460 thread.asBinder().linkToDeath(new AppDeathRecipient(
3461 app, pid, thread), 0);
3462 } catch (RemoteException e) {
3463 app.resetPackageList();
3464 startProcessLocked(app, "link fail", processName);
3465 return false;
3466 }
3467
Doug Zongker2bec3d42009-12-04 12:52:44 -08003468 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469
3470 app.thread = thread;
3471 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003472 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3473 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 app.forcingToForeground = null;
3475 app.foregroundServices = false;
3476 app.debugging = false;
3477
3478 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3479
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003480 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3481 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003483 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003484 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003485 }
3486
Joe Onorato8a9b2202010-02-26 18:56:32 -08003487 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 TAG, "New app record " + app
3489 + " thread=" + thread.asBinder() + " pid=" + pid);
3490 try {
3491 int testMode = IApplicationThread.DEBUG_OFF;
3492 if (mDebugApp != null && mDebugApp.equals(processName)) {
3493 testMode = mWaitForDebugger
3494 ? IApplicationThread.DEBUG_WAIT
3495 : IApplicationThread.DEBUG_ON;
3496 app.debugging = true;
3497 if (mDebugTransient) {
3498 mDebugApp = mOrigDebugApp;
3499 mWaitForDebugger = mOrigWaitForDebugger;
3500 }
3501 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003502
Christopher Tate181fafa2009-05-14 11:12:14 -07003503 // If the app is being launched for restore or full backup, set it up specially
3504 boolean isRestrictedBackupMode = false;
3505 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3506 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3507 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3508 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003509
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003510 ensurePackageDexOpt(app.instrumentationInfo != null
3511 ? app.instrumentationInfo.packageName
3512 : app.info.packageName);
3513 if (app.instrumentationClass != null) {
3514 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003515 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003516 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003517 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003518 thread.bindApplication(processName, app.instrumentationInfo != null
3519 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 app.instrumentationClass, app.instrumentationProfileFile,
3521 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003522 isRestrictedBackupMode || !normalMode,
3523 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003524 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003525 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 } catch (Exception e) {
3527 // todo: Yikes! What should we do? For now we will try to
3528 // start another process, but that could easily get us in
3529 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003530 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531
3532 app.resetPackageList();
3533 startProcessLocked(app, "bind fail", processName);
3534 return false;
3535 }
3536
3537 // Remove this record from the list of starting applications.
3538 mPersistentStartingProcesses.remove(app);
3539 mProcessesOnHold.remove(app);
3540
3541 boolean badApp = false;
3542 boolean didSomething = false;
3543
3544 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003545 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003546 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3548 && processName.equals(hr.processName)) {
3549 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003550 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 didSomething = true;
3552 }
3553 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003554 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003555 + hr.intent.getComponent().flattenToShortString(), e);
3556 badApp = true;
3557 }
3558 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003559 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003560 }
3561 }
3562
3563 // Find any services that should be running in this process...
3564 if (!badApp && mPendingServices.size() > 0) {
3565 ServiceRecord sr = null;
3566 try {
3567 for (int i=0; i<mPendingServices.size(); i++) {
3568 sr = mPendingServices.get(i);
3569 if (app.info.uid != sr.appInfo.uid
3570 || !processName.equals(sr.processName)) {
3571 continue;
3572 }
3573
3574 mPendingServices.remove(i);
3575 i--;
3576 realStartServiceLocked(sr, app);
3577 didSomething = true;
3578 }
3579 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003580 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 + sr.shortName, e);
3582 badApp = true;
3583 }
3584 }
3585
3586 // Check if the next broadcast receiver is in this process...
3587 BroadcastRecord br = mPendingBroadcast;
3588 if (!badApp && br != null && br.curApp == app) {
3589 try {
3590 mPendingBroadcast = null;
3591 processCurBroadcastLocked(br, app);
3592 didSomething = true;
3593 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003594 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595 + br.curComponent.flattenToShortString(), e);
3596 badApp = true;
3597 logBroadcastReceiverDiscard(br);
3598 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3599 br.resultExtras, br.resultAbort, true);
3600 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003601 // We need to reset the state if we fails to start the receiver.
3602 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 }
3604 }
3605
Christopher Tate181fafa2009-05-14 11:12:14 -07003606 // Check whether the next backup agent is in this process...
3607 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003608 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003609 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003610 try {
3611 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3612 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003613 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003614 e.printStackTrace();
3615 }
3616 }
3617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 if (badApp) {
3619 // todo: Also need to kill application to deal with all
3620 // kinds of exceptions.
3621 handleAppDiedLocked(app, false);
3622 return false;
3623 }
3624
3625 if (!didSomething) {
3626 updateOomAdjLocked();
3627 }
3628
3629 return true;
3630 }
3631
3632 public final void attachApplication(IApplicationThread thread) {
3633 synchronized (this) {
3634 int callingPid = Binder.getCallingPid();
3635 final long origId = Binder.clearCallingIdentity();
3636 attachApplicationLocked(thread, callingPid);
3637 Binder.restoreCallingIdentity(origId);
3638 }
3639 }
3640
Dianne Hackborne88846e2009-09-30 21:34:25 -07003641 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003643 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 Binder.restoreCallingIdentity(origId);
3645 }
3646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003648 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003649 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 mWindowManager.enableScreenAfterBoot();
3651 }
3652
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003653 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003654 IntentFilter pkgFilter = new IntentFilter();
3655 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3656 pkgFilter.addDataScheme("package");
3657 mContext.registerReceiver(new BroadcastReceiver() {
3658 @Override
3659 public void onReceive(Context context, Intent intent) {
3660 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3661 if (pkgs != null) {
3662 for (String pkg : pkgs) {
3663 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3664 setResultCode(Activity.RESULT_OK);
3665 return;
3666 }
3667 }
3668 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003669 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003670 }, pkgFilter);
3671
3672 synchronized (this) {
3673 // Ensure that any processes we had put on hold are now started
3674 // up.
3675 final int NP = mProcessesOnHold.size();
3676 if (NP > 0) {
3677 ArrayList<ProcessRecord> procs =
3678 new ArrayList<ProcessRecord>(mProcessesOnHold);
3679 for (int ip=0; ip<NP; ip++) {
3680 this.startProcessLocked(procs.get(ip), "on-hold", null);
3681 }
3682 }
3683
3684 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003685 // Start looking for apps that are abusing wake locks.
3686 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
3687 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003688 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003689 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003690 broadcastIntentLocked(null, null,
3691 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3692 null, null, 0, null, null,
3693 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3694 false, false, MY_PID, Process.SYSTEM_UID);
3695 }
3696 }
3697 }
3698
3699 final void ensureBootCompleted() {
3700 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003701 boolean enableScreen;
3702 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003703 booting = mBooting;
3704 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003705 enableScreen = !mBooted;
3706 mBooted = true;
3707 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003708
3709 if (booting) {
3710 finishBooting();
3711 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003712
3713 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003714 enableScreenAfterBoot();
3715 }
3716 }
3717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 public final void activityPaused(IBinder token, Bundle icicle) {
3719 // Refuse possible leaked file descriptors
3720 if (icicle != null && icicle.hasFileDescriptors()) {
3721 throw new IllegalArgumentException("File descriptors passed in Bundle");
3722 }
3723
3724 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003725 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003726 Binder.restoreCallingIdentity(origId);
3727 }
3728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 public final void activityStopped(IBinder token, Bitmap thumbnail,
3730 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003731 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 TAG, "Activity stopped: token=" + token);
3733
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003734 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003735
3736 final long origId = Binder.clearCallingIdentity();
3737
3738 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003739 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003741 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 r.thumbnail = thumbnail;
3743 r.description = description;
3744 r.stopped = true;
3745 r.state = ActivityState.STOPPED;
3746 if (!r.finishing) {
3747 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003748 r.stack.destroyActivityLocked(r, true);
3749 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 }
3751 }
3752 }
3753 }
3754
3755 if (r != null) {
3756 sendPendingThumbnail(r, null, null, null, false);
3757 }
3758
3759 trimApplications();
3760
3761 Binder.restoreCallingIdentity(origId);
3762 }
3763
3764 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003765 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003766 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 }
3768
3769 public String getCallingPackage(IBinder token) {
3770 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003771 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003772 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 }
3774 }
3775
3776 public ComponentName getCallingActivity(IBinder token) {
3777 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003778 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 return r != null ? r.intent.getComponent() : null;
3780 }
3781 }
3782
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003783 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003784 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003785 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003786 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 if (r != null) {
3788 return r.resultTo;
3789 }
3790 }
3791 return null;
3792 }
3793
3794 public ComponentName getActivityClassForToken(IBinder token) {
3795 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003796 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003798 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 return r.intent.getComponent();
3800 }
3801 return null;
3802 }
3803 }
3804
3805 public String getPackageForToken(IBinder token) {
3806 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003807 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003809 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 return r.packageName;
3811 }
3812 return null;
3813 }
3814 }
3815
3816 public IIntentSender getIntentSender(int type,
3817 String packageName, IBinder token, String resultWho,
3818 int requestCode, Intent intent, String resolvedType, int flags) {
3819 // Refuse possible leaked file descriptors
3820 if (intent != null && intent.hasFileDescriptors() == true) {
3821 throw new IllegalArgumentException("File descriptors passed in Intent");
3822 }
3823
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003824 if (type == INTENT_SENDER_BROADCAST) {
3825 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3826 throw new IllegalArgumentException(
3827 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3828 }
3829 }
3830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 synchronized(this) {
3832 int callingUid = Binder.getCallingUid();
3833 try {
3834 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3835 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003836 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 .getPackageUid(packageName);
3838 if (uid != Binder.getCallingUid()) {
3839 String msg = "Permission Denial: getIntentSender() from pid="
3840 + Binder.getCallingPid()
3841 + ", uid=" + Binder.getCallingUid()
3842 + ", (need uid=" + uid + ")"
3843 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003844 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 throw new SecurityException(msg);
3846 }
3847 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003848
3849 return getIntentSenderLocked(type, packageName, callingUid,
3850 token, resultWho, requestCode, intent, resolvedType, flags);
3851
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003852 } catch (RemoteException e) {
3853 throw new SecurityException(e);
3854 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003855 }
3856 }
3857
3858 IIntentSender getIntentSenderLocked(int type,
3859 String packageName, int callingUid, IBinder token, String resultWho,
3860 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003861 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003862 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003863 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003864 if (index < 0) {
3865 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003867 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003868 if (activity.finishing) {
3869 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003871 }
3872
3873 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3874 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3875 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3876 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3877 |PendingIntent.FLAG_UPDATE_CURRENT);
3878
3879 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3880 type, packageName, activity, resultWho,
3881 requestCode, intent, resolvedType, flags);
3882 WeakReference<PendingIntentRecord> ref;
3883 ref = mIntentSenderRecords.get(key);
3884 PendingIntentRecord rec = ref != null ? ref.get() : null;
3885 if (rec != null) {
3886 if (!cancelCurrent) {
3887 if (updateCurrent) {
3888 rec.key.requestIntent.replaceExtras(intent);
3889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 return rec;
3891 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003892 rec.canceled = true;
3893 mIntentSenderRecords.remove(key);
3894 }
3895 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 return rec;
3897 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003898 rec = new PendingIntentRecord(this, key, callingUid);
3899 mIntentSenderRecords.put(key, rec.ref);
3900 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3901 if (activity.pendingResults == null) {
3902 activity.pendingResults
3903 = new HashSet<WeakReference<PendingIntentRecord>>();
3904 }
3905 activity.pendingResults.add(rec.ref);
3906 }
3907 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003908 }
3909
3910 public void cancelIntentSender(IIntentSender sender) {
3911 if (!(sender instanceof PendingIntentRecord)) {
3912 return;
3913 }
3914 synchronized(this) {
3915 PendingIntentRecord rec = (PendingIntentRecord)sender;
3916 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003917 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 .getPackageUid(rec.key.packageName);
3919 if (uid != Binder.getCallingUid()) {
3920 String msg = "Permission Denial: cancelIntentSender() from pid="
3921 + Binder.getCallingPid()
3922 + ", uid=" + Binder.getCallingUid()
3923 + " is not allowed to cancel packges "
3924 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003925 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 throw new SecurityException(msg);
3927 }
3928 } catch (RemoteException e) {
3929 throw new SecurityException(e);
3930 }
3931 cancelIntentSenderLocked(rec, true);
3932 }
3933 }
3934
3935 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3936 rec.canceled = true;
3937 mIntentSenderRecords.remove(rec.key);
3938 if (cleanActivity && rec.key.activity != null) {
3939 rec.key.activity.pendingResults.remove(rec.ref);
3940 }
3941 }
3942
3943 public String getPackageForIntentSender(IIntentSender pendingResult) {
3944 if (!(pendingResult instanceof PendingIntentRecord)) {
3945 return null;
3946 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003947 try {
3948 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3949 return res.key.packageName;
3950 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 }
3952 return null;
3953 }
3954
3955 public void setProcessLimit(int max) {
3956 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3957 "setProcessLimit()");
3958 mProcessLimit = max;
3959 }
3960
3961 public int getProcessLimit() {
3962 return mProcessLimit;
3963 }
3964
3965 void foregroundTokenDied(ForegroundToken token) {
3966 synchronized (ActivityManagerService.this) {
3967 synchronized (mPidsSelfLocked) {
3968 ForegroundToken cur
3969 = mForegroundProcesses.get(token.pid);
3970 if (cur != token) {
3971 return;
3972 }
3973 mForegroundProcesses.remove(token.pid);
3974 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3975 if (pr == null) {
3976 return;
3977 }
3978 pr.forcingToForeground = null;
3979 pr.foregroundServices = false;
3980 }
3981 updateOomAdjLocked();
3982 }
3983 }
3984
3985 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3986 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3987 "setProcessForeground()");
3988 synchronized(this) {
3989 boolean changed = false;
3990
3991 synchronized (mPidsSelfLocked) {
3992 ProcessRecord pr = mPidsSelfLocked.get(pid);
3993 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003994 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 return;
3996 }
3997 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3998 if (oldToken != null) {
3999 oldToken.token.unlinkToDeath(oldToken, 0);
4000 mForegroundProcesses.remove(pid);
4001 pr.forcingToForeground = null;
4002 changed = true;
4003 }
4004 if (isForeground && token != null) {
4005 ForegroundToken newToken = new ForegroundToken() {
4006 public void binderDied() {
4007 foregroundTokenDied(this);
4008 }
4009 };
4010 newToken.pid = pid;
4011 newToken.token = token;
4012 try {
4013 token.linkToDeath(newToken, 0);
4014 mForegroundProcesses.put(pid, newToken);
4015 pr.forcingToForeground = token;
4016 changed = true;
4017 } catch (RemoteException e) {
4018 // If the process died while doing this, we will later
4019 // do the cleanup with the process death link.
4020 }
4021 }
4022 }
4023
4024 if (changed) {
4025 updateOomAdjLocked();
4026 }
4027 }
4028 }
4029
4030 // =========================================================
4031 // PERMISSIONS
4032 // =========================================================
4033
4034 static class PermissionController extends IPermissionController.Stub {
4035 ActivityManagerService mActivityManagerService;
4036 PermissionController(ActivityManagerService activityManagerService) {
4037 mActivityManagerService = activityManagerService;
4038 }
4039
4040 public boolean checkPermission(String permission, int pid, int uid) {
4041 return mActivityManagerService.checkPermission(permission, pid,
4042 uid) == PackageManager.PERMISSION_GRANTED;
4043 }
4044 }
4045
4046 /**
4047 * This can be called with or without the global lock held.
4048 */
4049 int checkComponentPermission(String permission, int pid, int uid,
4050 int reqUid) {
4051 // We might be performing an operation on behalf of an indirect binder
4052 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4053 // client identity accordingly before proceeding.
4054 Identity tlsIdentity = sCallerIdentity.get();
4055 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004056 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4058 uid = tlsIdentity.uid;
4059 pid = tlsIdentity.pid;
4060 }
4061
4062 // Root, system server and our own process get to do everything.
4063 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4064 !Process.supportsProcesses()) {
4065 return PackageManager.PERMISSION_GRANTED;
4066 }
4067 // If the target requires a specific UID, always fail for others.
4068 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004069 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 return PackageManager.PERMISSION_DENIED;
4071 }
4072 if (permission == null) {
4073 return PackageManager.PERMISSION_GRANTED;
4074 }
4075 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004076 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 .checkUidPermission(permission, uid);
4078 } catch (RemoteException e) {
4079 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004080 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 }
4082 return PackageManager.PERMISSION_DENIED;
4083 }
4084
4085 /**
4086 * As the only public entry point for permissions checking, this method
4087 * can enforce the semantic that requesting a check on a null global
4088 * permission is automatically denied. (Internally a null permission
4089 * string is used when calling {@link #checkComponentPermission} in cases
4090 * when only uid-based security is needed.)
4091 *
4092 * This can be called with or without the global lock held.
4093 */
4094 public int checkPermission(String permission, int pid, int uid) {
4095 if (permission == null) {
4096 return PackageManager.PERMISSION_DENIED;
4097 }
4098 return checkComponentPermission(permission, pid, uid, -1);
4099 }
4100
4101 /**
4102 * Binder IPC calls go through the public entry point.
4103 * This can be called with or without the global lock held.
4104 */
4105 int checkCallingPermission(String permission) {
4106 return checkPermission(permission,
4107 Binder.getCallingPid(),
4108 Binder.getCallingUid());
4109 }
4110
4111 /**
4112 * This can be called with or without the global lock held.
4113 */
4114 void enforceCallingPermission(String permission, String func) {
4115 if (checkCallingPermission(permission)
4116 == PackageManager.PERMISSION_GRANTED) {
4117 return;
4118 }
4119
4120 String msg = "Permission Denial: " + func + " from pid="
4121 + Binder.getCallingPid()
4122 + ", uid=" + Binder.getCallingUid()
4123 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004124 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 throw new SecurityException(msg);
4126 }
4127
4128 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4129 ProviderInfo pi, int uid, int modeFlags) {
4130 try {
4131 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4132 if ((pi.readPermission != null) &&
4133 (pm.checkUidPermission(pi.readPermission, uid)
4134 != PackageManager.PERMISSION_GRANTED)) {
4135 return false;
4136 }
4137 }
4138 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4139 if ((pi.writePermission != null) &&
4140 (pm.checkUidPermission(pi.writePermission, uid)
4141 != PackageManager.PERMISSION_GRANTED)) {
4142 return false;
4143 }
4144 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004145 if (!pi.exported && pi.applicationInfo.uid != uid) {
4146 return false;
4147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004148 return true;
4149 } catch (RemoteException e) {
4150 return false;
4151 }
4152 }
4153
4154 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4155 int modeFlags) {
4156 // Root gets to do everything.
4157 if (uid == 0 || !Process.supportsProcesses()) {
4158 return true;
4159 }
4160 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4161 if (perms == null) return false;
4162 UriPermission perm = perms.get(uri);
4163 if (perm == null) return false;
4164 return (modeFlags&perm.modeFlags) == modeFlags;
4165 }
4166
4167 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4168 // Another redirected-binder-call permissions check as in
4169 // {@link checkComponentPermission}.
4170 Identity tlsIdentity = sCallerIdentity.get();
4171 if (tlsIdentity != null) {
4172 uid = tlsIdentity.uid;
4173 pid = tlsIdentity.pid;
4174 }
4175
4176 // Our own process gets to do everything.
4177 if (pid == MY_PID) {
4178 return PackageManager.PERMISSION_GRANTED;
4179 }
4180 synchronized(this) {
4181 return checkUriPermissionLocked(uri, uid, modeFlags)
4182 ? PackageManager.PERMISSION_GRANTED
4183 : PackageManager.PERMISSION_DENIED;
4184 }
4185 }
4186
Dianne Hackborn39792d22010-08-19 18:01:52 -07004187 /**
4188 * Check if the targetPkg can be granted permission to access uri by
4189 * the callingUid using the given modeFlags. Throws a security exception
4190 * if callingUid is not allowed to do this. Returns the uid of the target
4191 * if the URI permission grant should be performed; returns -1 if it is not
4192 * needed (for example targetPkg already has permission to access the URI).
4193 */
4194 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4195 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4197 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4198 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004199 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 }
4201
Joe Onorato8a9b2202010-02-26 18:56:32 -08004202 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004203 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004204
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004205 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206
4207 // If this is not a content: uri, we can't do anything with it.
4208 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004209 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004210 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004211 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 }
4213
4214 String name = uri.getAuthority();
4215 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004216 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 if (cpr != null) {
4218 pi = cpr.info;
4219 } else {
4220 try {
4221 pi = pm.resolveContentProvider(name,
4222 PackageManager.GET_URI_PERMISSION_PATTERNS);
4223 } catch (RemoteException ex) {
4224 }
4225 }
4226 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004227 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004228 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 }
4230
4231 int targetUid;
4232 try {
4233 targetUid = pm.getPackageUid(targetPkg);
4234 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004235 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004236 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004237 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 }
4239 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004240 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004241 }
4242
4243 // First... does the target actually need this permission?
4244 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4245 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004246 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004247 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004248 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 }
4250
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004251 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004252 if (!pi.grantUriPermissions) {
4253 throw new SecurityException("Provider " + pi.packageName
4254 + "/" + pi.name
4255 + " does not allow granting of Uri permissions (uri "
4256 + uri + ")");
4257 }
4258 if (pi.uriPermissionPatterns != null) {
4259 final int N = pi.uriPermissionPatterns.length;
4260 boolean allowed = false;
4261 for (int i=0; i<N; i++) {
4262 if (pi.uriPermissionPatterns[i] != null
4263 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4264 allowed = true;
4265 break;
4266 }
4267 }
4268 if (!allowed) {
4269 throw new SecurityException("Provider " + pi.packageName
4270 + "/" + pi.name
4271 + " does not allow granting of permission to path of Uri "
4272 + uri);
4273 }
4274 }
4275
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004276 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 // this uri?
4278 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4279 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4280 throw new SecurityException("Uid " + callingUid
4281 + " does not have permission to uri " + uri);
4282 }
4283 }
4284
Dianne Hackborn39792d22010-08-19 18:01:52 -07004285 return targetUid;
4286 }
4287
4288 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4289 Uri uri, int modeFlags, UriPermissionOwner owner) {
4290 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4291 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4292 if (modeFlags == 0) {
4293 return;
4294 }
4295
4296 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004297 // to the uri, and the target doesn't. Let's now give this to
4298 // the target.
4299
Joe Onorato8a9b2202010-02-26 18:56:32 -08004300 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004301 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 HashMap<Uri, UriPermission> targetUris
4304 = mGrantedUriPermissions.get(targetUid);
4305 if (targetUris == null) {
4306 targetUris = new HashMap<Uri, UriPermission>();
4307 mGrantedUriPermissions.put(targetUid, targetUris);
4308 }
4309
4310 UriPermission perm = targetUris.get(uri);
4311 if (perm == null) {
4312 perm = new UriPermission(targetUid, uri);
4313 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004317 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 perm.globalModeFlags |= modeFlags;
4319 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004320 perm.readOwners.add(owner);
4321 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004322 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004323 perm.writeOwners.add(owner);
4324 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004325 }
4326 }
4327
Dianne Hackborn39792d22010-08-19 18:01:52 -07004328 void grantUriPermissionLocked(int callingUid,
4329 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4330 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4331 if (targetUid < 0) {
4332 return;
4333 }
4334
4335 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4336 }
4337
4338 /**
4339 * Like checkGrantUriPermissionLocked, but takes an Intent.
4340 */
4341 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4342 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004343 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004344 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004345 + " from " + intent + "; flags=0x"
4346 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004349 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 }
4351 Uri data = intent.getData();
4352 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004353 return -1;
4354 }
4355 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4356 intent.getFlags());
4357 }
4358
4359 /**
4360 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4361 */
4362 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4363 String targetPkg, Intent intent, UriPermissionOwner owner) {
4364 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4365 intent.getFlags(), owner);
4366 }
4367
4368 void grantUriPermissionFromIntentLocked(int callingUid,
4369 String targetPkg, Intent intent, UriPermissionOwner owner) {
4370 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4371 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 return;
4373 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004374
4375 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 }
4377
4378 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4379 Uri uri, int modeFlags) {
4380 synchronized(this) {
4381 final ProcessRecord r = getRecordForAppLocked(caller);
4382 if (r == null) {
4383 throw new SecurityException("Unable to find app for caller "
4384 + caller
4385 + " when granting permission to uri " + uri);
4386 }
4387 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004388 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004389 }
4390 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004391 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004392 }
4393
4394 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4395 null);
4396 }
4397 }
4398
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004399 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4401 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4402 HashMap<Uri, UriPermission> perms
4403 = mGrantedUriPermissions.get(perm.uid);
4404 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004405 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004406 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004407 perms.remove(perm.uri);
4408 if (perms.size() == 0) {
4409 mGrantedUriPermissions.remove(perm.uid);
4410 }
4411 }
4412 }
4413 }
4414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4416 int modeFlags) {
4417 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4418 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4419 if (modeFlags == 0) {
4420 return;
4421 }
4422
Joe Onorato8a9b2202010-02-26 18:56:32 -08004423 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004424 "Revoking all granted permissions to " + uri);
4425
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004426 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004427
4428 final String authority = uri.getAuthority();
4429 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004430 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 if (cpr != null) {
4432 pi = cpr.info;
4433 } else {
4434 try {
4435 pi = pm.resolveContentProvider(authority,
4436 PackageManager.GET_URI_PERMISSION_PATTERNS);
4437 } catch (RemoteException ex) {
4438 }
4439 }
4440 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004441 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442 return;
4443 }
4444
4445 // Does the caller have this permission on the URI?
4446 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4447 // Right now, if you are not the original owner of the permission,
4448 // you are not allowed to revoke it.
4449 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4450 throw new SecurityException("Uid " + callingUid
4451 + " does not have permission to uri " + uri);
4452 //}
4453 }
4454
4455 // Go through all of the permissions and remove any that match.
4456 final List<String> SEGMENTS = uri.getPathSegments();
4457 if (SEGMENTS != null) {
4458 final int NS = SEGMENTS.size();
4459 int N = mGrantedUriPermissions.size();
4460 for (int i=0; i<N; i++) {
4461 HashMap<Uri, UriPermission> perms
4462 = mGrantedUriPermissions.valueAt(i);
4463 Iterator<UriPermission> it = perms.values().iterator();
4464 toploop:
4465 while (it.hasNext()) {
4466 UriPermission perm = it.next();
4467 Uri targetUri = perm.uri;
4468 if (!authority.equals(targetUri.getAuthority())) {
4469 continue;
4470 }
4471 List<String> targetSegments = targetUri.getPathSegments();
4472 if (targetSegments == null) {
4473 continue;
4474 }
4475 if (targetSegments.size() < NS) {
4476 continue;
4477 }
4478 for (int j=0; j<NS; j++) {
4479 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4480 continue toploop;
4481 }
4482 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004483 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004484 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 perm.clearModes(modeFlags);
4486 if (perm.modeFlags == 0) {
4487 it.remove();
4488 }
4489 }
4490 if (perms.size() == 0) {
4491 mGrantedUriPermissions.remove(
4492 mGrantedUriPermissions.keyAt(i));
4493 N--;
4494 i--;
4495 }
4496 }
4497 }
4498 }
4499
4500 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4501 int modeFlags) {
4502 synchronized(this) {
4503 final ProcessRecord r = getRecordForAppLocked(caller);
4504 if (r == null) {
4505 throw new SecurityException("Unable to find app for caller "
4506 + caller
4507 + " when revoking permission to uri " + uri);
4508 }
4509 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004510 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 return;
4512 }
4513
4514 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4515 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4516 if (modeFlags == 0) {
4517 return;
4518 }
4519
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004520 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521
4522 final String authority = uri.getAuthority();
4523 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004524 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004525 if (cpr != null) {
4526 pi = cpr.info;
4527 } else {
4528 try {
4529 pi = pm.resolveContentProvider(authority,
4530 PackageManager.GET_URI_PERMISSION_PATTERNS);
4531 } catch (RemoteException ex) {
4532 }
4533 }
4534 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004535 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 return;
4537 }
4538
4539 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4540 }
4541 }
4542
Dianne Hackborn7e269642010-08-25 19:50:20 -07004543 @Override
4544 public IBinder newUriPermissionOwner(String name) {
4545 synchronized(this) {
4546 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4547 return owner.getExternalTokenLocked();
4548 }
4549 }
4550
4551 @Override
4552 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4553 Uri uri, int modeFlags) {
4554 synchronized(this) {
4555 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4556 if (owner == null) {
4557 throw new IllegalArgumentException("Unknown owner: " + token);
4558 }
4559 if (fromUid != Binder.getCallingUid()) {
4560 if (Binder.getCallingUid() != Process.myUid()) {
4561 // Only system code can grant URI permissions on behalf
4562 // of other users.
4563 throw new SecurityException("nice try");
4564 }
4565 }
4566 if (targetPkg == null) {
4567 throw new IllegalArgumentException("null target");
4568 }
4569 if (uri == null) {
4570 throw new IllegalArgumentException("null uri");
4571 }
4572
4573 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4574 }
4575 }
4576
4577 @Override
4578 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4579 synchronized(this) {
4580 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4581 if (owner == null) {
4582 throw new IllegalArgumentException("Unknown owner: " + token);
4583 }
4584
4585 if (uri == null) {
4586 owner.removeUriPermissionsLocked(mode);
4587 } else {
4588 owner.removeUriPermissionLocked(uri, mode);
4589 }
4590 }
4591 }
4592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4594 synchronized (this) {
4595 ProcessRecord app =
4596 who != null ? getRecordForAppLocked(who) : null;
4597 if (app == null) return;
4598
4599 Message msg = Message.obtain();
4600 msg.what = WAIT_FOR_DEBUGGER_MSG;
4601 msg.obj = app;
4602 msg.arg1 = waiting ? 1 : 0;
4603 mHandler.sendMessage(msg);
4604 }
4605 }
4606
4607 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4608 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004609 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004611 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004612 }
4613
4614 // =========================================================
4615 // TASK MANAGEMENT
4616 // =========================================================
4617
4618 public List getTasks(int maxNum, int flags,
4619 IThumbnailReceiver receiver) {
4620 ArrayList list = new ArrayList();
4621
4622 PendingThumbnailsRecord pending = null;
4623 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004624 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625
4626 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004627 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004628 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4629 + ", receiver=" + receiver);
4630
4631 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4632 != PackageManager.PERMISSION_GRANTED) {
4633 if (receiver != null) {
4634 // If the caller wants to wait for pending thumbnails,
4635 // it ain't gonna get them.
4636 try {
4637 receiver.finished();
4638 } catch (RemoteException ex) {
4639 }
4640 }
4641 String msg = "Permission Denial: getTasks() from pid="
4642 + Binder.getCallingPid()
4643 + ", uid=" + Binder.getCallingUid()
4644 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004645 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004646 throw new SecurityException(msg);
4647 }
4648
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004649 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004650 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004651 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004652 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 CharSequence topDescription = null;
4654 TaskRecord curTask = null;
4655 int numActivities = 0;
4656 int numRunning = 0;
4657 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004658 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004660 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004661
4662 // Initialize state for next task if needed.
4663 if (top == null ||
4664 (top.state == ActivityState.INITIALIZING
4665 && top.task == r.task)) {
4666 top = r;
4667 topDescription = r.description;
4668 curTask = r.task;
4669 numActivities = numRunning = 0;
4670 }
4671
4672 // Add 'r' into the current task.
4673 numActivities++;
4674 if (r.app != null && r.app.thread != null) {
4675 numRunning++;
4676 }
4677 if (topDescription == null) {
4678 topDescription = r.description;
4679 }
4680
Joe Onorato8a9b2202010-02-26 18:56:32 -08004681 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004682 TAG, r.intent.getComponent().flattenToShortString()
4683 + ": task=" + r.task);
4684
4685 // If the next one is a different task, generate a new
4686 // TaskInfo entry for what we have.
4687 if (next == null || next.task != curTask) {
4688 ActivityManager.RunningTaskInfo ci
4689 = new ActivityManager.RunningTaskInfo();
4690 ci.id = curTask.taskId;
4691 ci.baseActivity = r.intent.getComponent();
4692 ci.topActivity = top.intent.getComponent();
4693 ci.thumbnail = top.thumbnail;
4694 ci.description = topDescription;
4695 ci.numActivities = numActivities;
4696 ci.numRunning = numRunning;
4697 //System.out.println(
4698 // "#" + maxNum + ": " + " descr=" + ci.description);
4699 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004700 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004701 TAG, "State=" + top.state + "Idle=" + top.idle
4702 + " app=" + top.app
4703 + " thr=" + (top.app != null ? top.app.thread : null));
4704 if (top.state == ActivityState.RESUMED
4705 || top.state == ActivityState.PAUSING) {
4706 if (top.idle && top.app != null
4707 && top.app.thread != null) {
4708 topRecord = top;
4709 topThumbnail = top.app.thread;
4710 } else {
4711 top.thumbnailNeeded = true;
4712 }
4713 }
4714 if (pending == null) {
4715 pending = new PendingThumbnailsRecord(receiver);
4716 }
4717 pending.pendingRecords.add(top);
4718 }
4719 list.add(ci);
4720 maxNum--;
4721 top = null;
4722 }
4723 }
4724
4725 if (pending != null) {
4726 mPendingThumbnails.add(pending);
4727 }
4728 }
4729
Joe Onorato8a9b2202010-02-26 18:56:32 -08004730 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731
4732 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004733 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 try {
4735 topThumbnail.requestThumbnail(topRecord);
4736 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004737 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004738 sendPendingThumbnail(null, topRecord, null, null, true);
4739 }
4740 }
4741
4742 if (pending == null && receiver != null) {
4743 // In this case all thumbnails were available and the client
4744 // is being asked to be told when the remaining ones come in...
4745 // which is unusually, since the top-most currently running
4746 // activity should never have a canned thumbnail! Oh well.
4747 try {
4748 receiver.finished();
4749 } catch (RemoteException ex) {
4750 }
4751 }
4752
4753 return list;
4754 }
4755
4756 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4757 int flags) {
4758 synchronized (this) {
4759 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4760 "getRecentTasks()");
4761
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004762 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004764 final int N = mRecentTasks.size();
4765 ArrayList<ActivityManager.RecentTaskInfo> res
4766 = new ArrayList<ActivityManager.RecentTaskInfo>(
4767 maxNum < N ? maxNum : N);
4768 for (int i=0; i<N && maxNum > 0; i++) {
4769 TaskRecord tr = mRecentTasks.get(i);
4770 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4771 || (tr.intent == null)
4772 || ((tr.intent.getFlags()
4773 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4774 ActivityManager.RecentTaskInfo rti
4775 = new ActivityManager.RecentTaskInfo();
4776 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4777 rti.baseIntent = new Intent(
4778 tr.intent != null ? tr.intent : tr.affinityIntent);
4779 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004780
4781 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4782 // Check whether this activity is currently available.
4783 try {
4784 if (rti.origActivity != null) {
4785 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4786 continue;
4787 }
4788 } else if (rti.baseIntent != null) {
4789 if (pm.queryIntentActivities(rti.baseIntent,
4790 null, 0) == null) {
4791 continue;
4792 }
4793 }
4794 } catch (RemoteException e) {
4795 // Will never happen.
4796 }
4797 }
4798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004799 res.add(rti);
4800 maxNum--;
4801 }
4802 }
4803 return res;
4804 }
4805 }
4806
4807 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4808 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004809 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004810 TaskRecord jt = startTask;
4811
4812 // First look backwards
4813 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004814 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 if (r.task != jt) {
4816 jt = r.task;
4817 if (affinity.equals(jt.affinity)) {
4818 return j;
4819 }
4820 }
4821 }
4822
4823 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004824 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004825 jt = startTask;
4826 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004827 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 if (r.task != jt) {
4829 if (affinity.equals(jt.affinity)) {
4830 return j;
4831 }
4832 jt = r.task;
4833 }
4834 }
4835
4836 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004837 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 return N-1;
4839 }
4840
4841 return -1;
4842 }
4843
4844 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004845 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004846 */
4847 public void moveTaskToFront(int task) {
4848 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4849 "moveTaskToFront()");
4850
4851 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004852 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4853 Binder.getCallingUid(), "Task to front")) {
4854 return;
4855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004856 final long origId = Binder.clearCallingIdentity();
4857 try {
4858 int N = mRecentTasks.size();
4859 for (int i=0; i<N; i++) {
4860 TaskRecord tr = mRecentTasks.get(i);
4861 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004862 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 return;
4864 }
4865 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004866 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4867 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004869 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004870 return;
4871 }
4872 }
4873 } finally {
4874 Binder.restoreCallingIdentity(origId);
4875 }
4876 }
4877 }
4878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004879 public void moveTaskToBack(int task) {
4880 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4881 "moveTaskToBack()");
4882
4883 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004884 if (mMainStack.mResumedActivity != null
4885 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004886 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4887 Binder.getCallingUid(), "Task to back")) {
4888 return;
4889 }
4890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004892 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004893 Binder.restoreCallingIdentity(origId);
4894 }
4895 }
4896
4897 /**
4898 * Moves an activity, and all of the other activities within the same task, to the bottom
4899 * of the history stack. The activity's order within the task is unchanged.
4900 *
4901 * @param token A reference to the activity we wish to move
4902 * @param nonRoot If false then this only works if the activity is the root
4903 * of a task; if true it will work for any activity in a task.
4904 * @return Returns true if the move completed, false if not.
4905 */
4906 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4907 synchronized(this) {
4908 final long origId = Binder.clearCallingIdentity();
4909 int taskId = getTaskForActivityLocked(token, !nonRoot);
4910 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004911 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 }
4913 Binder.restoreCallingIdentity(origId);
4914 }
4915 return false;
4916 }
4917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 public void moveTaskBackwards(int task) {
4919 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4920 "moveTaskBackwards()");
4921
4922 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004923 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4924 Binder.getCallingUid(), "Task backwards")) {
4925 return;
4926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 final long origId = Binder.clearCallingIdentity();
4928 moveTaskBackwardsLocked(task);
4929 Binder.restoreCallingIdentity(origId);
4930 }
4931 }
4932
4933 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004934 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004935 }
4936
4937 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4938 synchronized(this) {
4939 return getTaskForActivityLocked(token, onlyRoot);
4940 }
4941 }
4942
4943 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004944 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 TaskRecord lastTask = null;
4946 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004947 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 if (r == token) {
4949 if (!onlyRoot || lastTask != r.task) {
4950 return r.task.taskId;
4951 }
4952 return -1;
4953 }
4954 lastTask = r.task;
4955 }
4956
4957 return -1;
4958 }
4959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 public void finishOtherInstances(IBinder token, ComponentName className) {
4961 synchronized(this) {
4962 final long origId = Binder.clearCallingIdentity();
4963
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004964 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 TaskRecord lastTask = null;
4966 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004967 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968 if (r.realActivity.equals(className)
4969 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004970 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004971 null, "others")) {
4972 i--;
4973 N--;
4974 }
4975 }
4976 lastTask = r.task;
4977 }
4978
4979 Binder.restoreCallingIdentity(origId);
4980 }
4981 }
4982
4983 // =========================================================
4984 // THUMBNAILS
4985 // =========================================================
4986
4987 public void reportThumbnail(IBinder token,
4988 Bitmap thumbnail, CharSequence description) {
4989 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4990 final long origId = Binder.clearCallingIdentity();
4991 sendPendingThumbnail(null, token, thumbnail, description, true);
4992 Binder.restoreCallingIdentity(origId);
4993 }
4994
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004995 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 Bitmap thumbnail, CharSequence description, boolean always) {
4997 TaskRecord task = null;
4998 ArrayList receivers = null;
4999
5000 //System.out.println("Send pending thumbnail: " + r);
5001
5002 synchronized(this) {
5003 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005004 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005005 if (index < 0) {
5006 return;
5007 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005008 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005009 }
5010 if (thumbnail == null) {
5011 thumbnail = r.thumbnail;
5012 description = r.description;
5013 }
5014 if (thumbnail == null && !always) {
5015 // If there is no thumbnail, and this entry is not actually
5016 // going away, then abort for now and pick up the next
5017 // thumbnail we get.
5018 return;
5019 }
5020 task = r.task;
5021
5022 int N = mPendingThumbnails.size();
5023 int i=0;
5024 while (i<N) {
5025 PendingThumbnailsRecord pr =
5026 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5027 //System.out.println("Looking in " + pr.pendingRecords);
5028 if (pr.pendingRecords.remove(r)) {
5029 if (receivers == null) {
5030 receivers = new ArrayList();
5031 }
5032 receivers.add(pr);
5033 if (pr.pendingRecords.size() == 0) {
5034 pr.finished = true;
5035 mPendingThumbnails.remove(i);
5036 N--;
5037 continue;
5038 }
5039 }
5040 i++;
5041 }
5042 }
5043
5044 if (receivers != null) {
5045 final int N = receivers.size();
5046 for (int i=0; i<N; i++) {
5047 try {
5048 PendingThumbnailsRecord pr =
5049 (PendingThumbnailsRecord)receivers.get(i);
5050 pr.receiver.newThumbnail(
5051 task != null ? task.taskId : -1, thumbnail, description);
5052 if (pr.finished) {
5053 pr.receiver.finished();
5054 }
5055 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005056 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005057 }
5058 }
5059 }
5060 }
5061
5062 // =========================================================
5063 // CONTENT PROVIDERS
5064 // =========================================================
5065
5066 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5067 List providers = null;
5068 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005069 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005070 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005071 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005072 } catch (RemoteException ex) {
5073 }
5074 if (providers != null) {
5075 final int N = providers.size();
5076 for (int i=0; i<N; i++) {
5077 ProviderInfo cpi =
5078 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005079 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005080 if (cpr == null) {
5081 cpr = new ContentProviderRecord(cpi, app.info);
5082 mProvidersByClass.put(cpi.name, cpr);
5083 }
5084 app.pubProviders.put(cpi.name, cpr);
5085 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005086 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005087 }
5088 }
5089 return providers;
5090 }
5091
5092 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005093 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005094 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5095 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5096 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5097 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005098 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 return null;
5100 }
5101 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5102 cpi.exported ? -1 : cpi.applicationInfo.uid)
5103 == PackageManager.PERMISSION_GRANTED) {
5104 return null;
5105 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005106
5107 PathPermission[] pps = cpi.pathPermissions;
5108 if (pps != null) {
5109 int i = pps.length;
5110 while (i > 0) {
5111 i--;
5112 PathPermission pp = pps[i];
5113 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5114 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005115 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005116 return null;
5117 }
5118 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5119 cpi.exported ? -1 : cpi.applicationInfo.uid)
5120 == PackageManager.PERMISSION_GRANTED) {
5121 return null;
5122 }
5123 }
5124 }
5125
Dianne Hackbornb424b632010-08-18 15:59:05 -07005126 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5127 if (perms != null) {
5128 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5129 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5130 return null;
5131 }
5132 }
5133 }
5134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135 String msg = "Permission Denial: opening provider " + cpi.name
5136 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5137 + ", uid=" + callingUid + ") requires "
5138 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005139 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 return msg;
5141 }
5142
5143 private final ContentProviderHolder getContentProviderImpl(
5144 IApplicationThread caller, String name) {
5145 ContentProviderRecord cpr;
5146 ProviderInfo cpi = null;
5147
5148 synchronized(this) {
5149 ProcessRecord r = null;
5150 if (caller != null) {
5151 r = getRecordForAppLocked(caller);
5152 if (r == null) {
5153 throw new SecurityException(
5154 "Unable to find app for caller " + caller
5155 + " (pid=" + Binder.getCallingPid()
5156 + ") when getting content provider " + name);
5157 }
5158 }
5159
5160 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005161 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 if (cpr != null) {
5163 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005164 String msg;
5165 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5166 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005167 }
5168
5169 if (r != null && cpr.canRunHere(r)) {
5170 // This provider has been published or is in the process
5171 // of being published... but it is also allowed to run
5172 // in the caller's process, so don't make a connection
5173 // and just let the caller instantiate its own instance.
5174 if (cpr.provider != null) {
5175 // don't give caller the provider object, it needs
5176 // to make its own.
5177 cpr = new ContentProviderRecord(cpr);
5178 }
5179 return cpr;
5180 }
5181
5182 final long origId = Binder.clearCallingIdentity();
5183
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005184 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005185 // return it right away.
5186 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005187 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005188 "Adding provider requested by "
5189 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005190 + cpr.info.processName);
5191 Integer cnt = r.conProviders.get(cpr);
5192 if (cnt == null) {
5193 r.conProviders.put(cpr, new Integer(1));
5194 } else {
5195 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005198 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5199 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005200 // make sure to count it as being accessed and thus
5201 // back up on the LRU list. This is good because
5202 // content providers are often expensive to start.
5203 updateLruProcessLocked(cpr.app, false, true);
5204 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005205 } else {
5206 cpr.externals++;
5207 }
5208
5209 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 updateOomAdjLocked(cpr.app);
5211 }
5212
5213 Binder.restoreCallingIdentity(origId);
5214
5215 } else {
5216 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005217 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005218 resolveContentProvider(name,
5219 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 } catch (RemoteException ex) {
5221 }
5222 if (cpi == null) {
5223 return null;
5224 }
5225
Dianne Hackbornb424b632010-08-18 15:59:05 -07005226 String msg;
5227 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5228 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 }
5230
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005231 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5232 && !cpi.processName.equals("system")) {
5233 // If this content provider does not run in the system
5234 // process, and the system is not yet ready to run other
5235 // processes, then fail fast instead of hanging.
5236 throw new IllegalArgumentException(
5237 "Attempt to launch content provider before system ready");
5238 }
5239
Dianne Hackborn860755f2010-06-03 18:47:52 -07005240 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005241 final boolean firstClass = cpr == null;
5242 if (firstClass) {
5243 try {
5244 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005245 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246 getApplicationInfo(
5247 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005248 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005250 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 + cpi.name);
5252 return null;
5253 }
5254 cpr = new ContentProviderRecord(cpi, ai);
5255 } catch (RemoteException ex) {
5256 // pm is in same process, this will never happen.
5257 }
5258 }
5259
5260 if (r != null && cpr.canRunHere(r)) {
5261 // If this is a multiprocess provider, then just return its
5262 // info and allow the caller to instantiate it. Only do
5263 // this if the provider is the same user as the caller's
5264 // process, or can run as root (so can be in any process).
5265 return cpr;
5266 }
5267
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005268 if (DEBUG_PROVIDER) {
5269 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005270 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005271 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 }
5273
5274 // This is single process, and our app is now connecting to it.
5275 // See if we are already in the process of launching this
5276 // provider.
5277 final int N = mLaunchingProviders.size();
5278 int i;
5279 for (i=0; i<N; i++) {
5280 if (mLaunchingProviders.get(i) == cpr) {
5281 break;
5282 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 }
5284
5285 // If the provider is not already being launched, then get it
5286 // started.
5287 if (i >= N) {
5288 final long origId = Binder.clearCallingIdentity();
5289 ProcessRecord proc = startProcessLocked(cpi.processName,
5290 cpr.appInfo, false, 0, "content provider",
5291 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005292 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005294 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 + cpi.applicationInfo.packageName + "/"
5296 + cpi.applicationInfo.uid + " for provider "
5297 + name + ": process is bad");
5298 return null;
5299 }
5300 cpr.launchingApp = proc;
5301 mLaunchingProviders.add(cpr);
5302 Binder.restoreCallingIdentity(origId);
5303 }
5304
5305 // Make sure the provider is published (the same provider class
5306 // may be published under multiple names).
5307 if (firstClass) {
5308 mProvidersByClass.put(cpi.name, cpr);
5309 }
5310 mProvidersByName.put(name, cpr);
5311
5312 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005313 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005314 "Adding provider requested by "
5315 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005316 + cpr.info.processName);
5317 Integer cnt = r.conProviders.get(cpr);
5318 if (cnt == null) {
5319 r.conProviders.put(cpr, new Integer(1));
5320 } else {
5321 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 cpr.clients.add(r);
5324 } else {
5325 cpr.externals++;
5326 }
5327 }
5328 }
5329
5330 // Wait for the provider to be published...
5331 synchronized (cpr) {
5332 while (cpr.provider == null) {
5333 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005334 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 + cpi.applicationInfo.packageName + "/"
5336 + cpi.applicationInfo.uid + " for provider "
5337 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005338 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005339 cpi.applicationInfo.packageName,
5340 cpi.applicationInfo.uid, name);
5341 return null;
5342 }
5343 try {
5344 cpr.wait();
5345 } catch (InterruptedException ex) {
5346 }
5347 }
5348 }
5349 return cpr;
5350 }
5351
5352 public final ContentProviderHolder getContentProvider(
5353 IApplicationThread caller, String name) {
5354 if (caller == null) {
5355 String msg = "null IApplicationThread when getting content provider "
5356 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005357 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 throw new SecurityException(msg);
5359 }
5360
5361 return getContentProviderImpl(caller, name);
5362 }
5363
5364 private ContentProviderHolder getContentProviderExternal(String name) {
5365 return getContentProviderImpl(null, name);
5366 }
5367
5368 /**
5369 * Drop a content provider from a ProcessRecord's bookkeeping
5370 * @param cpr
5371 */
5372 public void removeContentProvider(IApplicationThread caller, String name) {
5373 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005374 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005376 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005377 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005378 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 return;
5380 }
5381 final ProcessRecord r = getRecordForAppLocked(caller);
5382 if (r == null) {
5383 throw new SecurityException(
5384 "Unable to find app for caller " + caller +
5385 " when removing content provider " + name);
5386 }
5387 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005388 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005389 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005390 + r.info.processName + " from process "
5391 + localCpr.appInfo.processName);
5392 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005393 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005394 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005395 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 return;
5397 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005398 Integer cnt = r.conProviders.get(localCpr);
5399 if (cnt == null || cnt.intValue() <= 1) {
5400 localCpr.clients.remove(r);
5401 r.conProviders.remove(localCpr);
5402 } else {
5403 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005405 }
5406 updateOomAdjLocked();
5407 }
5408 }
5409
5410 private void removeContentProviderExternal(String name) {
5411 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005412 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005413 if(cpr == null) {
5414 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005415 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 return;
5417 }
5418
5419 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005420 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 localCpr.externals--;
5422 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005423 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 }
5425 updateOomAdjLocked();
5426 }
5427 }
5428
5429 public final void publishContentProviders(IApplicationThread caller,
5430 List<ContentProviderHolder> providers) {
5431 if (providers == null) {
5432 return;
5433 }
5434
5435 synchronized(this) {
5436 final ProcessRecord r = getRecordForAppLocked(caller);
5437 if (r == null) {
5438 throw new SecurityException(
5439 "Unable to find app for caller " + caller
5440 + " (pid=" + Binder.getCallingPid()
5441 + ") when publishing content providers");
5442 }
5443
5444 final long origId = Binder.clearCallingIdentity();
5445
5446 final int N = providers.size();
5447 for (int i=0; i<N; i++) {
5448 ContentProviderHolder src = providers.get(i);
5449 if (src == null || src.info == null || src.provider == null) {
5450 continue;
5451 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005452 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 if (dst != null) {
5454 mProvidersByClass.put(dst.info.name, dst);
5455 String names[] = dst.info.authority.split(";");
5456 for (int j = 0; j < names.length; j++) {
5457 mProvidersByName.put(names[j], dst);
5458 }
5459
5460 int NL = mLaunchingProviders.size();
5461 int j;
5462 for (j=0; j<NL; j++) {
5463 if (mLaunchingProviders.get(j) == dst) {
5464 mLaunchingProviders.remove(j);
5465 j--;
5466 NL--;
5467 }
5468 }
5469 synchronized (dst) {
5470 dst.provider = src.provider;
5471 dst.app = r;
5472 dst.notifyAll();
5473 }
5474 updateOomAdjLocked(r);
5475 }
5476 }
5477
5478 Binder.restoreCallingIdentity(origId);
5479 }
5480 }
5481
5482 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005483 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005484 synchronized (mSelf) {
5485 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5486 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005487 if (providers != null) {
5488 for (int i=providers.size()-1; i>=0; i--) {
5489 ProviderInfo pi = (ProviderInfo)providers.get(i);
5490 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5491 Slog.w(TAG, "Not installing system proc provider " + pi.name
5492 + ": not system .apk");
5493 providers.remove(i);
5494 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005495 }
5496 }
5497 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005498 if (providers != null) {
5499 mSystemThread.installSystemProviders(providers);
5500 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 }
5502
5503 // =========================================================
5504 // GLOBAL MANAGEMENT
5505 // =========================================================
5506
5507 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5508 ApplicationInfo info, String customProcess) {
5509 String proc = customProcess != null ? customProcess : info.processName;
5510 BatteryStatsImpl.Uid.Proc ps = null;
5511 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5512 synchronized (stats) {
5513 ps = stats.getProcessStatsLocked(info.uid, proc);
5514 }
5515 return new ProcessRecord(ps, thread, info, proc);
5516 }
5517
5518 final ProcessRecord addAppLocked(ApplicationInfo info) {
5519 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5520
5521 if (app == null) {
5522 app = newProcessRecordLocked(null, info, null);
5523 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005524 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005525 }
5526
5527 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5528 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5529 app.persistent = true;
5530 app.maxAdj = CORE_SERVER_ADJ;
5531 }
5532 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5533 mPersistentStartingProcesses.add(app);
5534 startProcessLocked(app, "added application", app.processName);
5535 }
5536
5537 return app;
5538 }
5539
5540 public void unhandledBack() {
5541 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5542 "unhandledBack()");
5543
5544 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005545 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005546 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005547 TAG, "Performing unhandledBack(): stack size = " + count);
5548 if (count > 1) {
5549 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005550 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5552 Binder.restoreCallingIdentity(origId);
5553 }
5554 }
5555 }
5556
5557 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5558 String name = uri.getAuthority();
5559 ContentProviderHolder cph = getContentProviderExternal(name);
5560 ParcelFileDescriptor pfd = null;
5561 if (cph != null) {
5562 // We record the binder invoker's uid in thread-local storage before
5563 // going to the content provider to open the file. Later, in the code
5564 // that handles all permissions checks, we look for this uid and use
5565 // that rather than the Activity Manager's own uid. The effect is that
5566 // we do the check against the caller's permissions even though it looks
5567 // to the content provider like the Activity Manager itself is making
5568 // the request.
5569 sCallerIdentity.set(new Identity(
5570 Binder.getCallingPid(), Binder.getCallingUid()));
5571 try {
5572 pfd = cph.provider.openFile(uri, "r");
5573 } catch (FileNotFoundException e) {
5574 // do nothing; pfd will be returned null
5575 } finally {
5576 // Ensure that whatever happens, we clean up the identity state
5577 sCallerIdentity.remove();
5578 }
5579
5580 // We've got the fd now, so we're done with the provider.
5581 removeContentProviderExternal(name);
5582 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005583 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005584 }
5585 return pfd;
5586 }
5587
5588 public void goingToSleep() {
5589 synchronized(this) {
5590 mSleeping = true;
5591 mWindowManager.setEventDispatching(false);
5592
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005593 if (mMainStack.mResumedActivity != null) {
5594 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005596 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005598
5599 // Initialize the wake times of all processes.
5600 checkExcessiveWakeLocksLocked(false);
5601 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5602 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5603 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005604 }
5605 }
5606
Dianne Hackborn55280a92009-05-07 15:53:46 -07005607 public boolean shutdown(int timeout) {
5608 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5609 != PackageManager.PERMISSION_GRANTED) {
5610 throw new SecurityException("Requires permission "
5611 + android.Manifest.permission.SHUTDOWN);
5612 }
5613
5614 boolean timedout = false;
5615
5616 synchronized(this) {
5617 mShuttingDown = true;
5618 mWindowManager.setEventDispatching(false);
5619
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005620 if (mMainStack.mResumedActivity != null) {
5621 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005622 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005623 while (mMainStack.mResumedActivity != null
5624 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005625 long delay = endTime - System.currentTimeMillis();
5626 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005627 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005628 timedout = true;
5629 break;
5630 }
5631 try {
5632 this.wait();
5633 } catch (InterruptedException e) {
5634 }
5635 }
5636 }
5637 }
5638
5639 mUsageStatsService.shutdown();
5640 mBatteryStatsService.shutdown();
5641
5642 return timedout;
5643 }
5644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 public void wakingUp() {
5646 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005647 if (mMainStack.mGoingToSleep.isHeld()) {
5648 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 }
5650 mWindowManager.setEventDispatching(true);
5651 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005652 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005653 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005654 }
5655 }
5656
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005657 public void stopAppSwitches() {
5658 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5659 != PackageManager.PERMISSION_GRANTED) {
5660 throw new SecurityException("Requires permission "
5661 + android.Manifest.permission.STOP_APP_SWITCHES);
5662 }
5663
5664 synchronized(this) {
5665 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5666 + APP_SWITCH_DELAY_TIME;
5667 mDidAppSwitch = false;
5668 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5669 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5670 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5671 }
5672 }
5673
5674 public void resumeAppSwitches() {
5675 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5676 != PackageManager.PERMISSION_GRANTED) {
5677 throw new SecurityException("Requires permission "
5678 + android.Manifest.permission.STOP_APP_SWITCHES);
5679 }
5680
5681 synchronized(this) {
5682 // Note that we don't execute any pending app switches... we will
5683 // let those wait until either the timeout, or the next start
5684 // activity request.
5685 mAppSwitchesAllowedTime = 0;
5686 }
5687 }
5688
5689 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5690 String name) {
5691 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5692 return true;
5693 }
5694
5695 final int perm = checkComponentPermission(
5696 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5697 callingUid, -1);
5698 if (perm == PackageManager.PERMISSION_GRANTED) {
5699 return true;
5700 }
5701
Joe Onorato8a9b2202010-02-26 18:56:32 -08005702 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005703 return false;
5704 }
5705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005706 public void setDebugApp(String packageName, boolean waitForDebugger,
5707 boolean persistent) {
5708 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5709 "setDebugApp()");
5710
5711 // Note that this is not really thread safe if there are multiple
5712 // callers into it at the same time, but that's not a situation we
5713 // care about.
5714 if (persistent) {
5715 final ContentResolver resolver = mContext.getContentResolver();
5716 Settings.System.putString(
5717 resolver, Settings.System.DEBUG_APP,
5718 packageName);
5719 Settings.System.putInt(
5720 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5721 waitForDebugger ? 1 : 0);
5722 }
5723
5724 synchronized (this) {
5725 if (!persistent) {
5726 mOrigDebugApp = mDebugApp;
5727 mOrigWaitForDebugger = mWaitForDebugger;
5728 }
5729 mDebugApp = packageName;
5730 mWaitForDebugger = waitForDebugger;
5731 mDebugTransient = !persistent;
5732 if (packageName != null) {
5733 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005734 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005735 Binder.restoreCallingIdentity(origId);
5736 }
5737 }
5738 }
5739
5740 public void setAlwaysFinish(boolean enabled) {
5741 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5742 "setAlwaysFinish()");
5743
5744 Settings.System.putInt(
5745 mContext.getContentResolver(),
5746 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5747
5748 synchronized (this) {
5749 mAlwaysFinishActivities = enabled;
5750 }
5751 }
5752
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005753 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005755 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005756 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005757 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 }
5759 }
5760
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005761 public boolean isUserAMonkey() {
5762 // For now the fact that there is a controller implies
5763 // we have a monkey.
5764 synchronized (this) {
5765 return mController != null;
5766 }
5767 }
5768
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005769 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005770 synchronized (this) {
5771 mWatchers.register(watcher);
5772 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005773 }
5774
5775 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005776 synchronized (this) {
5777 mWatchers.unregister(watcher);
5778 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005779 }
5780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 public final void enterSafeMode() {
5782 synchronized(this) {
5783 // It only makes sense to do this before the system is ready
5784 // and started launching other packages.
5785 if (!mSystemReady) {
5786 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005787 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005788 } catch (RemoteException e) {
5789 }
5790
5791 View v = LayoutInflater.from(mContext).inflate(
5792 com.android.internal.R.layout.safe_mode, null);
5793 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5794 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5795 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5796 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5797 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5798 lp.format = v.getBackground().getOpacity();
5799 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5800 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5801 ((WindowManager)mContext.getSystemService(
5802 Context.WINDOW_SERVICE)).addView(v, lp);
5803 }
5804 }
5805 }
5806
5807 public void noteWakeupAlarm(IIntentSender sender) {
5808 if (!(sender instanceof PendingIntentRecord)) {
5809 return;
5810 }
5811 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5812 synchronized (stats) {
5813 if (mBatteryStatsService.isOnBattery()) {
5814 mBatteryStatsService.enforceCallingPermission();
5815 PendingIntentRecord rec = (PendingIntentRecord)sender;
5816 int MY_UID = Binder.getCallingUid();
5817 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5818 BatteryStatsImpl.Uid.Pkg pkg =
5819 stats.getPackageStatsLocked(uid, rec.key.packageName);
5820 pkg.incWakeupsLocked();
5821 }
5822 }
5823 }
5824
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005825 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005826 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005827 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005829 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 // XXX Note: don't acquire main activity lock here, because the window
5831 // manager calls in with its locks held.
5832
5833 boolean killed = false;
5834 synchronized (mPidsSelfLocked) {
5835 int[] types = new int[pids.length];
5836 int worstType = 0;
5837 for (int i=0; i<pids.length; i++) {
5838 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5839 if (proc != null) {
5840 int type = proc.setAdj;
5841 types[i] = type;
5842 if (type > worstType) {
5843 worstType = type;
5844 }
5845 }
5846 }
5847
5848 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5849 // then constrain it so we will kill all hidden procs.
5850 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5851 worstType = HIDDEN_APP_MIN_ADJ;
5852 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005853 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005854 for (int i=0; i<pids.length; i++) {
5855 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5856 if (proc == null) {
5857 continue;
5858 }
5859 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005860 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005861 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005862 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5863 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005864 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005865 proc.killedBackground = true;
5866 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005867 }
5868 }
5869 }
5870 return killed;
5871 }
5872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 public final void startRunning(String pkg, String cls, String action,
5874 String data) {
5875 synchronized(this) {
5876 if (mStartRunning) {
5877 return;
5878 }
5879 mStartRunning = true;
5880 mTopComponent = pkg != null && cls != null
5881 ? new ComponentName(pkg, cls) : null;
5882 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5883 mTopData = data;
5884 if (!mSystemReady) {
5885 return;
5886 }
5887 }
5888
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005889 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005890 }
5891
5892 private void retrieveSettings() {
5893 final ContentResolver resolver = mContext.getContentResolver();
5894 String debugApp = Settings.System.getString(
5895 resolver, Settings.System.DEBUG_APP);
5896 boolean waitForDebugger = Settings.System.getInt(
5897 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5898 boolean alwaysFinishActivities = Settings.System.getInt(
5899 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5900
5901 Configuration configuration = new Configuration();
5902 Settings.System.getConfiguration(resolver, configuration);
5903
5904 synchronized (this) {
5905 mDebugApp = mOrigDebugApp = debugApp;
5906 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5907 mAlwaysFinishActivities = alwaysFinishActivities;
5908 // This happens before any activities are started, so we can
5909 // change mConfiguration in-place.
5910 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005911 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005912 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005913 }
5914 }
5915
5916 public boolean testIsSystemReady() {
5917 // no need to synchronize(this) just to read & return the value
5918 return mSystemReady;
5919 }
5920
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005921 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005922 // In the simulator, startRunning will never have been called, which
5923 // normally sets a few crucial variables. Do it here instead.
5924 if (!Process.supportsProcesses()) {
5925 mStartRunning = true;
5926 mTopAction = Intent.ACTION_MAIN;
5927 }
5928
5929 synchronized(this) {
5930 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005931 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 return;
5933 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005934
5935 // Check to see if there are any update receivers to run.
5936 if (!mDidUpdate) {
5937 if (mWaitingUpdate) {
5938 return;
5939 }
5940 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5941 List<ResolveInfo> ris = null;
5942 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005943 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005944 intent, null, 0);
5945 } catch (RemoteException e) {
5946 }
5947 if (ris != null) {
5948 for (int i=ris.size()-1; i>=0; i--) {
5949 if ((ris.get(i).activityInfo.applicationInfo.flags
5950 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5951 ris.remove(i);
5952 }
5953 }
5954 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5955 for (int i=0; i<ris.size(); i++) {
5956 ActivityInfo ai = ris.get(i).activityInfo;
5957 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5958 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005959 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005960 finisher = new IIntentReceiver.Stub() {
5961 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005962 String data, Bundle extras, boolean ordered,
5963 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005964 throws RemoteException {
5965 synchronized (ActivityManagerService.this) {
5966 mDidUpdate = true;
5967 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005968 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005969 }
5970 };
5971 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005972 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005973 broadcastIntentLocked(null, null, intent, null, finisher,
5974 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005975 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005976 mWaitingUpdate = true;
5977 }
5978 }
5979 }
5980 if (mWaitingUpdate) {
5981 return;
5982 }
5983 mDidUpdate = true;
5984 }
5985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005986 mSystemReady = true;
5987 if (!mStartRunning) {
5988 return;
5989 }
5990 }
5991
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005992 ArrayList<ProcessRecord> procsToKill = null;
5993 synchronized(mPidsSelfLocked) {
5994 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5995 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5996 if (!isAllowedWhileBooting(proc.info)){
5997 if (procsToKill == null) {
5998 procsToKill = new ArrayList<ProcessRecord>();
5999 }
6000 procsToKill.add(proc);
6001 }
6002 }
6003 }
6004
6005 if (procsToKill != null) {
6006 synchronized(this) {
6007 for (int i=procsToKill.size()-1; i>=0; i--) {
6008 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006009 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006010 removeProcessLocked(proc, true);
6011 }
6012 }
6013 }
6014
Joe Onorato8a9b2202010-02-26 18:56:32 -08006015 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006016 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017 SystemClock.uptimeMillis());
6018
6019 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006020 // Make sure we have no pre-ready processes sitting around.
6021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6023 ResolveInfo ri = mContext.getPackageManager()
6024 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006025 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006026 CharSequence errorMsg = null;
6027 if (ri != null) {
6028 ActivityInfo ai = ri.activityInfo;
6029 ApplicationInfo app = ai.applicationInfo;
6030 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6031 mTopAction = Intent.ACTION_FACTORY_TEST;
6032 mTopData = null;
6033 mTopComponent = new ComponentName(app.packageName,
6034 ai.name);
6035 } else {
6036 errorMsg = mContext.getResources().getText(
6037 com.android.internal.R.string.factorytest_not_system);
6038 }
6039 } else {
6040 errorMsg = mContext.getResources().getText(
6041 com.android.internal.R.string.factorytest_no_action);
6042 }
6043 if (errorMsg != null) {
6044 mTopAction = null;
6045 mTopData = null;
6046 mTopComponent = null;
6047 Message msg = Message.obtain();
6048 msg.what = SHOW_FACTORY_ERROR_MSG;
6049 msg.getData().putCharSequence("msg", errorMsg);
6050 mHandler.sendMessage(msg);
6051 }
6052 }
6053 }
6054
6055 retrieveSettings();
6056
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006057 if (goingCallback != null) goingCallback.run();
6058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006059 synchronized (this) {
6060 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6061 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006062 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006063 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006064 if (apps != null) {
6065 int N = apps.size();
6066 int i;
6067 for (i=0; i<N; i++) {
6068 ApplicationInfo info
6069 = (ApplicationInfo)apps.get(i);
6070 if (info != null &&
6071 !info.packageName.equals("android")) {
6072 addAppLocked(info);
6073 }
6074 }
6075 }
6076 } catch (RemoteException ex) {
6077 // pm is in same process, this will never happen.
6078 }
6079 }
6080
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006081 // Start up initial activity.
6082 mBooting = true;
6083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006085 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 Message msg = Message.obtain();
6087 msg.what = SHOW_UID_ERROR_MSG;
6088 mHandler.sendMessage(msg);
6089 }
6090 } catch (RemoteException e) {
6091 }
6092
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006093 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006094 }
6095 }
6096
Dan Egnorb7f03672009-12-09 16:22:32 -08006097 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006098 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006099 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006100 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006101 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 startAppProblemLocked(app);
6103 app.stopFreezingAllLocked();
6104 return handleAppCrashLocked(app);
6105 }
6106
Dan Egnorb7f03672009-12-09 16:22:32 -08006107 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006108 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006109 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006110 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006111 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6112 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006113 startAppProblemLocked(app);
6114 app.stopFreezingAllLocked();
6115 }
6116
6117 /**
6118 * Generate a process error record, suitable for attachment to a ProcessRecord.
6119 *
6120 * @param app The ProcessRecord in which the error occurred.
6121 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6122 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006123 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006124 * @param shortMsg Short message describing the crash.
6125 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006126 * @param stackTrace Full crash stack trace, may be null.
6127 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006128 * @return Returns a fully-formed AppErrorStateInfo record.
6129 */
6130 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006131 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006132 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006134 report.condition = condition;
6135 report.processName = app.processName;
6136 report.pid = app.pid;
6137 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006138 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006139 report.shortMsg = shortMsg;
6140 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006141 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006142
6143 return report;
6144 }
6145
Dan Egnor42471dd2010-01-07 17:25:22 -08006146 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006147 synchronized (this) {
6148 app.crashing = false;
6149 app.crashingReport = null;
6150 app.notResponding = false;
6151 app.notRespondingReport = null;
6152 if (app.anrDialog == fromDialog) {
6153 app.anrDialog = null;
6154 }
6155 if (app.waitDialog == fromDialog) {
6156 app.waitDialog = null;
6157 }
6158 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006159 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006160 Slog.i(ActivityManagerService.TAG, "Killing "
6161 + app.processName + " (pid=" + app.pid + "): user's request");
6162 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6163 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006164 Process.killProcess(app.pid);
6165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006166 }
6167 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006168
Dan Egnorb7f03672009-12-09 16:22:32 -08006169 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006170 long now = SystemClock.uptimeMillis();
6171
6172 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6173 app.info.uid);
6174 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6175 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006176 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006177 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006178 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006179 app.info.processName, app.info.uid);
6180 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006181 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6182 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006183 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006184 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006185 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006186 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006187 }
6188 }
6189 if (!app.persistent) {
6190 // We don't want to start this process again until the user
6191 // explicitly does so... but for persistent process, we really
6192 // need to keep it running. If a persistent process is actually
6193 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006194 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006195 app.info.processName);
6196 mBadProcesses.put(app.info.processName, app.info.uid, now);
6197 app.bad = true;
6198 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6199 app.removed = true;
6200 removeProcessLocked(app, false);
6201 return false;
6202 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006203 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006204 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006205 if (r.app == app) {
6206 // If the top running activity is from this crashing
6207 // process, then terminate it to avoid getting in a loop.
6208 Slog.w(TAG, " Force finishing activity "
6209 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006210 int index = mMainStack.indexOfTokenLocked(r);
6211 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006212 Activity.RESULT_CANCELED, null, "crashed");
6213 // Also terminate an activities below it that aren't yet
6214 // stopped, to avoid a situation where one will get
6215 // re-start our crashing activity once it gets resumed again.
6216 index--;
6217 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006218 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006219 if (r.state == ActivityState.RESUMED
6220 || r.state == ActivityState.PAUSING
6221 || r.state == ActivityState.PAUSED) {
6222 if (!r.isHomeActivity) {
6223 Slog.w(TAG, " Force finishing activity "
6224 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006225 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006226 Activity.RESULT_CANCELED, null, "crashed");
6227 }
6228 }
6229 }
6230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006231 }
6232
6233 // Bump up the crash count of any services currently running in the proc.
6234 if (app.services.size() != 0) {
6235 // Any services running in the application need to be placed
6236 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006237 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006238 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006239 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240 sr.crashCount++;
6241 }
6242 }
6243
6244 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6245 return true;
6246 }
6247
6248 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006249 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6250 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006251 skipCurrentReceiverLocked(app);
6252 }
6253
6254 void skipCurrentReceiverLocked(ProcessRecord app) {
6255 boolean reschedule = false;
6256 BroadcastRecord r = app.curReceiver;
6257 if (r != null) {
6258 // The current broadcast is waiting for this app's receiver
6259 // to be finished. Looks like that's not going to happen, so
6260 // let the broadcast continue.
6261 logBroadcastReceiverDiscard(r);
6262 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6263 r.resultExtras, r.resultAbort, true);
6264 reschedule = true;
6265 }
6266 r = mPendingBroadcast;
6267 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006268 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006269 "skip & discard pending app " + r);
6270 logBroadcastReceiverDiscard(r);
6271 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6272 r.resultExtras, r.resultAbort, true);
6273 reschedule = true;
6274 }
6275 if (reschedule) {
6276 scheduleBroadcastsLocked();
6277 }
6278 }
6279
Dan Egnor60d87622009-12-16 16:32:58 -08006280 /**
6281 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6282 * The application process will exit immediately after this call returns.
6283 * @param app object of the crashing app, null for the system server
6284 * @param crashInfo describing the exception
6285 */
6286 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6287 ProcessRecord r = findAppProcess(app);
6288
6289 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6290 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006291 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006292 crashInfo.exceptionClassName,
6293 crashInfo.exceptionMessage,
6294 crashInfo.throwFileName,
6295 crashInfo.throwLineNumber);
6296
Dan Egnor42471dd2010-01-07 17:25:22 -08006297 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006298
6299 crashApplication(r, crashInfo);
6300 }
6301
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006302 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006303 IBinder app,
6304 int violationMask,
6305 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006306 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006307
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006308 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006309 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006310 boolean logIt = true;
6311 synchronized (mAlreadyLoggedViolatedStacks) {
6312 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6313 logIt = false;
6314 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006315 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006316 // the relative pain numbers, without logging all
6317 // the stack traces repeatedly. We'd want to do
6318 // likewise in the client code, which also does
6319 // dup suppression, before the Binder call.
6320 } else {
6321 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6322 mAlreadyLoggedViolatedStacks.clear();
6323 }
6324 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6325 }
6326 }
6327 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006328 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006329 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006330 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006331
6332 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6333 AppErrorResult result = new AppErrorResult();
6334 synchronized (this) {
6335 final long origId = Binder.clearCallingIdentity();
6336
6337 Message msg = Message.obtain();
6338 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6339 HashMap<String, Object> data = new HashMap<String, Object>();
6340 data.put("result", result);
6341 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006342 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006343 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006344 msg.obj = data;
6345 mHandler.sendMessage(msg);
6346
6347 Binder.restoreCallingIdentity(origId);
6348 }
6349 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006350 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006351 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006352 }
6353
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006354 // Depending on the policy in effect, there could be a bunch of
6355 // these in quick succession so we try to batch these together to
6356 // minimize disk writes, number of dropbox entries, and maximize
6357 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006358 private void logStrictModeViolationToDropBox(
6359 ProcessRecord process,
6360 StrictMode.ViolationInfo info) {
6361 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006362 return;
6363 }
6364 final boolean isSystemApp = process == null ||
6365 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6366 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6367 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6368 final DropBoxManager dbox = (DropBoxManager)
6369 mContext.getSystemService(Context.DROPBOX_SERVICE);
6370
6371 // Exit early if the dropbox isn't configured to accept this report type.
6372 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6373
6374 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006375 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006376 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6377 synchronized (sb) {
6378 bufferWasEmpty = sb.length() == 0;
6379 appendDropBoxProcessHeaders(process, sb);
6380 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6381 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006382 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6383 if (info.violationNumThisLoop != 0) {
6384 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6385 }
6386 if (info != null && info.durationMillis != -1) {
6387 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006388 }
6389 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006390 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6391 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006392 }
6393 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006394
6395 // Only buffer up to ~64k. Various logging bits truncate
6396 // things at 128k.
6397 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006398 }
6399
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006400 // Flush immediately if the buffer's grown too large, or this
6401 // is a non-system app. Non-system apps are isolated with a
6402 // different tag & policy and not batched.
6403 //
6404 // Batching is useful during internal testing with
6405 // StrictMode settings turned up high. Without batching,
6406 // thousands of separate files could be created on boot.
6407 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006408 new Thread("Error dump: " + dropboxTag) {
6409 @Override
6410 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006411 String report;
6412 synchronized (sb) {
6413 report = sb.toString();
6414 sb.delete(0, sb.length());
6415 sb.trimToSize();
6416 }
6417 if (report.length() != 0) {
6418 dbox.addText(dropboxTag, report);
6419 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006420 }
6421 }.start();
6422 return;
6423 }
6424
6425 // System app batching:
6426 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006427 // An existing dropbox-writing thread is outstanding, so
6428 // we don't need to start it up. The existing thread will
6429 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006430 return;
6431 }
6432
6433 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6434 // (After this point, we shouldn't access AMS internal data structures.)
6435 new Thread("Error dump: " + dropboxTag) {
6436 @Override
6437 public void run() {
6438 // 5 second sleep to let stacks arrive and be batched together
6439 try {
6440 Thread.sleep(5000); // 5 seconds
6441 } catch (InterruptedException e) {}
6442
6443 String errorReport;
6444 synchronized (mStrictModeBuffer) {
6445 errorReport = mStrictModeBuffer.toString();
6446 if (errorReport.length() == 0) {
6447 return;
6448 }
6449 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6450 mStrictModeBuffer.trimToSize();
6451 }
6452 dbox.addText(dropboxTag, errorReport);
6453 }
6454 }.start();
6455 }
6456
Dan Egnor60d87622009-12-16 16:32:58 -08006457 /**
6458 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6459 * @param app object of the crashing app, null for the system server
6460 * @param tag reported by the caller
6461 * @param crashInfo describing the context of the error
6462 * @return true if the process should exit immediately (WTF is fatal)
6463 */
6464 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006465 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006466 ProcessRecord r = findAppProcess(app);
6467
6468 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6469 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006470 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006471 tag, crashInfo.exceptionMessage);
6472
Dan Egnor42471dd2010-01-07 17:25:22 -08006473 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006474
Doug Zongker43866e02010-01-07 12:09:54 -08006475 if (Settings.Secure.getInt(mContext.getContentResolver(),
6476 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006477 crashApplication(r, crashInfo);
6478 return true;
6479 } else {
6480 return false;
6481 }
6482 }
6483
6484 /**
6485 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6486 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6487 */
6488 private ProcessRecord findAppProcess(IBinder app) {
6489 if (app == null) {
6490 return null;
6491 }
6492
6493 synchronized (this) {
6494 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6495 final int NA = apps.size();
6496 for (int ia=0; ia<NA; ia++) {
6497 ProcessRecord p = apps.valueAt(ia);
6498 if (p.thread != null && p.thread.asBinder() == app) {
6499 return p;
6500 }
6501 }
6502 }
6503
Joe Onorato8a9b2202010-02-26 18:56:32 -08006504 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006505 return null;
6506 }
6507 }
6508
6509 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006510 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6511 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006512 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006513 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006514 if (process == null || process.pid == MY_PID) {
6515 sb.append("Process: system_server\n");
6516 } else {
6517 sb.append("Process: ").append(process.processName).append("\n");
6518 }
6519 if (process != null) {
6520 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006521 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006522 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6523 for (String pkg : process.pkgList) {
6524 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006525 try {
Dan Egnora455d192010-03-12 08:52:28 -08006526 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6527 if (pi != null) {
6528 sb.append(" v").append(pi.versionCode);
6529 if (pi.versionName != null) {
6530 sb.append(" (").append(pi.versionName).append(")");
6531 }
6532 }
6533 } catch (RemoteException e) {
6534 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006535 }
Dan Egnora455d192010-03-12 08:52:28 -08006536 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006537 }
Dan Egnora455d192010-03-12 08:52:28 -08006538 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006539 }
6540
6541 private static String processClass(ProcessRecord process) {
6542 if (process == null || process.pid == MY_PID) {
6543 return "system_server";
6544 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6545 return "system_app";
6546 } else {
6547 return "data_app";
6548 }
6549 }
6550
6551 /**
6552 * Write a description of an error (crash, WTF, ANR) to the drop box.
6553 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6554 * @param process which caused the error, null means the system server
6555 * @param activity which triggered the error, null if unknown
6556 * @param parent activity related to the error, null if unknown
6557 * @param subject line related to the error, null if absent
6558 * @param report in long form describing the error, null if absent
6559 * @param logFile to include in the report, null if none
6560 * @param crashInfo giving an application stack trace, null if absent
6561 */
6562 public void addErrorToDropBox(String eventType,
6563 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6564 final String report, final File logFile,
6565 final ApplicationErrorReport.CrashInfo crashInfo) {
6566 // NOTE -- this must never acquire the ActivityManagerService lock,
6567 // otherwise the watchdog may be prevented from resetting the system.
6568
6569 final String dropboxTag = processClass(process) + "_" + eventType;
6570 final DropBoxManager dbox = (DropBoxManager)
6571 mContext.getSystemService(Context.DROPBOX_SERVICE);
6572
6573 // Exit early if the dropbox isn't configured to accept this report type.
6574 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6575
6576 final StringBuilder sb = new StringBuilder(1024);
6577 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006578 if (activity != null) {
6579 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6580 }
6581 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6582 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6583 }
6584 if (parent != null && parent != activity) {
6585 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6586 }
6587 if (subject != null) {
6588 sb.append("Subject: ").append(subject).append("\n");
6589 }
6590 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6591 sb.append("\n");
6592
6593 // Do the rest in a worker thread to avoid blocking the caller on I/O
6594 // (After this point, we shouldn't access AMS internal data structures.)
6595 Thread worker = new Thread("Error dump: " + dropboxTag) {
6596 @Override
6597 public void run() {
6598 if (report != null) {
6599 sb.append(report);
6600 }
6601 if (logFile != null) {
6602 try {
6603 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6604 } catch (IOException e) {
6605 Slog.e(TAG, "Error reading " + logFile, e);
6606 }
6607 }
6608 if (crashInfo != null && crashInfo.stackTrace != null) {
6609 sb.append(crashInfo.stackTrace);
6610 }
6611
6612 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6613 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6614 if (lines > 0) {
6615 sb.append("\n");
6616
6617 // Merge several logcat streams, and take the last N lines
6618 InputStreamReader input = null;
6619 try {
6620 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6621 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6622 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6623
6624 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6625 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6626 input = new InputStreamReader(logcat.getInputStream());
6627
6628 int num;
6629 char[] buf = new char[8192];
6630 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6631 } catch (IOException e) {
6632 Slog.e(TAG, "Error running logcat", e);
6633 } finally {
6634 if (input != null) try { input.close(); } catch (IOException e) {}
6635 }
6636 }
6637
6638 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006639 }
Dan Egnora455d192010-03-12 08:52:28 -08006640 };
6641
6642 if (process == null || process.pid == MY_PID) {
6643 worker.run(); // We may be about to die -- need to run this synchronously
6644 } else {
6645 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006646 }
6647 }
6648
6649 /**
6650 * Bring up the "unexpected error" dialog box for a crashing app.
6651 * Deal with edge cases (intercepts from instrumented applications,
6652 * ActivityController, error intent receivers, that sort of thing).
6653 * @param r the application crashing
6654 * @param crashInfo describing the failure
6655 */
6656 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006657 long timeMillis = System.currentTimeMillis();
6658 String shortMsg = crashInfo.exceptionClassName;
6659 String longMsg = crashInfo.exceptionMessage;
6660 String stackTrace = crashInfo.stackTrace;
6661 if (shortMsg != null && longMsg != null) {
6662 longMsg = shortMsg + ": " + longMsg;
6663 } else if (shortMsg != null) {
6664 longMsg = shortMsg;
6665 }
6666
Dan Egnor60d87622009-12-16 16:32:58 -08006667 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006668 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006669 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006670 try {
6671 String name = r != null ? r.processName : null;
6672 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006673 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006674 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006675 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006676 + " at watcher's request");
6677 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006678 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006679 }
6680 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006681 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006682 }
6683 }
6684
6685 final long origId = Binder.clearCallingIdentity();
6686
6687 // If this process is running instrumentation, finish it.
6688 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006689 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006690 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006691 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6692 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 Bundle info = new Bundle();
6694 info.putString("shortMsg", shortMsg);
6695 info.putString("longMsg", longMsg);
6696 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6697 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006698 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 }
6700
Dan Egnor60d87622009-12-16 16:32:58 -08006701 // If we can't identify the process or it's already exceeded its crash quota,
6702 // quit right away without showing a crash dialog.
6703 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006704 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006705 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006706 }
6707
6708 Message msg = Message.obtain();
6709 msg.what = SHOW_ERROR_MSG;
6710 HashMap data = new HashMap();
6711 data.put("result", result);
6712 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006713 msg.obj = data;
6714 mHandler.sendMessage(msg);
6715
6716 Binder.restoreCallingIdentity(origId);
6717 }
6718
6719 int res = result.get();
6720
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006721 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006722 synchronized (this) {
6723 if (r != null) {
6724 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6725 SystemClock.uptimeMillis());
6726 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006727 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006728 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006729 }
6730 }
6731
6732 if (appErrorIntent != null) {
6733 try {
6734 mContext.startActivity(appErrorIntent);
6735 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006736 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006739 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006740
6741 Intent createAppErrorIntentLocked(ProcessRecord r,
6742 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6743 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006744 if (report == null) {
6745 return null;
6746 }
6747 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6748 result.setComponent(r.errorReportReceiver);
6749 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6750 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6751 return result;
6752 }
6753
Dan Egnorb7f03672009-12-09 16:22:32 -08006754 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6755 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006756 if (r.errorReportReceiver == null) {
6757 return null;
6758 }
6759
6760 if (!r.crashing && !r.notResponding) {
6761 return null;
6762 }
6763
Dan Egnorb7f03672009-12-09 16:22:32 -08006764 ApplicationErrorReport report = new ApplicationErrorReport();
6765 report.packageName = r.info.packageName;
6766 report.installerPackageName = r.errorReportReceiver.getPackageName();
6767 report.processName = r.processName;
6768 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006769 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006770
Dan Egnorb7f03672009-12-09 16:22:32 -08006771 if (r.crashing) {
6772 report.type = ApplicationErrorReport.TYPE_CRASH;
6773 report.crashInfo = crashInfo;
6774 } else if (r.notResponding) {
6775 report.type = ApplicationErrorReport.TYPE_ANR;
6776 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006777
Dan Egnorb7f03672009-12-09 16:22:32 -08006778 report.anrInfo.activity = r.notRespondingReport.tag;
6779 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6780 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006781 }
6782
Dan Egnorb7f03672009-12-09 16:22:32 -08006783 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006784 }
6785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6787 // assume our apps are happy - lazy create the list
6788 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6789
6790 synchronized (this) {
6791
6792 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006793 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6794 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6796 // This one's in trouble, so we'll generate a report for it
6797 // crashes are higher priority (in case there's a crash *and* an anr)
6798 ActivityManager.ProcessErrorStateInfo report = null;
6799 if (app.crashing) {
6800 report = app.crashingReport;
6801 } else if (app.notResponding) {
6802 report = app.notRespondingReport;
6803 }
6804
6805 if (report != null) {
6806 if (errList == null) {
6807 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6808 }
6809 errList.add(report);
6810 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006811 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006812 " crashing = " + app.crashing +
6813 " notResponding = " + app.notResponding);
6814 }
6815 }
6816 }
6817 }
6818
6819 return errList;
6820 }
6821
6822 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6823 // Lazy instantiation of list
6824 List<ActivityManager.RunningAppProcessInfo> runList = null;
6825 synchronized (this) {
6826 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006827 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6828 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6830 // Generate process state info for running application
6831 ActivityManager.RunningAppProcessInfo currApp =
6832 new ActivityManager.RunningAppProcessInfo(app.processName,
6833 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006834 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006835 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07006836 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006837 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006838 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006839 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006840 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6841 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6842 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006843 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6844 } else if (adj >= HOME_APP_ADJ) {
6845 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6846 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006847 } else if (adj >= SECONDARY_SERVER_ADJ) {
6848 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006849 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6850 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6851 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6852 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006853 } else if (adj >= VISIBLE_APP_ADJ) {
6854 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6855 } else {
6856 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6857 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006858 currApp.importanceReasonCode = app.adjTypeCode;
6859 if (app.adjSource instanceof ProcessRecord) {
6860 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006861 } else if (app.adjSource instanceof ActivityRecord) {
6862 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006863 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6864 }
6865 if (app.adjTarget instanceof ComponentName) {
6866 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6867 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006868 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006869 // + " lru=" + currApp.lru);
6870 if (runList == null) {
6871 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6872 }
6873 runList.add(currApp);
6874 }
6875 }
6876 }
6877 return runList;
6878 }
6879
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006880 public List<ApplicationInfo> getRunningExternalApplications() {
6881 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6882 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6883 if (runningApps != null && runningApps.size() > 0) {
6884 Set<String> extList = new HashSet<String>();
6885 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6886 if (app.pkgList != null) {
6887 for (String pkg : app.pkgList) {
6888 extList.add(pkg);
6889 }
6890 }
6891 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006892 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006893 for (String pkg : extList) {
6894 try {
6895 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6896 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6897 retList.add(info);
6898 }
6899 } catch (RemoteException e) {
6900 }
6901 }
6902 }
6903 return retList;
6904 }
6905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906 @Override
6907 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006908 if (checkCallingPermission(android.Manifest.permission.DUMP)
6909 != PackageManager.PERMISSION_GRANTED) {
6910 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6911 + Binder.getCallingPid()
6912 + ", uid=" + Binder.getCallingUid()
6913 + " without permission "
6914 + android.Manifest.permission.DUMP);
6915 return;
6916 }
6917
6918 boolean dumpAll = false;
6919
6920 int opti = 0;
6921 while (opti < args.length) {
6922 String opt = args[opti];
6923 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6924 break;
6925 }
6926 opti++;
6927 if ("-a".equals(opt)) {
6928 dumpAll = true;
6929 } else if ("-h".equals(opt)) {
6930 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006931 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006932 pw.println(" cmd may be one of:");
6933 pw.println(" activities: activity stack state");
6934 pw.println(" broadcasts: broadcast state");
6935 pw.println(" intents: pending intent state");
6936 pw.println(" processes: process state");
6937 pw.println(" providers: content provider state");
6938 pw.println(" services: service state");
6939 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006940 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006941 } else {
6942 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006943 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006944 }
6945
6946 // Is the caller requesting to dump a particular piece of data?
6947 if (opti < args.length) {
6948 String cmd = args[opti];
6949 opti++;
6950 if ("activities".equals(cmd) || "a".equals(cmd)) {
6951 synchronized (this) {
6952 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006953 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006954 return;
6955 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6956 synchronized (this) {
6957 dumpBroadcastsLocked(fd, pw, args, opti, true);
6958 }
6959 return;
6960 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6961 synchronized (this) {
6962 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6963 }
6964 return;
6965 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6966 synchronized (this) {
6967 dumpProcessesLocked(fd, pw, args, opti, true);
6968 }
6969 return;
6970 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6971 synchronized (this) {
6972 dumpProvidersLocked(fd, pw, args, opti, true);
6973 }
6974 return;
6975 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006976 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006977 return;
6978 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6979 synchronized (this) {
6980 dumpServicesLocked(fd, pw, args, opti, true);
6981 }
6982 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006983 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006984 }
6985
6986 // No piece of data specified, dump everything.
6987 synchronized (this) {
6988 boolean needSep;
6989 if (dumpAll) {
6990 pw.println("Providers in Current Activity Manager State:");
6991 }
6992 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6993 if (needSep) {
6994 pw.println(" ");
6995 }
6996 if (dumpAll) {
6997 pw.println("-------------------------------------------------------------------------------");
6998 pw.println("Broadcasts in Current Activity Manager State:");
6999 }
7000 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7001 if (needSep) {
7002 pw.println(" ");
7003 }
7004 if (dumpAll) {
7005 pw.println("-------------------------------------------------------------------------------");
7006 pw.println("Services in Current Activity Manager State:");
7007 }
7008 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7009 if (needSep) {
7010 pw.println(" ");
7011 }
7012 if (dumpAll) {
7013 pw.println("-------------------------------------------------------------------------------");
7014 pw.println("PendingIntents in Current Activity Manager State:");
7015 }
7016 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7017 if (needSep) {
7018 pw.println(" ");
7019 }
7020 if (dumpAll) {
7021 pw.println("-------------------------------------------------------------------------------");
7022 pw.println("Activities in Current Activity Manager State:");
7023 }
7024 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7025 if (needSep) {
7026 pw.println(" ");
7027 }
7028 if (dumpAll) {
7029 pw.println("-------------------------------------------------------------------------------");
7030 pw.println("Processes in Current Activity Manager State:");
7031 }
7032 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7033 }
7034 }
7035
7036 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7037 int opti, boolean dumpAll, boolean needHeader) {
7038 if (needHeader) {
7039 pw.println(" Activity stack:");
7040 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007041 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007042 pw.println(" ");
7043 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007044 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7045 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007047 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007048 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007049 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007050 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007051 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007052 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007053 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007054 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007055 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007056 pw.println(" ");
7057 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007058 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007061 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007062 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7063 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007064 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007065 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007067 if (dumpAll && mRecentTasks.size() > 0) {
7068 pw.println(" ");
7069 pw.println("Recent tasks in Current Activity Manager State:");
7070
7071 final int N = mRecentTasks.size();
7072 for (int i=0; i<N; i++) {
7073 TaskRecord tr = mRecentTasks.get(i);
7074 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7075 pw.println(tr);
7076 mRecentTasks.get(i).dump(pw, " ");
7077 }
7078 }
7079
7080 pw.println(" ");
7081 pw.println(" mCurTask: " + mCurTask);
7082
7083 return true;
7084 }
7085
7086 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7087 int opti, boolean dumpAll) {
7088 boolean needSep = false;
7089 int numPers = 0;
7090
7091 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7093 final int NA = procs.size();
7094 for (int ia=0; ia<NA; ia++) {
7095 if (!needSep) {
7096 pw.println(" All known processes:");
7097 needSep = true;
7098 }
7099 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007100 pw.print(r.persistent ? " *PERS*" : " *APP*");
7101 pw.print(" UID "); pw.print(procs.keyAt(ia));
7102 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007103 r.dump(pw, " ");
7104 if (r.persistent) {
7105 numPers++;
7106 }
7107 }
7108 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007109 }
7110
7111 if (mLruProcesses.size() > 0) {
7112 if (needSep) pw.println(" ");
7113 needSep = true;
7114 pw.println(" Running processes (most recent first):");
7115 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007116 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007117 needSep = true;
7118 }
7119
7120 synchronized (mPidsSelfLocked) {
7121 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007122 if (needSep) pw.println(" ");
7123 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007124 pw.println(" PID mappings:");
7125 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7126 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7127 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007128 }
7129 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007130 }
7131
7132 if (mForegroundProcesses.size() > 0) {
7133 if (needSep) pw.println(" ");
7134 needSep = true;
7135 pw.println(" Foreground Processes:");
7136 for (int i=0; i<mForegroundProcesses.size(); i++) {
7137 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7138 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007139 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007140 }
7141
7142 if (mPersistentStartingProcesses.size() > 0) {
7143 if (needSep) pw.println(" ");
7144 needSep = true;
7145 pw.println(" Persisent processes that are starting:");
7146 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
7147 "Starting Norm", "Restarting PERS", false);
7148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007150 if (mStartingProcesses.size() > 0) {
7151 if (needSep) pw.println(" ");
7152 needSep = true;
7153 pw.println(" Processes that are starting:");
7154 dumpProcessList(pw, this, mStartingProcesses, " ",
7155 "Starting Norm", "Starting PERS", false);
7156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007158 if (mRemovedProcesses.size() > 0) {
7159 if (needSep) pw.println(" ");
7160 needSep = true;
7161 pw.println(" Processes that are being removed:");
7162 dumpProcessList(pw, this, mRemovedProcesses, " ",
7163 "Removed Norm", "Removed PERS", false);
7164 }
7165
7166 if (mProcessesOnHold.size() > 0) {
7167 if (needSep) pw.println(" ");
7168 needSep = true;
7169 pw.println(" Processes that are on old until the system is ready:");
7170 dumpProcessList(pw, this, mProcessesOnHold, " ",
7171 "OnHold Norm", "OnHold PERS", false);
7172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007173
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007174 if (mProcessesToGc.size() > 0) {
7175 if (needSep) pw.println(" ");
7176 needSep = true;
7177 pw.println(" Processes that are waiting to GC:");
7178 long now = SystemClock.uptimeMillis();
7179 for (int i=0; i<mProcessesToGc.size(); i++) {
7180 ProcessRecord proc = mProcessesToGc.get(i);
7181 pw.print(" Process "); pw.println(proc);
7182 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7183 pw.print(", last gced=");
7184 pw.print(now-proc.lastRequestedGc);
7185 pw.print(" ms ago, last lowMem=");
7186 pw.print(now-proc.lastLowMemory);
7187 pw.println(" ms ago");
7188
7189 }
7190 }
7191
7192 if (mProcessCrashTimes.getMap().size() > 0) {
7193 if (needSep) pw.println(" ");
7194 needSep = true;
7195 pw.println(" Time since processes crashed:");
7196 long now = SystemClock.uptimeMillis();
7197 for (Map.Entry<String, SparseArray<Long>> procs
7198 : mProcessCrashTimes.getMap().entrySet()) {
7199 SparseArray<Long> uids = procs.getValue();
7200 final int N = uids.size();
7201 for (int i=0; i<N; i++) {
7202 pw.print(" Process "); pw.print(procs.getKey());
7203 pw.print(" uid "); pw.print(uids.keyAt(i));
7204 pw.print(": last crashed ");
7205 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007206 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007207 }
7208 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007209 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007210
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007211 if (mBadProcesses.getMap().size() > 0) {
7212 if (needSep) pw.println(" ");
7213 needSep = true;
7214 pw.println(" Bad processes:");
7215 for (Map.Entry<String, SparseArray<Long>> procs
7216 : mBadProcesses.getMap().entrySet()) {
7217 SparseArray<Long> uids = procs.getValue();
7218 final int N = uids.size();
7219 for (int i=0; i<N; i++) {
7220 pw.print(" Bad process "); pw.print(procs.getKey());
7221 pw.print(" uid "); pw.print(uids.keyAt(i));
7222 pw.print(": crashed at time ");
7223 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007224 }
7225 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007228 pw.println(" ");
7229 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007230 if (mHeavyWeightProcess != null) {
7231 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7232 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007233 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007234 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007235 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7236 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7237 || mOrigWaitForDebugger) {
7238 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7239 + " mDebugTransient=" + mDebugTransient
7240 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7241 }
7242 if (mAlwaysFinishActivities || mController != null) {
7243 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7244 + " mController=" + mController);
7245 }
7246 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007247 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007248 pw.println(" mStartRunning=" + mStartRunning
7249 + " mSystemReady=" + mSystemReady
7250 + " mBooting=" + mBooting
7251 + " mBooted=" + mBooted
7252 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007253 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7254 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007255 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007256 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007257
7258 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007259 }
7260
7261 /**
7262 * There are three ways to call this:
7263 * - no service specified: dump all the services
7264 * - a flattened component name that matched an existing service was specified as the
7265 * first arg: dump that one service
7266 * - the first arg isn't the flattened component name of an existing service:
7267 * dump all services whose component contains the first arg as a substring
7268 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007269 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7270 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 String[] newArgs;
7272 String componentNameString;
7273 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007274 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275 componentNameString = null;
7276 newArgs = EMPTY_STRING_ARRAY;
7277 r = null;
7278 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007279 componentNameString = args[opti];
7280 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007281 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007282 synchronized (this) {
7283 r = componentName != null ? mServices.get(componentName) : null;
7284 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007285 newArgs = new String[args.length - opti];
7286 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007287 }
7288
7289 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007290 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007291 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007292 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7293 synchronized (this) {
7294 for (ServiceRecord r1 : mServices.values()) {
7295 if (componentNameString == null
7296 || r1.name.flattenToString().contains(componentNameString)) {
7297 services.add(r1);
7298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 }
7300 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007301 for (int i=0; i<services.size(); i++) {
7302 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007304 }
7305 }
7306
7307 /**
7308 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7309 * there is a thread associated with the service.
7310 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007311 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7312 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007313 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007314 if (dumpAll) {
7315 synchronized (this) {
7316 pw.print(" * "); pw.println(r);
7317 r.dump(pw, " ");
7318 }
7319 pw.println("");
7320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321 if (r.app != null && r.app.thread != null) {
7322 try {
7323 // flush anything that is already in the PrintWriter since the thread is going
7324 // to write to the file descriptor directly
7325 pw.flush();
7326 r.app.thread.dumpService(fd, r, args);
7327 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007328 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 } catch (RemoteException e) {
7330 pw.println("got a RemoteException while dumping the service");
7331 }
7332 }
7333 }
7334
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007335 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7336 int opti, boolean dumpAll) {
7337 boolean needSep = false;
7338
7339 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007340 if (mRegisteredReceivers.size() > 0) {
7341 pw.println(" ");
7342 pw.println(" Registered Receivers:");
7343 Iterator it = mRegisteredReceivers.values().iterator();
7344 while (it.hasNext()) {
7345 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007346 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007347 r.dump(pw, " ");
7348 }
7349 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007351 pw.println(" ");
7352 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007353 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007354 needSep = true;
7355 }
7356
7357 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7358 || mPendingBroadcast != null) {
7359 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007361 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007363 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7364 pw.println(" Broadcast #" + i + ":");
7365 mParallelBroadcasts.get(i).dump(pw, " ");
7366 }
7367 if (mOrderedBroadcasts.size() > 0) {
7368 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007369 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007370 }
7371 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7372 pw.println(" Serialized Broadcast #" + i + ":");
7373 mOrderedBroadcasts.get(i).dump(pw, " ");
7374 }
7375 pw.println(" ");
7376 pw.println(" Pending broadcast:");
7377 if (mPendingBroadcast != null) {
7378 mPendingBroadcast.dump(pw, " ");
7379 } else {
7380 pw.println(" (null)");
7381 }
7382 needSep = true;
7383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007385 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007387 pw.println(" Historical broadcasts:");
7388 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7389 BroadcastRecord r = mBroadcastHistory[i];
7390 if (r == null) {
7391 break;
7392 }
7393 pw.println(" Historical Broadcast #" + i + ":");
7394 r.dump(pw, " ");
7395 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007396 needSep = true;
7397 }
7398
7399 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007400 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007401 pw.println(" Sticky broadcasts:");
7402 StringBuilder sb = new StringBuilder(128);
7403 for (Map.Entry<String, ArrayList<Intent>> ent
7404 : mStickyBroadcasts.entrySet()) {
7405 pw.print(" * Sticky action "); pw.print(ent.getKey());
7406 pw.println(":");
7407 ArrayList<Intent> intents = ent.getValue();
7408 final int N = intents.size();
7409 for (int i=0; i<N; i++) {
7410 sb.setLength(0);
7411 sb.append(" Intent: ");
7412 intents.get(i).toShortString(sb, true, false);
7413 pw.println(sb.toString());
7414 Bundle bundle = intents.get(i).getExtras();
7415 if (bundle != null) {
7416 pw.print(" ");
7417 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007418 }
7419 }
7420 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007421 needSep = true;
7422 }
7423
7424 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007425 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007426 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 pw.println(" mHandler:");
7428 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007429 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007431
7432 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 }
7434
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007435 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7436 int opti, boolean dumpAll) {
7437 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007439 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 if (mServices.size() > 0) {
7441 pw.println(" Active services:");
7442 Iterator<ServiceRecord> it = mServices.values().iterator();
7443 while (it.hasNext()) {
7444 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007445 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 r.dump(pw, " ");
7447 }
7448 needSep = true;
7449 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007451
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007452 if (mPendingServices.size() > 0) {
7453 if (needSep) pw.println(" ");
7454 pw.println(" Pending services:");
7455 for (int i=0; i<mPendingServices.size(); i++) {
7456 ServiceRecord r = mPendingServices.get(i);
7457 pw.print(" * Pending "); pw.println(r);
7458 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007459 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007460 needSep = true;
7461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007462
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007463 if (mRestartingServices.size() > 0) {
7464 if (needSep) pw.println(" ");
7465 pw.println(" Restarting services:");
7466 for (int i=0; i<mRestartingServices.size(); i++) {
7467 ServiceRecord r = mRestartingServices.get(i);
7468 pw.print(" * Restarting "); pw.println(r);
7469 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007471 needSep = true;
7472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007473
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007474 if (mStoppingServices.size() > 0) {
7475 if (needSep) pw.println(" ");
7476 pw.println(" Stopping services:");
7477 for (int i=0; i<mStoppingServices.size(); i++) {
7478 ServiceRecord r = mStoppingServices.get(i);
7479 pw.print(" * Stopping "); pw.println(r);
7480 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007482 needSep = true;
7483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007485 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007486 if (mServiceConnections.size() > 0) {
7487 if (needSep) pw.println(" ");
7488 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007489 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007490 = mServiceConnections.values().iterator();
7491 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007492 ArrayList<ConnectionRecord> r = it.next();
7493 for (int i=0; i<r.size(); i++) {
7494 pw.print(" * "); pw.println(r.get(i));
7495 r.get(i).dump(pw, " ");
7496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007497 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007498 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007499 }
7500 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007501
7502 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007503 }
7504
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007505 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7506 int opti, boolean dumpAll) {
7507 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007508
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007509 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007510 if (mProvidersByClass.size() > 0) {
7511 if (needSep) pw.println(" ");
7512 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007513 Iterator<Map.Entry<String, ContentProviderRecord>> it
7514 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007516 Map.Entry<String, ContentProviderRecord> e = it.next();
7517 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007518 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007519 r.dump(pw, " ");
7520 }
7521 needSep = true;
7522 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007523
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007524 if (mProvidersByName.size() > 0) {
7525 pw.println(" ");
7526 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007527 Iterator<Map.Entry<String, ContentProviderRecord>> it
7528 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007529 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007530 Map.Entry<String, ContentProviderRecord> e = it.next();
7531 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007532 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7533 pw.println(r);
7534 }
7535 needSep = true;
7536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007537 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007538
7539 if (mLaunchingProviders.size() > 0) {
7540 if (needSep) pw.println(" ");
7541 pw.println(" Launching content providers:");
7542 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7543 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7544 pw.println(mLaunchingProviders.get(i));
7545 }
7546 needSep = true;
7547 }
7548
7549 if (mGrantedUriPermissions.size() > 0) {
7550 pw.println();
7551 pw.println("Granted Uri Permissions:");
7552 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7553 int uid = mGrantedUriPermissions.keyAt(i);
7554 HashMap<Uri, UriPermission> perms
7555 = mGrantedUriPermissions.valueAt(i);
7556 pw.print(" * UID "); pw.print(uid);
7557 pw.println(" holds:");
7558 for (UriPermission perm : perms.values()) {
7559 pw.print(" "); pw.println(perm);
7560 perm.dump(pw, " ");
7561 }
7562 }
7563 needSep = true;
7564 }
7565
7566 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007567 }
7568
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007569 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7570 int opti, boolean dumpAll) {
7571 boolean needSep = false;
7572
7573 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007574 if (this.mIntentSenderRecords.size() > 0) {
7575 Iterator<WeakReference<PendingIntentRecord>> it
7576 = mIntentSenderRecords.values().iterator();
7577 while (it.hasNext()) {
7578 WeakReference<PendingIntentRecord> ref = it.next();
7579 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007580 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007582 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 rec.dump(pw, " ");
7584 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007585 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 }
7587 }
7588 }
7589 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007590
7591 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592 }
7593
7594 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007595 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007596 TaskRecord lastTask = null;
7597 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007598 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007599 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007600 if (lastTask != r.task) {
7601 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007602 pw.print(prefix);
7603 pw.print(full ? "* " : " ");
7604 pw.println(lastTask);
7605 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007606 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007609 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7610 pw.print(" #"); pw.print(i); pw.print(": ");
7611 pw.println(r);
7612 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007613 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 }
7616 }
7617
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007618 private static String buildOomTag(String prefix, String space, int val, int base) {
7619 if (val == base) {
7620 if (space == null) return prefix;
7621 return prefix + " ";
7622 }
7623 return prefix + "+" + Integer.toString(val-base);
7624 }
7625
7626 private static final int dumpProcessList(PrintWriter pw,
7627 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 String prefix, String normalLabel, String persistentLabel,
7629 boolean inclOomAdj) {
7630 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007631 final int N = list.size()-1;
7632 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 ProcessRecord r = (ProcessRecord)list.get(i);
7634 if (false) {
7635 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7636 + " #" + i + ":");
7637 r.dump(pw, prefix + " ");
7638 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007639 String oomAdj;
7640 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007641 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007642 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007643 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7644 } else if (r.setAdj >= HOME_APP_ADJ) {
7645 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7646 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7647 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7648 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7649 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007650 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7651 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7652 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7653 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007654 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7655 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7656 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7657 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007658 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007659 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007660 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007661 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007662 } else {
7663 oomAdj = Integer.toString(r.setAdj);
7664 }
7665 String schedGroup;
7666 switch (r.setSchedGroup) {
7667 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7668 schedGroup = "B";
7669 break;
7670 case Process.THREAD_GROUP_DEFAULT:
7671 schedGroup = "F";
7672 break;
7673 default:
7674 schedGroup = Integer.toString(r.setSchedGroup);
7675 break;
7676 }
7677 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007679 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007680 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007681 pw.print(prefix);
7682 pw.print(" ");
7683 if (r.adjTarget instanceof ComponentName) {
7684 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7685 } else if (r.adjTarget != null) {
7686 pw.print(r.adjTarget.toString());
7687 } else {
7688 pw.print("{null}");
7689 }
7690 pw.print("<=");
7691 if (r.adjSource instanceof ProcessRecord) {
7692 pw.print("Proc{");
7693 pw.print(((ProcessRecord)r.adjSource).toShortString());
7694 pw.println("}");
7695 } else if (r.adjSource != null) {
7696 pw.println(r.adjSource.toString());
7697 } else {
7698 pw.println("{null}");
7699 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 } else {
7702 pw.println(String.format("%s%s #%2d: %s",
7703 prefix, (r.persistent ? persistentLabel : normalLabel),
7704 i, r.toString()));
7705 }
7706 if (r.persistent) {
7707 numPers++;
7708 }
7709 }
7710 return numPers;
7711 }
7712
Dianne Hackborn472ad872010-04-07 17:31:48 -07007713 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007715 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007716 long uptime = SystemClock.uptimeMillis();
7717 long realtime = SystemClock.elapsedRealtime();
7718
7719 if (isCheckinRequest) {
7720 // short checkin version
7721 pw.println(uptime + "," + realtime);
7722 pw.flush();
7723 } else {
7724 pw.println("Applications Memory Usage (kB):");
7725 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7726 }
7727 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7728 ProcessRecord r = (ProcessRecord)list.get(i);
7729 if (r.thread != null) {
7730 if (!isCheckinRequest) {
7731 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7732 pw.flush();
7733 }
7734 try {
7735 r.thread.asBinder().dump(fd, args);
7736 } catch (RemoteException e) {
7737 if (!isCheckinRequest) {
7738 pw.println("Got RemoteException!");
7739 pw.flush();
7740 }
7741 }
7742 }
7743 }
7744 }
7745
7746 /**
7747 * Searches array of arguments for the specified string
7748 * @param args array of argument strings
7749 * @param value value to search for
7750 * @return true if the value is contained in the array
7751 */
7752 private static boolean scanArgs(String[] args, String value) {
7753 if (args != null) {
7754 for (String arg : args) {
7755 if (value.equals(arg)) {
7756 return true;
7757 }
7758 }
7759 }
7760 return false;
7761 }
7762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007763 private final void killServicesLocked(ProcessRecord app,
7764 boolean allowRestart) {
7765 // Report disconnected services.
7766 if (false) {
7767 // XXX we are letting the client link to the service for
7768 // death notifications.
7769 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007770 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007772 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007773 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007774 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007775 = r.connections.values().iterator();
7776 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007777 ArrayList<ConnectionRecord> cl = jt.next();
7778 for (int i=0; i<cl.size(); i++) {
7779 ConnectionRecord c = cl.get(i);
7780 if (c.binding.client != app) {
7781 try {
7782 //c.conn.connected(r.className, null);
7783 } catch (Exception e) {
7784 // todo: this should be asynchronous!
7785 Slog.w(TAG, "Exception thrown disconnected servce "
7786 + r.shortName
7787 + " from app " + app.processName, e);
7788 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007789 }
7790 }
7791 }
7792 }
7793 }
7794 }
7795 }
7796
7797 // Clean up any connections this application has to other services.
7798 if (app.connections.size() > 0) {
7799 Iterator<ConnectionRecord> it = app.connections.iterator();
7800 while (it.hasNext()) {
7801 ConnectionRecord r = it.next();
7802 removeConnectionLocked(r, app, null);
7803 }
7804 }
7805 app.connections.clear();
7806
7807 if (app.services.size() != 0) {
7808 // Any services running in the application need to be placed
7809 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007810 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007812 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007813 synchronized (sr.stats.getBatteryStats()) {
7814 sr.stats.stopLaunchedLocked();
7815 }
7816 sr.app = null;
7817 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007818 if (mStoppingServices.remove(sr)) {
7819 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
7820 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007821
7822 boolean hasClients = sr.bindings.size() > 0;
7823 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007824 Iterator<IntentBindRecord> bindings
7825 = sr.bindings.values().iterator();
7826 while (bindings.hasNext()) {
7827 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007828 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007829 + ": shouldUnbind=" + b.hasBound);
7830 b.binder = null;
7831 b.requested = b.received = b.hasBound = false;
7832 }
7833 }
7834
7835 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007836 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007838 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 sr.crashCount, sr.shortName, app.pid);
7840 bringDownServiceLocked(sr, true);
7841 } else if (!allowRestart) {
7842 bringDownServiceLocked(sr, true);
7843 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007844 boolean canceled = scheduleServiceRestartLocked(sr, true);
7845
7846 // Should the service remain running? Note that in the
7847 // extreme case of so many attempts to deliver a command
7848 // that it failed, that we also will stop it here.
7849 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7850 if (sr.pendingStarts.size() == 0) {
7851 sr.startRequested = false;
7852 if (!hasClients) {
7853 // Whoops, no reason to restart!
7854 bringDownServiceLocked(sr, true);
7855 }
7856 }
7857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007858 }
7859 }
7860
7861 if (!allowRestart) {
7862 app.services.clear();
7863 }
7864 }
7865
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007866 // Make sure we have no more records on the stopping list.
7867 int i = mStoppingServices.size();
7868 while (i > 0) {
7869 i--;
7870 ServiceRecord sr = mStoppingServices.get(i);
7871 if (sr.app == app) {
7872 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007873 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007874 }
7875 }
7876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007877 app.executingServices.clear();
7878 }
7879
7880 private final void removeDyingProviderLocked(ProcessRecord proc,
7881 ContentProviderRecord cpr) {
7882 synchronized (cpr) {
7883 cpr.launchingApp = null;
7884 cpr.notifyAll();
7885 }
7886
7887 mProvidersByClass.remove(cpr.info.name);
7888 String names[] = cpr.info.authority.split(";");
7889 for (int j = 0; j < names.length; j++) {
7890 mProvidersByName.remove(names[j]);
7891 }
7892
7893 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7894 while (cit.hasNext()) {
7895 ProcessRecord capp = cit.next();
7896 if (!capp.persistent && capp.thread != null
7897 && capp.pid != 0
7898 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007899 Slog.i(TAG, "Kill " + capp.processName
7900 + " (pid " + capp.pid + "): provider " + cpr.info.name
7901 + " in dying process " + proc.processName);
7902 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7903 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904 Process.killProcess(capp.pid);
7905 }
7906 }
7907
7908 mLaunchingProviders.remove(cpr);
7909 }
7910
7911 /**
7912 * Main code for cleaning up a process when it has gone away. This is
7913 * called both as a result of the process dying, or directly when stopping
7914 * a process when running in single process mode.
7915 */
7916 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7917 boolean restarting, int index) {
7918 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007919 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007920 }
7921
Dianne Hackborn36124872009-10-08 16:22:03 -07007922 mProcessesToGc.remove(app);
7923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007924 // Dismiss any open dialogs.
7925 if (app.crashDialog != null) {
7926 app.crashDialog.dismiss();
7927 app.crashDialog = null;
7928 }
7929 if (app.anrDialog != null) {
7930 app.anrDialog.dismiss();
7931 app.anrDialog = null;
7932 }
7933 if (app.waitDialog != null) {
7934 app.waitDialog.dismiss();
7935 app.waitDialog = null;
7936 }
7937
7938 app.crashing = false;
7939 app.notResponding = false;
7940
7941 app.resetPackageList();
7942 app.thread = null;
7943 app.forcingToForeground = null;
7944 app.foregroundServices = false;
7945
7946 killServicesLocked(app, true);
7947
7948 boolean restart = false;
7949
7950 int NL = mLaunchingProviders.size();
7951
7952 // Remove published content providers.
7953 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007954 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007956 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957 cpr.provider = null;
7958 cpr.app = null;
7959
7960 // See if someone is waiting for this provider... in which
7961 // case we don't remove it, but just let it restart.
7962 int i = 0;
7963 if (!app.bad) {
7964 for (; i<NL; i++) {
7965 if (mLaunchingProviders.get(i) == cpr) {
7966 restart = true;
7967 break;
7968 }
7969 }
7970 } else {
7971 i = NL;
7972 }
7973
7974 if (i >= NL) {
7975 removeDyingProviderLocked(app, cpr);
7976 NL = mLaunchingProviders.size();
7977 }
7978 }
7979 app.pubProviders.clear();
7980 }
7981
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007982 // Take care of any launching providers waiting for this process.
7983 if (checkAppInLaunchingProvidersLocked(app, false)) {
7984 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007985 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987 // Unregister from connected content providers.
7988 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007989 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007990 while (it.hasNext()) {
7991 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7992 cpr.clients.remove(app);
7993 }
7994 app.conProviders.clear();
7995 }
7996
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007997 // At this point there may be remaining entries in mLaunchingProviders
7998 // where we were the only one waiting, so they are no longer of use.
7999 // Look for these and clean up if found.
8000 // XXX Commented out for now. Trying to figure out a way to reproduce
8001 // the actual situation to identify what is actually going on.
8002 if (false) {
8003 for (int i=0; i<NL; i++) {
8004 ContentProviderRecord cpr = (ContentProviderRecord)
8005 mLaunchingProviders.get(i);
8006 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8007 synchronized (cpr) {
8008 cpr.launchingApp = null;
8009 cpr.notifyAll();
8010 }
8011 }
8012 }
8013 }
8014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 skipCurrentReceiverLocked(app);
8016
8017 // Unregister any receivers.
8018 if (app.receivers.size() > 0) {
8019 Iterator<ReceiverList> it = app.receivers.iterator();
8020 while (it.hasNext()) {
8021 removeReceiverLocked(it.next());
8022 }
8023 app.receivers.clear();
8024 }
8025
Christopher Tate181fafa2009-05-14 11:12:14 -07008026 // If the app is undergoing backup, tell the backup manager about it
8027 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008028 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008029 try {
8030 IBackupManager bm = IBackupManager.Stub.asInterface(
8031 ServiceManager.getService(Context.BACKUP_SERVICE));
8032 bm.agentDisconnected(app.info.packageName);
8033 } catch (RemoteException e) {
8034 // can't happen; backup manager is local
8035 }
8036 }
8037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008038 // If the caller is restarting this app, then leave it in its
8039 // current lists and let the caller take care of it.
8040 if (restarting) {
8041 return;
8042 }
8043
8044 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008045 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046 "Removing non-persistent process during cleanup: " + app);
8047 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008048 if (mHeavyWeightProcess == app) {
8049 mHeavyWeightProcess = null;
8050 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 } else if (!app.removed) {
8053 // This app is persistent, so we need to keep its record around.
8054 // If it is not already on the pending app list, add it there
8055 // and start a new process for it.
8056 app.thread = null;
8057 app.forcingToForeground = null;
8058 app.foregroundServices = false;
8059 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8060 mPersistentStartingProcesses.add(app);
8061 restart = true;
8062 }
8063 }
8064 mProcessesOnHold.remove(app);
8065
The Android Open Source Project4df24232009-03-05 14:34:35 -08008066 if (app == mHomeProcess) {
8067 mHomeProcess = null;
8068 }
8069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008070 if (restart) {
8071 // We have components that still need to be running in the
8072 // process, so re-launch it.
8073 mProcessNames.put(app.processName, app.info.uid, app);
8074 startProcessLocked(app, "restart", app.processName);
8075 } else if (app.pid > 0 && app.pid != MY_PID) {
8076 // Goodbye!
8077 synchronized (mPidsSelfLocked) {
8078 mPidsSelfLocked.remove(app.pid);
8079 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8080 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008081 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008082 }
8083 }
8084
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008085 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8086 // Look through the content providers we are waiting to have launched,
8087 // and if any run in this process then either schedule a restart of
8088 // the process or kill the client waiting for it if this process has
8089 // gone bad.
8090 int NL = mLaunchingProviders.size();
8091 boolean restart = false;
8092 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008093 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008094 if (cpr.launchingApp == app) {
8095 if (!alwaysBad && !app.bad) {
8096 restart = true;
8097 } else {
8098 removeDyingProviderLocked(app, cpr);
8099 NL = mLaunchingProviders.size();
8100 }
8101 }
8102 }
8103 return restart;
8104 }
8105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008106 // =========================================================
8107 // SERVICES
8108 // =========================================================
8109
8110 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8111 ActivityManager.RunningServiceInfo info =
8112 new ActivityManager.RunningServiceInfo();
8113 info.service = r.name;
8114 if (r.app != null) {
8115 info.pid = r.app.pid;
8116 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008117 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008118 info.process = r.processName;
8119 info.foreground = r.isForeground;
8120 info.activeSince = r.createTime;
8121 info.started = r.startRequested;
8122 info.clientCount = r.connections.size();
8123 info.crashCount = r.crashCount;
8124 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008125 if (r.isForeground) {
8126 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8127 }
8128 if (r.startRequested) {
8129 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8130 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008131 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008132 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8133 }
8134 if (r.app != null && r.app.persistent) {
8135 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8136 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008137
8138 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8139 for (int i=0; i<connl.size(); i++) {
8140 ConnectionRecord conn = connl.get(i);
8141 if (conn.clientLabel != 0) {
8142 info.clientPackage = conn.binding.client.info.packageName;
8143 info.clientLabel = conn.clientLabel;
8144 return info;
8145 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008146 }
8147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008148 return info;
8149 }
8150
8151 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8152 int flags) {
8153 synchronized (this) {
8154 ArrayList<ActivityManager.RunningServiceInfo> res
8155 = new ArrayList<ActivityManager.RunningServiceInfo>();
8156
8157 if (mServices.size() > 0) {
8158 Iterator<ServiceRecord> it = mServices.values().iterator();
8159 while (it.hasNext() && res.size() < maxNum) {
8160 res.add(makeRunningServiceInfoLocked(it.next()));
8161 }
8162 }
8163
8164 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8165 ServiceRecord r = mRestartingServices.get(i);
8166 ActivityManager.RunningServiceInfo info =
8167 makeRunningServiceInfoLocked(r);
8168 info.restarting = r.nextRestartTime;
8169 res.add(info);
8170 }
8171
8172 return res;
8173 }
8174 }
8175
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008176 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8177 synchronized (this) {
8178 ServiceRecord r = mServices.get(name);
8179 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008180 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8181 for (int i=0; i<conn.size(); i++) {
8182 if (conn.get(i).clientIntent != null) {
8183 return conn.get(i).clientIntent;
8184 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008185 }
8186 }
8187 }
8188 }
8189 return null;
8190 }
8191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008192 private final ServiceRecord findServiceLocked(ComponentName name,
8193 IBinder token) {
8194 ServiceRecord r = mServices.get(name);
8195 return r == token ? r : null;
8196 }
8197
8198 private final class ServiceLookupResult {
8199 final ServiceRecord record;
8200 final String permission;
8201
8202 ServiceLookupResult(ServiceRecord _record, String _permission) {
8203 record = _record;
8204 permission = _permission;
8205 }
8206 };
8207
8208 private ServiceLookupResult findServiceLocked(Intent service,
8209 String resolvedType) {
8210 ServiceRecord r = null;
8211 if (service.getComponent() != null) {
8212 r = mServices.get(service.getComponent());
8213 }
8214 if (r == null) {
8215 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8216 r = mServicesByIntent.get(filter);
8217 }
8218
8219 if (r == null) {
8220 try {
8221 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008222 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 service, resolvedType, 0);
8224 ServiceInfo sInfo =
8225 rInfo != null ? rInfo.serviceInfo : null;
8226 if (sInfo == null) {
8227 return null;
8228 }
8229
8230 ComponentName name = new ComponentName(
8231 sInfo.applicationInfo.packageName, sInfo.name);
8232 r = mServices.get(name);
8233 } catch (RemoteException ex) {
8234 // pm is in same process, this will never happen.
8235 }
8236 }
8237 if (r != null) {
8238 int callingPid = Binder.getCallingPid();
8239 int callingUid = Binder.getCallingUid();
8240 if (checkComponentPermission(r.permission,
8241 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8242 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008243 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008244 + " from pid=" + callingPid
8245 + ", uid=" + callingUid
8246 + " requires " + r.permission);
8247 return new ServiceLookupResult(null, r.permission);
8248 }
8249 return new ServiceLookupResult(r, null);
8250 }
8251 return null;
8252 }
8253
8254 private class ServiceRestarter implements Runnable {
8255 private ServiceRecord mService;
8256
8257 void setService(ServiceRecord service) {
8258 mService = service;
8259 }
8260
8261 public void run() {
8262 synchronized(ActivityManagerService.this) {
8263 performServiceRestartLocked(mService);
8264 }
8265 }
8266 }
8267
8268 private ServiceLookupResult retrieveServiceLocked(Intent service,
8269 String resolvedType, int callingPid, int callingUid) {
8270 ServiceRecord r = null;
8271 if (service.getComponent() != null) {
8272 r = mServices.get(service.getComponent());
8273 }
8274 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8275 r = mServicesByIntent.get(filter);
8276 if (r == null) {
8277 try {
8278 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008279 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008280 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008281 ServiceInfo sInfo =
8282 rInfo != null ? rInfo.serviceInfo : null;
8283 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008284 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008285 ": not found");
8286 return null;
8287 }
8288
8289 ComponentName name = new ComponentName(
8290 sInfo.applicationInfo.packageName, sInfo.name);
8291 r = mServices.get(name);
8292 if (r == null) {
8293 filter = new Intent.FilterComparison(service.cloneFilter());
8294 ServiceRestarter res = new ServiceRestarter();
8295 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8296 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8297 synchronized (stats) {
8298 ss = stats.getServiceStatsLocked(
8299 sInfo.applicationInfo.uid, sInfo.packageName,
8300 sInfo.name);
8301 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008302 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 res.setService(r);
8304 mServices.put(name, r);
8305 mServicesByIntent.put(filter, r);
8306
8307 // Make sure this component isn't in the pending list.
8308 int N = mPendingServices.size();
8309 for (int i=0; i<N; i++) {
8310 ServiceRecord pr = mPendingServices.get(i);
8311 if (pr.name.equals(name)) {
8312 mPendingServices.remove(i);
8313 i--;
8314 N--;
8315 }
8316 }
8317 }
8318 } catch (RemoteException ex) {
8319 // pm is in same process, this will never happen.
8320 }
8321 }
8322 if (r != null) {
8323 if (checkComponentPermission(r.permission,
8324 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8325 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008326 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008327 + " from pid=" + Binder.getCallingPid()
8328 + ", uid=" + Binder.getCallingUid()
8329 + " requires " + r.permission);
8330 return new ServiceLookupResult(null, r.permission);
8331 }
8332 return new ServiceLookupResult(r, null);
8333 }
8334 return null;
8335 }
8336
8337 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8338 long now = SystemClock.uptimeMillis();
8339 if (r.executeNesting == 0 && r.app != null) {
8340 if (r.app.executingServices.size() == 0) {
8341 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8342 msg.obj = r.app;
8343 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8344 }
8345 r.app.executingServices.add(r);
8346 }
8347 r.executeNesting++;
8348 r.executingStart = now;
8349 }
8350
8351 private final void sendServiceArgsLocked(ServiceRecord r,
8352 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008353 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008354 if (N == 0) {
8355 return;
8356 }
8357
Dianne Hackborn39792d22010-08-19 18:01:52 -07008358 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008359 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008360 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008361 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8362 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008363 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008364 // If somehow we got a dummy start at the front, then
8365 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008366 continue;
8367 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008368 si.deliveredTime = SystemClock.uptimeMillis();
8369 r.deliveredStarts.add(si);
8370 si.deliveryCount++;
8371 if (si.targetPermissionUid >= 0) {
8372 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008373 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008374 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008375 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008376 bumpServiceExecutingLocked(r);
8377 if (!oomAdjusted) {
8378 oomAdjusted = true;
8379 updateOomAdjLocked(r.app);
8380 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008381 int flags = 0;
8382 if (si.deliveryCount > 0) {
8383 flags |= Service.START_FLAG_RETRY;
8384 }
8385 if (si.doneExecutingCount > 0) {
8386 flags |= Service.START_FLAG_REDELIVERY;
8387 }
8388 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008389 } catch (RemoteException e) {
8390 // Remote process gone... we'll let the normal cleanup take
8391 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008392 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008393 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008395 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008396 break;
8397 }
8398 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008399 }
8400
8401 private final boolean requestServiceBindingLocked(ServiceRecord r,
8402 IntentBindRecord i, boolean rebind) {
8403 if (r.app == null || r.app.thread == null) {
8404 // If service is not currently running, can't yet bind.
8405 return false;
8406 }
8407 if ((!i.requested || rebind) && i.apps.size() > 0) {
8408 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008409 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
8410 + " in " + i + ": shouldUnbind=" + i.hasBound);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008411 bumpServiceExecutingLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008412 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8413 if (!rebind) {
8414 i.requested = true;
8415 }
8416 i.hasBound = true;
8417 i.doRebind = false;
8418 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008419 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008420 return false;
8421 }
8422 }
8423 return true;
8424 }
8425
8426 private final void requestServiceBindingsLocked(ServiceRecord r) {
8427 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8428 while (bindings.hasNext()) {
8429 IntentBindRecord i = bindings.next();
8430 if (!requestServiceBindingLocked(r, i, false)) {
8431 break;
8432 }
8433 }
8434 }
8435
8436 private final void realStartServiceLocked(ServiceRecord r,
8437 ProcessRecord app) throws RemoteException {
8438 if (app.thread == null) {
8439 throw new RemoteException();
8440 }
8441
8442 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008443 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008444
8445 app.services.add(r);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008446 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008447 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008448 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008449
8450 boolean created = false;
8451 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008452 mStringBuilder.setLength(0);
8453 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008454 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008455 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008456 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008457 synchronized (r.stats.getBatteryStats()) {
8458 r.stats.startLaunchedLocked();
8459 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008460 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008462 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 created = true;
8464 } finally {
8465 if (!created) {
8466 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008467 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008468 }
8469 }
8470
8471 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008472
8473 // If the service is in the started state, and there are no
8474 // pending arguments, then fake up one so its onStartCommand() will
8475 // be called.
8476 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8477 r.lastStartId++;
8478 if (r.lastStartId < 1) {
8479 r.lastStartId = 1;
8480 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008481 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008482 }
8483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008484 sendServiceArgsLocked(r, true);
8485 }
8486
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008487 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8488 boolean allowCancel) {
8489 boolean canceled = false;
8490
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008491 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008492 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008493 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008494
8495 // Any delivered but not yet finished starts should be put back
8496 // on the pending list.
8497 final int N = r.deliveredStarts.size();
8498 if (N > 0) {
8499 for (int i=N-1; i>=0; i--) {
8500 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008501 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008502 if (si.intent == null) {
8503 // We'll generate this again if needed.
8504 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8505 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8506 r.pendingStarts.add(0, si);
8507 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8508 dur *= 2;
8509 if (minDuration < dur) minDuration = dur;
8510 if (resetTime < dur) resetTime = dur;
8511 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008512 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008513 + r.name);
8514 canceled = true;
8515 }
8516 }
8517 r.deliveredStarts.clear();
8518 }
8519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 r.totalRestartCount++;
8521 if (r.restartDelay == 0) {
8522 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008523 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008524 } else {
8525 // If it has been a "reasonably long time" since the service
8526 // was started, then reset our restart duration back to
8527 // the beginning, so we don't infinitely increase the duration
8528 // on a service that just occasionally gets killed (which is
8529 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008530 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008532 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008533 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008534 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008535 if (r.restartDelay < minDuration) {
8536 r.restartDelay = minDuration;
8537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 }
8539 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008540
8541 r.nextRestartTime = now + r.restartDelay;
8542
8543 // Make sure that we don't end up restarting a bunch of services
8544 // all at the same time.
8545 boolean repeat;
8546 do {
8547 repeat = false;
8548 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8549 ServiceRecord r2 = mRestartingServices.get(i);
8550 if (r2 != r && r.nextRestartTime
8551 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8552 && r.nextRestartTime
8553 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8554 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8555 r.restartDelay = r.nextRestartTime - now;
8556 repeat = true;
8557 break;
8558 }
8559 }
8560 } while (repeat);
8561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008562 if (!mRestartingServices.contains(r)) {
8563 mRestartingServices.add(r);
8564 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008565
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008566 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008569 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008571 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008572 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008573 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008574 r.shortName, r.restartDelay);
8575
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008576 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008577 }
8578
8579 final void performServiceRestartLocked(ServiceRecord r) {
8580 if (!mRestartingServices.contains(r)) {
8581 return;
8582 }
8583 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8584 }
8585
8586 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8587 if (r.restartDelay == 0) {
8588 return false;
8589 }
8590 r.resetRestartCounter();
8591 mRestartingServices.remove(r);
8592 mHandler.removeCallbacks(r.restarter);
8593 return true;
8594 }
8595
8596 private final boolean bringUpServiceLocked(ServiceRecord r,
8597 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008598 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 //r.dump(" ");
8600
Dianne Hackborn36124872009-10-08 16:22:03 -07008601 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008602 sendServiceArgsLocked(r, false);
8603 return true;
8604 }
8605
8606 if (!whileRestarting && r.restartDelay > 0) {
8607 // If waiting for a restart, then do nothing.
8608 return true;
8609 }
8610
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008611 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008612
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008613 // We are now bringing the service up, so no longer in the
8614 // restarting state.
8615 mRestartingServices.remove(r);
8616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008617 final String appName = r.processName;
8618 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8619 if (app != null && app.thread != null) {
8620 try {
8621 realStartServiceLocked(r, app);
8622 return true;
8623 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008624 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008625 }
8626
8627 // If a dead object exception was thrown -- fall through to
8628 // restart the application.
8629 }
8630
Dianne Hackborn36124872009-10-08 16:22:03 -07008631 // Not running -- get it started, and enqueue this service record
8632 // to be executed when the app comes up.
8633 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8634 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008635 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008636 + r.appInfo.packageName + "/"
8637 + r.appInfo.uid + " for service "
8638 + r.intent.getIntent() + ": process is bad");
8639 bringDownServiceLocked(r, true);
8640 return false;
8641 }
8642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 mPendingServices.add(r);
8645 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647 return true;
8648 }
8649
8650 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008651 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 //r.dump(" ");
8653
8654 // Does it still need to run?
8655 if (!force && r.startRequested) {
8656 return;
8657 }
8658 if (r.connections.size() > 0) {
8659 if (!force) {
8660 // XXX should probably keep a count of the number of auto-create
8661 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008662 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008663 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008664 ArrayList<ConnectionRecord> cr = it.next();
8665 for (int i=0; i<cr.size(); i++) {
8666 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8667 return;
8668 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 }
8670 }
8671 }
8672
8673 // Report to all of the connections that the service is no longer
8674 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008675 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008676 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008677 ArrayList<ConnectionRecord> c = it.next();
8678 for (int i=0; i<c.size(); i++) {
8679 try {
8680 c.get(i).conn.connected(r.name, null);
8681 } catch (Exception e) {
8682 Slog.w(TAG, "Failure disconnecting service " + r.name +
8683 " to connection " + c.get(i).conn.asBinder() +
8684 " (in " + c.get(i).binding.client.processName + ")", e);
8685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008686 }
8687 }
8688 }
8689
8690 // Tell the service that it has been unbound.
8691 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8692 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8693 while (it.hasNext()) {
8694 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008695 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008696 + ": hasBound=" + ibr.hasBound);
8697 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8698 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008699 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
8700 + " for " + ibr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008701 bumpServiceExecutingLocked(r);
8702 updateOomAdjLocked(r.app);
8703 ibr.hasBound = false;
8704 r.app.thread.scheduleUnbindService(r,
8705 ibr.intent.getIntent());
8706 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008707 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008708 + r.shortName, e);
8709 serviceDoneExecutingLocked(r, true);
8710 }
8711 }
8712 }
8713 }
8714
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008715 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008716 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 System.identityHashCode(r), r.shortName,
8718 (r.app != null) ? r.app.pid : -1);
8719
8720 mServices.remove(r.name);
8721 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008722 r.totalRestartCount = 0;
8723 unscheduleServiceRestartLocked(r);
8724
8725 // Also make sure it is not on the pending list.
8726 int N = mPendingServices.size();
8727 for (int i=0; i<N; i++) {
8728 if (mPendingServices.get(i) == r) {
8729 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008730 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008731 i--;
8732 N--;
8733 }
8734 }
8735
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008736 r.cancelNotification();
8737 r.isForeground = false;
8738 r.foregroundId = 0;
8739 r.foregroundNoti = null;
8740
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008741 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008742 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008743 r.pendingStarts.clear();
8744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 if (r.app != null) {
8746 synchronized (r.stats.getBatteryStats()) {
8747 r.stats.stopLaunchedLocked();
8748 }
8749 r.app.services.remove(r);
8750 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008751 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008752 if (DEBUG_SERVICE) {
8753 RuntimeException here = new RuntimeException();
8754 here.fillInStackTrace();
8755 Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
8756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 bumpServiceExecutingLocked(r);
8758 mStoppingServices.add(r);
8759 updateOomAdjLocked(r.app);
8760 r.app.thread.scheduleStopService(r);
8761 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008762 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008763 + r.shortName, e);
8764 serviceDoneExecutingLocked(r, true);
8765 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008766 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008767 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008768 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008769 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008770 }
8771 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008772 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008773 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008774 }
8775 }
8776
8777 ComponentName startServiceLocked(IApplicationThread caller,
8778 Intent service, String resolvedType,
8779 int callingPid, int callingUid) {
8780 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008781 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 + " type=" + resolvedType + " args=" + service.getExtras());
8783
8784 if (caller != null) {
8785 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8786 if (callerApp == null) {
8787 throw new SecurityException(
8788 "Unable to find app for caller " + caller
8789 + " (pid=" + Binder.getCallingPid()
8790 + ") when starting service " + service);
8791 }
8792 }
8793
8794 ServiceLookupResult res =
8795 retrieveServiceLocked(service, resolvedType,
8796 callingPid, callingUid);
8797 if (res == null) {
8798 return null;
8799 }
8800 if (res.record == null) {
8801 return new ComponentName("!", res.permission != null
8802 ? res.permission : "private to package");
8803 }
8804 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07008805 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
8806 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008808 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 }
8810 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008811 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 r.lastStartId++;
8813 if (r.lastStartId < 1) {
8814 r.lastStartId = 1;
8815 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008816 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
8817 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008818 r.lastActivity = SystemClock.uptimeMillis();
8819 synchronized (r.stats.getBatteryStats()) {
8820 r.stats.startRunningLocked();
8821 }
8822 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8823 return new ComponentName("!", "Service process is bad");
8824 }
8825 return r.name;
8826 }
8827 }
8828
8829 public ComponentName startService(IApplicationThread caller, Intent service,
8830 String resolvedType) {
8831 // Refuse possible leaked file descriptors
8832 if (service != null && service.hasFileDescriptors() == true) {
8833 throw new IllegalArgumentException("File descriptors passed in Intent");
8834 }
8835
8836 synchronized(this) {
8837 final int callingPid = Binder.getCallingPid();
8838 final int callingUid = Binder.getCallingUid();
8839 final long origId = Binder.clearCallingIdentity();
8840 ComponentName res = startServiceLocked(caller, service,
8841 resolvedType, callingPid, callingUid);
8842 Binder.restoreCallingIdentity(origId);
8843 return res;
8844 }
8845 }
8846
8847 ComponentName startServiceInPackage(int uid,
8848 Intent service, String resolvedType) {
8849 synchronized(this) {
8850 final long origId = Binder.clearCallingIdentity();
8851 ComponentName res = startServiceLocked(null, service,
8852 resolvedType, -1, uid);
8853 Binder.restoreCallingIdentity(origId);
8854 return res;
8855 }
8856 }
8857
8858 public int stopService(IApplicationThread caller, Intent service,
8859 String resolvedType) {
8860 // Refuse possible leaked file descriptors
8861 if (service != null && service.hasFileDescriptors() == true) {
8862 throw new IllegalArgumentException("File descriptors passed in Intent");
8863 }
8864
8865 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008866 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008867 + " type=" + resolvedType);
8868
8869 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8870 if (caller != null && callerApp == null) {
8871 throw new SecurityException(
8872 "Unable to find app for caller " + caller
8873 + " (pid=" + Binder.getCallingPid()
8874 + ") when stopping service " + service);
8875 }
8876
8877 // If this service is active, make sure it is stopped.
8878 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8879 if (r != null) {
8880 if (r.record != null) {
8881 synchronized (r.record.stats.getBatteryStats()) {
8882 r.record.stats.stopRunningLocked();
8883 }
8884 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008885 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008886 final long origId = Binder.clearCallingIdentity();
8887 bringDownServiceLocked(r.record, false);
8888 Binder.restoreCallingIdentity(origId);
8889 return 1;
8890 }
8891 return -1;
8892 }
8893 }
8894
8895 return 0;
8896 }
8897
8898 public IBinder peekService(Intent service, String resolvedType) {
8899 // Refuse possible leaked file descriptors
8900 if (service != null && service.hasFileDescriptors() == true) {
8901 throw new IllegalArgumentException("File descriptors passed in Intent");
8902 }
8903
8904 IBinder ret = null;
8905
8906 synchronized(this) {
8907 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8908
8909 if (r != null) {
8910 // r.record is null if findServiceLocked() failed the caller permission check
8911 if (r.record == null) {
8912 throw new SecurityException(
8913 "Permission Denial: Accessing service " + r.record.name
8914 + " from pid=" + Binder.getCallingPid()
8915 + ", uid=" + Binder.getCallingUid()
8916 + " requires " + r.permission);
8917 }
8918 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8919 if (ib != null) {
8920 ret = ib.binder;
8921 }
8922 }
8923 }
8924
8925 return ret;
8926 }
8927
8928 public boolean stopServiceToken(ComponentName className, IBinder token,
8929 int startId) {
8930 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008931 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008932 + " " + token + " startId=" + startId);
8933 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008934 if (r != null) {
8935 if (startId >= 0) {
8936 // Asked to only stop if done with all work. Note that
8937 // to avoid leaks, we will take this as dropping all
8938 // start items up to and including this one.
8939 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8940 if (si != null) {
8941 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008942 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
8943 cur.removeUriPermissionsLocked();
8944 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008945 break;
8946 }
8947 }
8948 }
8949
8950 if (r.lastStartId != startId) {
8951 return false;
8952 }
8953
8954 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008955 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008956 + " is last, but have " + r.deliveredStarts.size()
8957 + " remaining args");
8958 }
8959 }
8960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008961 synchronized (r.stats.getBatteryStats()) {
8962 r.stats.stopRunningLocked();
8963 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008964 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008965 }
8966 final long origId = Binder.clearCallingIdentity();
8967 bringDownServiceLocked(r, false);
8968 Binder.restoreCallingIdentity(origId);
8969 return true;
8970 }
8971 }
8972 return false;
8973 }
8974
8975 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008976 int id, Notification notification, boolean removeNotification) {
8977 final long origId = Binder.clearCallingIdentity();
8978 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979 synchronized(this) {
8980 ServiceRecord r = findServiceLocked(className, token);
8981 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008982 if (id != 0) {
8983 if (notification == null) {
8984 throw new IllegalArgumentException("null notification");
8985 }
8986 if (r.foregroundId != id) {
8987 r.cancelNotification();
8988 r.foregroundId = id;
8989 }
8990 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8991 r.foregroundNoti = notification;
8992 r.isForeground = true;
8993 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008994 if (r.app != null) {
8995 updateServiceForegroundLocked(r.app, true);
8996 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008997 } else {
8998 if (r.isForeground) {
8999 r.isForeground = false;
9000 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009001 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009002 updateServiceForegroundLocked(r.app, true);
9003 }
9004 }
9005 if (removeNotification) {
9006 r.cancelNotification();
9007 r.foregroundId = 0;
9008 r.foregroundNoti = null;
9009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009010 }
9011 }
9012 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009013 } finally {
9014 Binder.restoreCallingIdentity(origId);
9015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009016 }
9017
9018 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9019 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009020 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009021 if (sr.isForeground) {
9022 anyForeground = true;
9023 break;
9024 }
9025 }
9026 if (anyForeground != proc.foregroundServices) {
9027 proc.foregroundServices = anyForeground;
9028 if (oomAdj) {
9029 updateOomAdjLocked();
9030 }
9031 }
9032 }
9033
9034 public int bindService(IApplicationThread caller, IBinder token,
9035 Intent service, String resolvedType,
9036 IServiceConnection connection, int flags) {
9037 // Refuse possible leaked file descriptors
9038 if (service != null && service.hasFileDescriptors() == true) {
9039 throw new IllegalArgumentException("File descriptors passed in Intent");
9040 }
9041
9042 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009043 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 + " type=" + resolvedType + " conn=" + connection.asBinder()
9045 + " flags=0x" + Integer.toHexString(flags));
9046 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9047 if (callerApp == null) {
9048 throw new SecurityException(
9049 "Unable to find app for caller " + caller
9050 + " (pid=" + Binder.getCallingPid()
9051 + ") when binding service " + service);
9052 }
9053
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009054 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009056 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009057 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009058 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009059 return 0;
9060 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009061 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009062 }
9063
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009064 int clientLabel = 0;
9065 PendingIntent clientIntent = null;
9066
9067 if (callerApp.info.uid == Process.SYSTEM_UID) {
9068 // Hacky kind of thing -- allow system stuff to tell us
9069 // what they are, so we can report this elsewhere for
9070 // others to know why certain services are running.
9071 try {
9072 clientIntent = (PendingIntent)service.getParcelableExtra(
9073 Intent.EXTRA_CLIENT_INTENT);
9074 } catch (RuntimeException e) {
9075 }
9076 if (clientIntent != null) {
9077 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9078 if (clientLabel != 0) {
9079 // There are no useful extras in the intent, trash them.
9080 // System code calling with this stuff just needs to know
9081 // this will happen.
9082 service = service.cloneFilter();
9083 }
9084 }
9085 }
9086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 ServiceLookupResult res =
9088 retrieveServiceLocked(service, resolvedType,
9089 Binder.getCallingPid(), Binder.getCallingUid());
9090 if (res == null) {
9091 return 0;
9092 }
9093 if (res.record == null) {
9094 return -1;
9095 }
9096 ServiceRecord s = res.record;
9097
9098 final long origId = Binder.clearCallingIdentity();
9099
9100 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009101 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009102 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009103 }
9104
9105 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9106 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009107 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108
9109 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009110 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9111 if (clist == null) {
9112 clist = new ArrayList<ConnectionRecord>();
9113 s.connections.put(binder, clist);
9114 }
9115 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009116 b.connections.add(c);
9117 if (activity != null) {
9118 if (activity.connections == null) {
9119 activity.connections = new HashSet<ConnectionRecord>();
9120 }
9121 activity.connections.add(c);
9122 }
9123 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009124 clist = mServiceConnections.get(binder);
9125 if (clist == null) {
9126 clist = new ArrayList<ConnectionRecord>();
9127 mServiceConnections.put(binder, clist);
9128 }
9129 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130
9131 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9132 s.lastActivity = SystemClock.uptimeMillis();
9133 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9134 return 0;
9135 }
9136 }
9137
9138 if (s.app != null) {
9139 // This could have made the service more important.
9140 updateOomAdjLocked(s.app);
9141 }
9142
Joe Onorato8a9b2202010-02-26 18:56:32 -08009143 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009144 + ": received=" + b.intent.received
9145 + " apps=" + b.intent.apps.size()
9146 + " doRebind=" + b.intent.doRebind);
9147
9148 if (s.app != null && b.intent.received) {
9149 // Service is already running, so we can immediately
9150 // publish the connection.
9151 try {
9152 c.conn.connected(s.name, b.intent.binder);
9153 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009154 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155 + " to connection " + c.conn.asBinder()
9156 + " (in " + c.binding.client.processName + ")", e);
9157 }
9158
9159 // If this is the first app connected back to this binding,
9160 // and the service had previously asked to be told when
9161 // rebound, then do so.
9162 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9163 requestServiceBindingLocked(s, b.intent, true);
9164 }
9165 } else if (!b.intent.requested) {
9166 requestServiceBindingLocked(s, b.intent, false);
9167 }
9168
9169 Binder.restoreCallingIdentity(origId);
9170 }
9171
9172 return 1;
9173 }
9174
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009175 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009176 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 IBinder binder = c.conn.asBinder();
9178 AppBindRecord b = c.binding;
9179 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009180 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9181 if (clist != null) {
9182 clist.remove(c);
9183 if (clist.size() == 0) {
9184 s.connections.remove(binder);
9185 }
9186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009187 b.connections.remove(c);
9188 if (c.activity != null && c.activity != skipAct) {
9189 if (c.activity.connections != null) {
9190 c.activity.connections.remove(c);
9191 }
9192 }
9193 if (b.client != skipApp) {
9194 b.client.connections.remove(c);
9195 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009196 clist = mServiceConnections.get(binder);
9197 if (clist != null) {
9198 clist.remove(c);
9199 if (clist.size() == 0) {
9200 mServiceConnections.remove(binder);
9201 }
9202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203
9204 if (b.connections.size() == 0) {
9205 b.intent.apps.remove(b.client);
9206 }
9207
Joe Onorato8a9b2202010-02-26 18:56:32 -08009208 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009209 + ": shouldUnbind=" + b.intent.hasBound);
9210 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9211 && b.intent.hasBound) {
9212 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009213 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
9214 + " from " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 bumpServiceExecutingLocked(s);
9216 updateOomAdjLocked(s.app);
9217 b.intent.hasBound = false;
9218 // Assume the client doesn't want to know about a rebind;
9219 // we will deal with that later if it asks for one.
9220 b.intent.doRebind = false;
9221 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9222 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009223 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009224 serviceDoneExecutingLocked(s, true);
9225 }
9226 }
9227
9228 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9229 bringDownServiceLocked(s, false);
9230 }
9231 }
9232
9233 public boolean unbindService(IServiceConnection connection) {
9234 synchronized (this) {
9235 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009236 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009237 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9238 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009239 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 + connection.asBinder());
9241 return false;
9242 }
9243
9244 final long origId = Binder.clearCallingIdentity();
9245
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009246 while (clist.size() > 0) {
9247 ConnectionRecord r = clist.get(0);
9248 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009250 if (r.binding.service.app != null) {
9251 // This could have made the service less important.
9252 updateOomAdjLocked(r.binding.service.app);
9253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009254 }
9255
9256 Binder.restoreCallingIdentity(origId);
9257 }
9258
9259 return true;
9260 }
9261
9262 public void publishService(IBinder token, Intent intent, IBinder service) {
9263 // Refuse possible leaked file descriptors
9264 if (intent != null && intent.hasFileDescriptors() == true) {
9265 throw new IllegalArgumentException("File descriptors passed in Intent");
9266 }
9267
9268 synchronized(this) {
9269 if (!(token instanceof ServiceRecord)) {
9270 throw new IllegalArgumentException("Invalid service token");
9271 }
9272 ServiceRecord r = (ServiceRecord)token;
9273
9274 final long origId = Binder.clearCallingIdentity();
9275
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009276 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009277 + " " + intent + ": " + service);
9278 if (r != null) {
9279 Intent.FilterComparison filter
9280 = new Intent.FilterComparison(intent);
9281 IntentBindRecord b = r.bindings.get(filter);
9282 if (b != null && !b.received) {
9283 b.binder = service;
9284 b.requested = true;
9285 b.received = true;
9286 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009287 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009288 = r.connections.values().iterator();
9289 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009290 ArrayList<ConnectionRecord> clist = it.next();
9291 for (int i=0; i<clist.size(); i++) {
9292 ConnectionRecord c = clist.get(i);
9293 if (!filter.equals(c.binding.intent.intent)) {
9294 if (DEBUG_SERVICE) Slog.v(
9295 TAG, "Not publishing to: " + c);
9296 if (DEBUG_SERVICE) Slog.v(
9297 TAG, "Bound intent: " + c.binding.intent.intent);
9298 if (DEBUG_SERVICE) Slog.v(
9299 TAG, "Published intent: " + intent);
9300 continue;
9301 }
9302 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9303 try {
9304 c.conn.connected(r.name, service);
9305 } catch (Exception e) {
9306 Slog.w(TAG, "Failure sending service " + r.name +
9307 " to connection " + c.conn.asBinder() +
9308 " (in " + c.binding.client.processName + ")", e);
9309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009310 }
9311 }
9312 }
9313 }
9314
9315 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9316
9317 Binder.restoreCallingIdentity(origId);
9318 }
9319 }
9320 }
9321
9322 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9323 // Refuse possible leaked file descriptors
9324 if (intent != null && intent.hasFileDescriptors() == true) {
9325 throw new IllegalArgumentException("File descriptors passed in Intent");
9326 }
9327
9328 synchronized(this) {
9329 if (!(token instanceof ServiceRecord)) {
9330 throw new IllegalArgumentException("Invalid service token");
9331 }
9332 ServiceRecord r = (ServiceRecord)token;
9333
9334 final long origId = Binder.clearCallingIdentity();
9335
9336 if (r != null) {
9337 Intent.FilterComparison filter
9338 = new Intent.FilterComparison(intent);
9339 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009340 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009341 + " at " + b + ": apps="
9342 + (b != null ? b.apps.size() : 0));
9343 if (b != null) {
9344 if (b.apps.size() > 0) {
9345 // Applications have already bound since the last
9346 // unbind, so just rebind right here.
9347 requestServiceBindingLocked(r, b, true);
9348 } else {
9349 // Note to tell the service the next time there is
9350 // a new client.
9351 b.doRebind = true;
9352 }
9353 }
9354
9355 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9356
9357 Binder.restoreCallingIdentity(origId);
9358 }
9359 }
9360 }
9361
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009362 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009363 synchronized(this) {
9364 if (!(token instanceof ServiceRecord)) {
9365 throw new IllegalArgumentException("Invalid service token");
9366 }
9367 ServiceRecord r = (ServiceRecord)token;
9368 boolean inStopping = mStoppingServices.contains(token);
9369 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009370 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009371 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009372 + " with incorrect token: given " + token
9373 + ", expected " + r);
9374 return;
9375 }
9376
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009377 if (type == 1) {
9378 // This is a call from a service start... take care of
9379 // book-keeping.
9380 r.callStart = true;
9381 switch (res) {
9382 case Service.START_STICKY_COMPATIBILITY:
9383 case Service.START_STICKY: {
9384 // We are done with the associated start arguments.
9385 r.findDeliveredStart(startId, true);
9386 // Don't stop if killed.
9387 r.stopIfKilled = false;
9388 break;
9389 }
9390 case Service.START_NOT_STICKY: {
9391 // We are done with the associated start arguments.
9392 r.findDeliveredStart(startId, true);
9393 if (r.lastStartId == startId) {
9394 // There is no more work, and this service
9395 // doesn't want to hang around if killed.
9396 r.stopIfKilled = true;
9397 }
9398 break;
9399 }
9400 case Service.START_REDELIVER_INTENT: {
9401 // We'll keep this item until they explicitly
9402 // call stop for it, but keep track of the fact
9403 // that it was delivered.
9404 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9405 if (si != null) {
9406 si.deliveryCount = 0;
9407 si.doneExecutingCount++;
9408 // Don't stop if killed.
9409 r.stopIfKilled = true;
9410 }
9411 break;
9412 }
9413 default:
9414 throw new IllegalArgumentException(
9415 "Unknown service start result: " + res);
9416 }
9417 if (res == Service.START_STICKY_COMPATIBILITY) {
9418 r.callStart = false;
9419 }
9420 }
9421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009422 final long origId = Binder.clearCallingIdentity();
9423 serviceDoneExecutingLocked(r, inStopping);
9424 Binder.restoreCallingIdentity(origId);
9425 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009426 Slog.w(TAG, "Done executing unknown service from pid "
9427 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009428 }
9429 }
9430 }
9431
9432 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009433 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9434 + ": nesting=" + r.executeNesting
9435 + ", inStopping=" + inStopping + ", app=" + r.app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009436 r.executeNesting--;
9437 if (r.executeNesting <= 0 && r.app != null) {
9438 r.app.executingServices.remove(r);
9439 if (r.app.executingServices.size() == 0) {
9440 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9441 }
9442 if (inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009443 if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009444 mStoppingServices.remove(r);
9445 }
9446 updateOomAdjLocked(r.app);
9447 }
9448 }
9449
9450 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009451 String anrMessage = null;
9452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009453 synchronized(this) {
9454 if (proc.executingServices.size() == 0 || proc.thread == null) {
9455 return;
9456 }
9457 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9458 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9459 ServiceRecord timeout = null;
9460 long nextTime = 0;
9461 while (it.hasNext()) {
9462 ServiceRecord sr = it.next();
9463 if (sr.executingStart < maxTime) {
9464 timeout = sr;
9465 break;
9466 }
9467 if (sr.executingStart > nextTime) {
9468 nextTime = sr.executingStart;
9469 }
9470 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009471 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009472 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009473 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009474 } else {
9475 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9476 msg.obj = proc;
9477 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9478 }
9479 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009480
9481 if (anrMessage != null) {
9482 appNotResponding(proc, null, null, anrMessage);
9483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 }
9485
9486 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009487 // BACKUP AND RESTORE
9488 // =========================================================
9489
9490 // Cause the target app to be launched if necessary and its backup agent
9491 // instantiated. The backup agent will invoke backupAgentCreated() on the
9492 // activity manager to announce its creation.
9493 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009494 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009495 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9496
9497 synchronized(this) {
9498 // !!! TODO: currently no check here that we're already bound
9499 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9500 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9501 synchronized (stats) {
9502 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9503 }
9504
9505 BackupRecord r = new BackupRecord(ss, app, backupMode);
9506 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9507 // startProcessLocked() returns existing proc's record if it's already running
9508 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009509 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009510 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009511 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009512 return false;
9513 }
9514
9515 r.app = proc;
9516 mBackupTarget = r;
9517 mBackupAppName = app.packageName;
9518
Christopher Tate6fa95972009-06-05 18:43:55 -07009519 // Try not to kill the process during backup
9520 updateOomAdjLocked(proc);
9521
Christopher Tate181fafa2009-05-14 11:12:14 -07009522 // If the process is already attached, schedule the creation of the backup agent now.
9523 // If it is not yet live, this will be done when it attaches to the framework.
9524 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009525 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009526 try {
9527 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9528 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009529 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009530 }
9531 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009532 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009533 }
9534 // Invariants: at this point, the target app process exists and the application
9535 // is either already running or in the process of coming up. mBackupTarget and
9536 // mBackupAppName describe the app, so that when it binds back to the AM we
9537 // know that it's scheduled for a backup-agent operation.
9538 }
9539
9540 return true;
9541 }
9542
9543 // A backup agent has just come up
9544 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009545 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009546 + " = " + agent);
9547
9548 synchronized(this) {
9549 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009550 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009551 return;
9552 }
9553
Christopher Tate043dadc2009-06-02 16:11:00 -07009554 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009555 try {
9556 IBackupManager bm = IBackupManager.Stub.asInterface(
9557 ServiceManager.getService(Context.BACKUP_SERVICE));
9558 bm.agentConnected(agentPackageName, agent);
9559 } catch (RemoteException e) {
9560 // can't happen; the backup manager service is local
9561 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009562 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009563 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009564 } finally {
9565 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009566 }
9567 }
9568 }
9569
9570 // done with this agent
9571 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009572 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009573 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009574 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009575 return;
9576 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009577
9578 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009579 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009580 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009581 return;
9582 }
9583
Christopher Tate181fafa2009-05-14 11:12:14 -07009584 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009585 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009586 return;
9587 }
9588
Christopher Tate6fa95972009-06-05 18:43:55 -07009589 ProcessRecord proc = mBackupTarget.app;
9590 mBackupTarget = null;
9591 mBackupAppName = null;
9592
9593 // Not backing this app up any more; reset its OOM adjustment
9594 updateOomAdjLocked(proc);
9595
Christopher Tatec7b31e32009-06-10 15:49:30 -07009596 // If the app crashed during backup, 'thread' will be null here
9597 if (proc.thread != null) {
9598 try {
9599 proc.thread.scheduleDestroyBackupAgent(appInfo);
9600 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009601 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009602 e.printStackTrace();
9603 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009604 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009605 }
9606 }
9607 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608 // BROADCASTS
9609 // =========================================================
9610
Josh Bartel7f208742010-02-25 11:01:44 -06009611 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009612 List cur) {
9613 final ContentResolver resolver = mContext.getContentResolver();
9614 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9615 if (list == null) {
9616 return cur;
9617 }
9618 int N = list.size();
9619 for (int i=0; i<N; i++) {
9620 Intent intent = list.get(i);
9621 if (filter.match(resolver, intent, true, TAG) >= 0) {
9622 if (cur == null) {
9623 cur = new ArrayList<Intent>();
9624 }
9625 cur.add(intent);
9626 }
9627 }
9628 return cur;
9629 }
9630
9631 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009632 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009633 + mBroadcastsScheduled);
9634
9635 if (mBroadcastsScheduled) {
9636 return;
9637 }
9638 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9639 mBroadcastsScheduled = true;
9640 }
9641
9642 public Intent registerReceiver(IApplicationThread caller,
9643 IIntentReceiver receiver, IntentFilter filter, String permission) {
9644 synchronized(this) {
9645 ProcessRecord callerApp = null;
9646 if (caller != null) {
9647 callerApp = getRecordForAppLocked(caller);
9648 if (callerApp == null) {
9649 throw new SecurityException(
9650 "Unable to find app for caller " + caller
9651 + " (pid=" + Binder.getCallingPid()
9652 + ") when registering receiver " + receiver);
9653 }
9654 }
9655
9656 List allSticky = null;
9657
9658 // Look for any matching sticky broadcasts...
9659 Iterator actions = filter.actionsIterator();
9660 if (actions != null) {
9661 while (actions.hasNext()) {
9662 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009663 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 }
9665 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009666 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009667 }
9668
9669 // The first sticky in the list is returned directly back to
9670 // the client.
9671 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9672
Joe Onorato8a9b2202010-02-26 18:56:32 -08009673 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009674 + ": " + sticky);
9675
9676 if (receiver == null) {
9677 return sticky;
9678 }
9679
9680 ReceiverList rl
9681 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9682 if (rl == null) {
9683 rl = new ReceiverList(this, callerApp,
9684 Binder.getCallingPid(),
9685 Binder.getCallingUid(), receiver);
9686 if (rl.app != null) {
9687 rl.app.receivers.add(rl);
9688 } else {
9689 try {
9690 receiver.asBinder().linkToDeath(rl, 0);
9691 } catch (RemoteException e) {
9692 return sticky;
9693 }
9694 rl.linkedToDeath = true;
9695 }
9696 mRegisteredReceivers.put(receiver.asBinder(), rl);
9697 }
9698 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9699 rl.add(bf);
9700 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009701 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 }
9703 mReceiverResolver.addFilter(bf);
9704
9705 // Enqueue broadcasts for all existing stickies that match
9706 // this filter.
9707 if (allSticky != null) {
9708 ArrayList receivers = new ArrayList();
9709 receivers.add(bf);
9710
9711 int N = allSticky.size();
9712 for (int i=0; i<N; i++) {
9713 Intent intent = (Intent)allSticky.get(i);
9714 BroadcastRecord r = new BroadcastRecord(intent, null,
9715 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009716 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009717 if (mParallelBroadcasts.size() == 0) {
9718 scheduleBroadcastsLocked();
9719 }
9720 mParallelBroadcasts.add(r);
9721 }
9722 }
9723
9724 return sticky;
9725 }
9726 }
9727
9728 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009729 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009730
9731 boolean doNext = false;
9732
9733 synchronized(this) {
9734 ReceiverList rl
9735 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9736 if (rl != null) {
9737 if (rl.curBroadcast != null) {
9738 BroadcastRecord r = rl.curBroadcast;
9739 doNext = finishReceiverLocked(
9740 receiver.asBinder(), r.resultCode, r.resultData,
9741 r.resultExtras, r.resultAbort, true);
9742 }
9743
9744 if (rl.app != null) {
9745 rl.app.receivers.remove(rl);
9746 }
9747 removeReceiverLocked(rl);
9748 if (rl.linkedToDeath) {
9749 rl.linkedToDeath = false;
9750 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9751 }
9752 }
9753 }
9754
9755 if (!doNext) {
9756 return;
9757 }
9758
9759 final long origId = Binder.clearCallingIdentity();
9760 processNextBroadcast(false);
9761 trimApplications();
9762 Binder.restoreCallingIdentity(origId);
9763 }
9764
9765 void removeReceiverLocked(ReceiverList rl) {
9766 mRegisteredReceivers.remove(rl.receiver.asBinder());
9767 int N = rl.size();
9768 for (int i=0; i<N; i++) {
9769 mReceiverResolver.removeFilter(rl.get(i));
9770 }
9771 }
9772
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009773 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9774 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9775 ProcessRecord r = mLruProcesses.get(i);
9776 if (r.thread != null) {
9777 try {
9778 r.thread.dispatchPackageBroadcast(cmd, packages);
9779 } catch (RemoteException ex) {
9780 }
9781 }
9782 }
9783 }
9784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785 private final int broadcastIntentLocked(ProcessRecord callerApp,
9786 String callerPackage, Intent intent, String resolvedType,
9787 IIntentReceiver resultTo, int resultCode, String resultData,
9788 Bundle map, String requiredPermission,
9789 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9790 intent = new Intent(intent);
9791
Joe Onorato8a9b2202010-02-26 18:56:32 -08009792 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009793 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9794 + " ordered=" + ordered);
9795 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009796 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009797 }
9798
9799 // Handle special intents: if this broadcast is from the package
9800 // manager about a package being removed, we need to remove all of
9801 // its activities from the history stack.
9802 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9803 intent.getAction());
9804 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9805 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009806 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009807 || uidRemoved) {
9808 if (checkComponentPermission(
9809 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9810 callingPid, callingUid, -1)
9811 == PackageManager.PERMISSION_GRANTED) {
9812 if (uidRemoved) {
9813 final Bundle intentExtras = intent.getExtras();
9814 final int uid = intentExtras != null
9815 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9816 if (uid >= 0) {
9817 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9818 synchronized (bs) {
9819 bs.removeUidStatsLocked(uid);
9820 }
9821 }
9822 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009823 // If resources are unvailble just force stop all
9824 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009825 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009826 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9827 if (list != null && (list.length > 0)) {
9828 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009829 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009830 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009831 sendPackageBroadcastLocked(
9832 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009833 }
9834 } else {
9835 Uri data = intent.getData();
9836 String ssp;
9837 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9838 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9839 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009840 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009841 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009842 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9843 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9844 new String[] {ssp});
9845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009846 }
9847 }
9848 }
9849 } else {
9850 String msg = "Permission Denial: " + intent.getAction()
9851 + " broadcast from " + callerPackage + " (pid=" + callingPid
9852 + ", uid=" + callingUid + ")"
9853 + " requires "
9854 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009855 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009856 throw new SecurityException(msg);
9857 }
9858 }
9859
9860 /*
9861 * If this is the time zone changed action, queue up a message that will reset the timezone
9862 * of all currently running processes. This message will get queued up before the broadcast
9863 * happens.
9864 */
9865 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9866 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9867 }
9868
Dianne Hackborn854060af2009-07-09 18:14:31 -07009869 /*
9870 * Prevent non-system code (defined here to be non-persistent
9871 * processes) from sending protected broadcasts.
9872 */
9873 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9874 || callingUid == Process.SHELL_UID || callingUid == 0) {
9875 // Always okay.
9876 } else if (callerApp == null || !callerApp.persistent) {
9877 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009878 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009879 intent.getAction())) {
9880 String msg = "Permission Denial: not allowed to send broadcast "
9881 + intent.getAction() + " from pid="
9882 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009883 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009884 throw new SecurityException(msg);
9885 }
9886 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009887 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009888 return BROADCAST_SUCCESS;
9889 }
9890 }
9891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 // Add to the sticky list if requested.
9893 if (sticky) {
9894 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9895 callingPid, callingUid)
9896 != PackageManager.PERMISSION_GRANTED) {
9897 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9898 + callingPid + ", uid=" + callingUid
9899 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009900 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 throw new SecurityException(msg);
9902 }
9903 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009904 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 + " and enforce permission " + requiredPermission);
9906 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9907 }
9908 if (intent.getComponent() != null) {
9909 throw new SecurityException(
9910 "Sticky broadcasts can't target a specific component");
9911 }
9912 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9913 if (list == null) {
9914 list = new ArrayList<Intent>();
9915 mStickyBroadcasts.put(intent.getAction(), list);
9916 }
9917 int N = list.size();
9918 int i;
9919 for (i=0; i<N; i++) {
9920 if (intent.filterEquals(list.get(i))) {
9921 // This sticky already exists, replace it.
9922 list.set(i, new Intent(intent));
9923 break;
9924 }
9925 }
9926 if (i >= N) {
9927 list.add(new Intent(intent));
9928 }
9929 }
9930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009931 // Figure out who all will receive this broadcast.
9932 List receivers = null;
9933 List<BroadcastFilter> registeredReceivers = null;
9934 try {
9935 if (intent.getComponent() != null) {
9936 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009937 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009938 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009939 if (ai != null) {
9940 receivers = new ArrayList();
9941 ResolveInfo ri = new ResolveInfo();
9942 ri.activityInfo = ai;
9943 receivers.add(ri);
9944 }
9945 } else {
9946 // Need to resolve the intent to interested receivers...
9947 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9948 == 0) {
9949 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009950 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009951 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009952 }
Mihai Preda074edef2009-05-18 17:13:31 +02009953 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009954 }
9955 } catch (RemoteException ex) {
9956 // pm is in same process, this will never happen.
9957 }
9958
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009959 final boolean replacePending =
9960 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9961
Joe Onorato8a9b2202010-02-26 18:56:32 -08009962 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009963 + " replacePending=" + replacePending);
9964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9966 if (!ordered && NR > 0) {
9967 // If we are not serializing this broadcast, then send the
9968 // registered receivers separately so they don't wait for the
9969 // components to be launched.
9970 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9971 callerPackage, callingPid, callingUid, requiredPermission,
9972 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009973 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009974 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009975 TAG, "Enqueueing parallel broadcast " + r
9976 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009977 boolean replaced = false;
9978 if (replacePending) {
9979 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9980 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009981 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009982 "***** DROPPING PARALLEL: " + intent);
9983 mParallelBroadcasts.set(i, r);
9984 replaced = true;
9985 break;
9986 }
9987 }
9988 }
9989 if (!replaced) {
9990 mParallelBroadcasts.add(r);
9991 scheduleBroadcastsLocked();
9992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009993 registeredReceivers = null;
9994 NR = 0;
9995 }
9996
9997 // Merge into one list.
9998 int ir = 0;
9999 if (receivers != null) {
10000 // A special case for PACKAGE_ADDED: do not allow the package
10001 // being added to see this broadcast. This prevents them from
10002 // using this as a back door to get run as soon as they are
10003 // installed. Maybe in the future we want to have a special install
10004 // broadcast or such for apps, but we'd like to deliberately make
10005 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010006 String skipPackages[] = null;
10007 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10008 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10009 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10010 Uri data = intent.getData();
10011 if (data != null) {
10012 String pkgName = data.getSchemeSpecificPart();
10013 if (pkgName != null) {
10014 skipPackages = new String[] { pkgName };
10015 }
10016 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010017 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010018 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010019 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010020 if (skipPackages != null && (skipPackages.length > 0)) {
10021 for (String skipPackage : skipPackages) {
10022 if (skipPackage != null) {
10023 int NT = receivers.size();
10024 for (int it=0; it<NT; it++) {
10025 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10026 if (curt.activityInfo.packageName.equals(skipPackage)) {
10027 receivers.remove(it);
10028 it--;
10029 NT--;
10030 }
10031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032 }
10033 }
10034 }
10035
10036 int NT = receivers != null ? receivers.size() : 0;
10037 int it = 0;
10038 ResolveInfo curt = null;
10039 BroadcastFilter curr = null;
10040 while (it < NT && ir < NR) {
10041 if (curt == null) {
10042 curt = (ResolveInfo)receivers.get(it);
10043 }
10044 if (curr == null) {
10045 curr = registeredReceivers.get(ir);
10046 }
10047 if (curr.getPriority() >= curt.priority) {
10048 // Insert this broadcast record into the final list.
10049 receivers.add(it, curr);
10050 ir++;
10051 curr = null;
10052 it++;
10053 NT++;
10054 } else {
10055 // Skip to the next ResolveInfo in the final list.
10056 it++;
10057 curt = null;
10058 }
10059 }
10060 }
10061 while (ir < NR) {
10062 if (receivers == null) {
10063 receivers = new ArrayList();
10064 }
10065 receivers.add(registeredReceivers.get(ir));
10066 ir++;
10067 }
10068
10069 if ((receivers != null && receivers.size() > 0)
10070 || resultTo != null) {
10071 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10072 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010073 receivers, resultTo, resultCode, resultData, map, ordered,
10074 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010075 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010076 TAG, "Enqueueing ordered broadcast " + r
10077 + ": prev had " + mOrderedBroadcasts.size());
10078 if (DEBUG_BROADCAST) {
10079 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010080 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010081 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010082 boolean replaced = false;
10083 if (replacePending) {
10084 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10085 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010086 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010087 "***** DROPPING ORDERED: " + intent);
10088 mOrderedBroadcasts.set(i, r);
10089 replaced = true;
10090 break;
10091 }
10092 }
10093 }
10094 if (!replaced) {
10095 mOrderedBroadcasts.add(r);
10096 scheduleBroadcastsLocked();
10097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010098 }
10099
10100 return BROADCAST_SUCCESS;
10101 }
10102
10103 public final int broadcastIntent(IApplicationThread caller,
10104 Intent intent, String resolvedType, IIntentReceiver resultTo,
10105 int resultCode, String resultData, Bundle map,
10106 String requiredPermission, boolean serialized, boolean sticky) {
10107 // Refuse possible leaked file descriptors
10108 if (intent != null && intent.hasFileDescriptors() == true) {
10109 throw new IllegalArgumentException("File descriptors passed in Intent");
10110 }
10111
10112 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010113 int flags = intent.getFlags();
10114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010115 if (!mSystemReady) {
10116 // if the caller really truly claims to know what they're doing, go
10117 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010118 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10119 intent = new Intent(intent);
10120 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10121 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080010122 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010123 + " before boot completion");
10124 throw new IllegalStateException("Cannot broadcast before boot completed");
10125 }
10126 }
10127
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010128 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10129 throw new IllegalArgumentException(
10130 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10131 }
10132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10134 final int callingPid = Binder.getCallingPid();
10135 final int callingUid = Binder.getCallingUid();
10136 final long origId = Binder.clearCallingIdentity();
10137 int res = broadcastIntentLocked(callerApp,
10138 callerApp != null ? callerApp.info.packageName : null,
10139 intent, resolvedType, resultTo,
10140 resultCode, resultData, map, requiredPermission, serialized,
10141 sticky, callingPid, callingUid);
10142 Binder.restoreCallingIdentity(origId);
10143 return res;
10144 }
10145 }
10146
10147 int broadcastIntentInPackage(String packageName, int uid,
10148 Intent intent, String resolvedType, IIntentReceiver resultTo,
10149 int resultCode, String resultData, Bundle map,
10150 String requiredPermission, boolean serialized, boolean sticky) {
10151 synchronized(this) {
10152 final long origId = Binder.clearCallingIdentity();
10153 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10154 resultTo, resultCode, resultData, map, requiredPermission,
10155 serialized, sticky, -1, uid);
10156 Binder.restoreCallingIdentity(origId);
10157 return res;
10158 }
10159 }
10160
10161 public final void unbroadcastIntent(IApplicationThread caller,
10162 Intent intent) {
10163 // Refuse possible leaked file descriptors
10164 if (intent != null && intent.hasFileDescriptors() == true) {
10165 throw new IllegalArgumentException("File descriptors passed in Intent");
10166 }
10167
10168 synchronized(this) {
10169 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10170 != PackageManager.PERMISSION_GRANTED) {
10171 String msg = "Permission Denial: unbroadcastIntent() from pid="
10172 + Binder.getCallingPid()
10173 + ", uid=" + Binder.getCallingUid()
10174 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010175 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010176 throw new SecurityException(msg);
10177 }
10178 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10179 if (list != null) {
10180 int N = list.size();
10181 int i;
10182 for (i=0; i<N; i++) {
10183 if (intent.filterEquals(list.get(i))) {
10184 list.remove(i);
10185 break;
10186 }
10187 }
10188 }
10189 }
10190 }
10191
10192 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10193 String resultData, Bundle resultExtras, boolean resultAbort,
10194 boolean explicit) {
10195 if (mOrderedBroadcasts.size() == 0) {
10196 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010197 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010198 }
10199 return false;
10200 }
10201 BroadcastRecord r = mOrderedBroadcasts.get(0);
10202 if (r.receiver == null) {
10203 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010204 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205 }
10206 return false;
10207 }
10208 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010209 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010210 return false;
10211 }
10212 int state = r.state;
10213 r.state = r.IDLE;
10214 if (state == r.IDLE) {
10215 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010216 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 }
10218 }
10219 r.receiver = null;
10220 r.intent.setComponent(null);
10221 if (r.curApp != null) {
10222 r.curApp.curReceiver = null;
10223 }
10224 if (r.curFilter != null) {
10225 r.curFilter.receiverList.curBroadcast = null;
10226 }
10227 r.curFilter = null;
10228 r.curApp = null;
10229 r.curComponent = null;
10230 r.curReceiver = null;
10231 mPendingBroadcast = null;
10232
10233 r.resultCode = resultCode;
10234 r.resultData = resultData;
10235 r.resultExtras = resultExtras;
10236 r.resultAbort = resultAbort;
10237
10238 // We will process the next receiver right now if this is finishing
10239 // an app receiver (which is always asynchronous) or after we have
10240 // come back from calling a receiver.
10241 return state == BroadcastRecord.APP_RECEIVE
10242 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10243 }
10244
10245 public void finishReceiver(IBinder who, int resultCode, String resultData,
10246 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010247 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010248
10249 // Refuse possible leaked file descriptors
10250 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10251 throw new IllegalArgumentException("File descriptors passed in Bundle");
10252 }
10253
10254 boolean doNext;
10255
10256 final long origId = Binder.clearCallingIdentity();
10257
10258 synchronized(this) {
10259 doNext = finishReceiverLocked(
10260 who, resultCode, resultData, resultExtras, resultAbort, true);
10261 }
10262
10263 if (doNext) {
10264 processNextBroadcast(false);
10265 }
10266 trimApplications();
10267
10268 Binder.restoreCallingIdentity(origId);
10269 }
10270
10271 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10272 if (r.nextReceiver > 0) {
10273 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10274 if (curReceiver instanceof BroadcastFilter) {
10275 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010276 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010277 System.identityHashCode(r),
10278 r.intent.getAction(),
10279 r.nextReceiver - 1,
10280 System.identityHashCode(bf));
10281 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010282 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010283 System.identityHashCode(r),
10284 r.intent.getAction(),
10285 r.nextReceiver - 1,
10286 ((ResolveInfo)curReceiver).toString());
10287 }
10288 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010289 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010290 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010291 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 System.identityHashCode(r),
10293 r.intent.getAction(),
10294 r.nextReceiver,
10295 "NONE");
10296 }
10297 }
10298
10299 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010300 ProcessRecord app = null;
10301 String anrMessage = null;
10302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010303 synchronized (this) {
10304 if (mOrderedBroadcasts.size() == 0) {
10305 return;
10306 }
10307 long now = SystemClock.uptimeMillis();
10308 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010309 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010310 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010311 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010312 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010313 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010314 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 return;
10316 }
10317
Joe Onorato8a9b2202010-02-26 18:56:32 -080010318 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010319 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010320 r.anrCount++;
10321
10322 // Current receiver has passed its expiration date.
10323 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010324 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010325 return;
10326 }
10327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010329 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010330 logBroadcastReceiverDiscard(r);
10331 if (curReceiver instanceof BroadcastFilter) {
10332 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10333 if (bf.receiverList.pid != 0
10334 && bf.receiverList.pid != MY_PID) {
10335 synchronized (this.mPidsSelfLocked) {
10336 app = this.mPidsSelfLocked.get(
10337 bf.receiverList.pid);
10338 }
10339 }
10340 } else {
10341 app = r.curApp;
10342 }
10343
10344 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010345 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010346 }
10347
10348 if (mPendingBroadcast == r) {
10349 mPendingBroadcast = null;
10350 }
10351
10352 // Move on to the next receiver.
10353 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10354 r.resultExtras, r.resultAbort, true);
10355 scheduleBroadcastsLocked();
10356 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010357
10358 if (anrMessage != null) {
10359 appNotResponding(app, null, null, anrMessage);
10360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010361 }
10362
10363 private final void processCurBroadcastLocked(BroadcastRecord r,
10364 ProcessRecord app) throws RemoteException {
10365 if (app.thread == null) {
10366 throw new RemoteException();
10367 }
10368 r.receiver = app.thread.asBinder();
10369 r.curApp = app;
10370 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010371 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010372
10373 // Tell the application to launch this receiver.
10374 r.intent.setComponent(r.curComponent);
10375
10376 boolean started = false;
10377 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010378 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379 "Delivering to component " + r.curComponent
10380 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010381 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010382 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10383 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10384 started = true;
10385 } finally {
10386 if (!started) {
10387 r.receiver = null;
10388 r.curApp = null;
10389 app.curReceiver = null;
10390 }
10391 }
10392
10393 }
10394
10395 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010396 Intent intent, int resultCode, String data, Bundle extras,
10397 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010398 if (app != null && app.thread != null) {
10399 // If we have an app thread, do the call through that so it is
10400 // correctly ordered with other one-way calls.
10401 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010402 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010404 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 }
10406 }
10407
10408 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10409 BroadcastFilter filter, boolean ordered) {
10410 boolean skip = false;
10411 if (filter.requiredPermission != null) {
10412 int perm = checkComponentPermission(filter.requiredPermission,
10413 r.callingPid, r.callingUid, -1);
10414 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010415 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010416 + r.intent.toString()
10417 + " from " + r.callerPackage + " (pid="
10418 + r.callingPid + ", uid=" + r.callingUid + ")"
10419 + " requires " + filter.requiredPermission
10420 + " due to registered receiver " + filter);
10421 skip = true;
10422 }
10423 }
10424 if (r.requiredPermission != null) {
10425 int perm = checkComponentPermission(r.requiredPermission,
10426 filter.receiverList.pid, filter.receiverList.uid, -1);
10427 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010428 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010429 + r.intent.toString()
10430 + " to " + filter.receiverList.app
10431 + " (pid=" + filter.receiverList.pid
10432 + ", uid=" + filter.receiverList.uid + ")"
10433 + " requires " + r.requiredPermission
10434 + " due to sender " + r.callerPackage
10435 + " (uid " + r.callingUid + ")");
10436 skip = true;
10437 }
10438 }
10439
10440 if (!skip) {
10441 // If this is not being sent as an ordered broadcast, then we
10442 // don't want to touch the fields that keep track of the current
10443 // state of ordered broadcasts.
10444 if (ordered) {
10445 r.receiver = filter.receiverList.receiver.asBinder();
10446 r.curFilter = filter;
10447 filter.receiverList.curBroadcast = r;
10448 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010449 if (filter.receiverList.app != null) {
10450 // Bump hosting application to no longer be in background
10451 // scheduling class. Note that we can't do that if there
10452 // isn't an app... but we can only be in that case for
10453 // things that directly call the IActivityManager API, which
10454 // are already core system stuff so don't matter for this.
10455 r.curApp = filter.receiverList.app;
10456 filter.receiverList.app.curReceiver = r;
10457 updateOomAdjLocked();
10458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010459 }
10460 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010461 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010462 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010463 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010464 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010465 }
10466 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10467 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010468 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010469 if (ordered) {
10470 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10471 }
10472 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010473 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474 if (ordered) {
10475 r.receiver = null;
10476 r.curFilter = null;
10477 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010478 if (filter.receiverList.app != null) {
10479 filter.receiverList.app.curReceiver = null;
10480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010481 }
10482 }
10483 }
10484 }
10485
Dianne Hackborn12527f92009-11-11 17:39:50 -080010486 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10487 if (r.callingUid < 0) {
10488 // This was from a registerReceiver() call; ignore it.
10489 return;
10490 }
10491 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10492 MAX_BROADCAST_HISTORY-1);
10493 r.finishTime = SystemClock.uptimeMillis();
10494 mBroadcastHistory[0] = r;
10495 }
10496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010497 private final void processNextBroadcast(boolean fromMsg) {
10498 synchronized(this) {
10499 BroadcastRecord r;
10500
Joe Onorato8a9b2202010-02-26 18:56:32 -080010501 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010502 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010503 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010504
10505 updateCpuStats();
10506
10507 if (fromMsg) {
10508 mBroadcastsScheduled = false;
10509 }
10510
10511 // First, deliver any non-serialized broadcasts right away.
10512 while (mParallelBroadcasts.size() > 0) {
10513 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010514 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010515 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010516 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010517 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518 for (int i=0; i<N; i++) {
10519 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010520 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010521 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010522 + target + ": " + r);
10523 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10524 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010525 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010526 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010527 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 }
10529
10530 // Now take care of the next serialized one...
10531
10532 // If we are waiting for a process to come up to handle the next
10533 // broadcast, then do nothing at this point. Just in case, we
10534 // check that the process we're waiting for still exists.
10535 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010536 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010537 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010538 + mPendingBroadcast.curApp);
10539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010540
10541 boolean isDead;
10542 synchronized (mPidsSelfLocked) {
10543 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10544 }
10545 if (!isDead) {
10546 // It's still alive, so keep waiting
10547 return;
10548 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010549 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010550 + " died before responding to broadcast");
10551 mPendingBroadcast = null;
10552 }
10553 }
10554
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010555 boolean looped = false;
10556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010557 do {
10558 if (mOrderedBroadcasts.size() == 0) {
10559 // No more broadcasts pending, so all done!
10560 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010561 if (looped) {
10562 // If we had finished the last ordered broadcast, then
10563 // make sure all processes have correct oom and sched
10564 // adjustments.
10565 updateOomAdjLocked();
10566 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010567 return;
10568 }
10569 r = mOrderedBroadcasts.get(0);
10570 boolean forceReceive = false;
10571
10572 // Ensure that even if something goes awry with the timeout
10573 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010574 // and continue to make progress.
10575 //
10576 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10577 // receivers don't get executed with with timeouts. They're intended for
10578 // one time heavy lifting after system upgrades and can take
10579 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010580 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010581 if (mSystemReady && r.dispatchTime > 0) {
10582 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 if ((numReceivers > 0) &&
10584 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010585 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010586 + " now=" + now
10587 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010588 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010589 + " intent=" + r.intent
10590 + " numReceivers=" + numReceivers
10591 + " nextReceiver=" + r.nextReceiver
10592 + " state=" + r.state);
10593 broadcastTimeout(); // forcibly finish this broadcast
10594 forceReceive = true;
10595 r.state = BroadcastRecord.IDLE;
10596 }
10597 }
10598
10599 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010600 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010601 "processNextBroadcast() called when not idle (state="
10602 + r.state + ")");
10603 return;
10604 }
10605
10606 if (r.receivers == null || r.nextReceiver >= numReceivers
10607 || r.resultAbort || forceReceive) {
10608 // No more receivers for this broadcast! Send the final
10609 // result if requested...
10610 if (r.resultTo != null) {
10611 try {
10612 if (DEBUG_BROADCAST) {
10613 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010614 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 + " seq=" + seq + " app=" + r.callerApp);
10616 }
10617 performReceive(r.callerApp, r.resultTo,
10618 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010619 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010621 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010622 }
10623 }
10624
Joe Onorato8a9b2202010-02-26 18:56:32 -080010625 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010626 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10627
Joe Onorato8a9b2202010-02-26 18:56:32 -080010628 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010629 + r);
10630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010631 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010632 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010633 mOrderedBroadcasts.remove(0);
10634 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010635 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010636 continue;
10637 }
10638 } while (r == null);
10639
10640 // Get the next receiver...
10641 int recIdx = r.nextReceiver++;
10642
10643 // Keep track of when this receiver started, and make sure there
10644 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010645 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010646 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010647 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648
Joe Onorato8a9b2202010-02-26 18:56:32 -080010649 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010650 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010651 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010653 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010654 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010655 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010656 }
10657
10658 Object nextReceiver = r.receivers.get(recIdx);
10659 if (nextReceiver instanceof BroadcastFilter) {
10660 // Simple case: this is a registered receiver who gets
10661 // a direct call.
10662 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010663 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010664 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010665 + filter + ": " + r);
10666 deliverToRegisteredReceiver(r, filter, r.ordered);
10667 if (r.receiver == null || !r.ordered) {
10668 // The receiver has already finished, so schedule to
10669 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010670 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10671 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010672 r.state = BroadcastRecord.IDLE;
10673 scheduleBroadcastsLocked();
10674 }
10675 return;
10676 }
10677
10678 // Hard case: need to instantiate the receiver, possibly
10679 // starting its application process to host it.
10680
10681 ResolveInfo info =
10682 (ResolveInfo)nextReceiver;
10683
10684 boolean skip = false;
10685 int perm = checkComponentPermission(info.activityInfo.permission,
10686 r.callingPid, r.callingUid,
10687 info.activityInfo.exported
10688 ? -1 : info.activityInfo.applicationInfo.uid);
10689 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010690 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 + r.intent.toString()
10692 + " from " + r.callerPackage + " (pid=" + r.callingPid
10693 + ", uid=" + r.callingUid + ")"
10694 + " requires " + info.activityInfo.permission
10695 + " due to receiver " + info.activityInfo.packageName
10696 + "/" + info.activityInfo.name);
10697 skip = true;
10698 }
10699 if (r.callingUid != Process.SYSTEM_UID &&
10700 r.requiredPermission != null) {
10701 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010702 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010703 checkPermission(r.requiredPermission,
10704 info.activityInfo.applicationInfo.packageName);
10705 } catch (RemoteException e) {
10706 perm = PackageManager.PERMISSION_DENIED;
10707 }
10708 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010709 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010710 + r.intent + " to "
10711 + info.activityInfo.applicationInfo.packageName
10712 + " requires " + r.requiredPermission
10713 + " due to sender " + r.callerPackage
10714 + " (uid " + r.callingUid + ")");
10715 skip = true;
10716 }
10717 }
10718 if (r.curApp != null && r.curApp.crashing) {
10719 // If the target process is crashing, just skip it.
10720 skip = true;
10721 }
10722
10723 if (skip) {
10724 r.receiver = null;
10725 r.curFilter = null;
10726 r.state = BroadcastRecord.IDLE;
10727 scheduleBroadcastsLocked();
10728 return;
10729 }
10730
10731 r.state = BroadcastRecord.APP_RECEIVE;
10732 String targetProcess = info.activityInfo.processName;
10733 r.curComponent = new ComponentName(
10734 info.activityInfo.applicationInfo.packageName,
10735 info.activityInfo.name);
10736 r.curReceiver = info.activityInfo;
10737
10738 // Is this receiver's application already running?
10739 ProcessRecord app = getProcessRecordLocked(targetProcess,
10740 info.activityInfo.applicationInfo.uid);
10741 if (app != null && app.thread != null) {
10742 try {
10743 processCurBroadcastLocked(r, app);
10744 return;
10745 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010746 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010747 + r.curComponent, e);
10748 }
10749
10750 // If a dead object exception was thrown -- fall through to
10751 // restart the application.
10752 }
10753
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010754 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 if ((r.curApp=startProcessLocked(targetProcess,
10756 info.activityInfo.applicationInfo, true,
10757 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010758 "broadcast", r.curComponent,
10759 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10760 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 // Ah, this recipient is unavailable. Finish it if necessary,
10762 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010763 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 + info.activityInfo.applicationInfo.packageName + "/"
10765 + info.activityInfo.applicationInfo.uid + " for broadcast "
10766 + r.intent + ": process is bad");
10767 logBroadcastReceiverDiscard(r);
10768 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10769 r.resultExtras, r.resultAbort, true);
10770 scheduleBroadcastsLocked();
10771 r.state = BroadcastRecord.IDLE;
10772 return;
10773 }
10774
10775 mPendingBroadcast = r;
10776 }
10777 }
10778
10779 // =========================================================
10780 // INSTRUMENTATION
10781 // =========================================================
10782
10783 public boolean startInstrumentation(ComponentName className,
10784 String profileFile, int flags, Bundle arguments,
10785 IInstrumentationWatcher watcher) {
10786 // Refuse possible leaked file descriptors
10787 if (arguments != null && arguments.hasFileDescriptors()) {
10788 throw new IllegalArgumentException("File descriptors passed in Bundle");
10789 }
10790
10791 synchronized(this) {
10792 InstrumentationInfo ii = null;
10793 ApplicationInfo ai = null;
10794 try {
10795 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010796 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010798 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 } catch (PackageManager.NameNotFoundException e) {
10800 }
10801 if (ii == null) {
10802 reportStartInstrumentationFailure(watcher, className,
10803 "Unable to find instrumentation info for: " + className);
10804 return false;
10805 }
10806 if (ai == null) {
10807 reportStartInstrumentationFailure(watcher, className,
10808 "Unable to find instrumentation target package: " + ii.targetPackage);
10809 return false;
10810 }
10811
10812 int match = mContext.getPackageManager().checkSignatures(
10813 ii.targetPackage, ii.packageName);
10814 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10815 String msg = "Permission Denial: starting instrumentation "
10816 + className + " from pid="
10817 + Binder.getCallingPid()
10818 + ", uid=" + Binder.getCallingPid()
10819 + " not allowed because package " + ii.packageName
10820 + " does not have a signature matching the target "
10821 + ii.targetPackage;
10822 reportStartInstrumentationFailure(watcher, className, msg);
10823 throw new SecurityException(msg);
10824 }
10825
10826 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010827 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010828 ProcessRecord app = addAppLocked(ai);
10829 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010830 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010831 app.instrumentationProfileFile = profileFile;
10832 app.instrumentationArguments = arguments;
10833 app.instrumentationWatcher = watcher;
10834 app.instrumentationResultClass = className;
10835 Binder.restoreCallingIdentity(origId);
10836 }
10837
10838 return true;
10839 }
10840
10841 /**
10842 * Report errors that occur while attempting to start Instrumentation. Always writes the
10843 * error to the logs, but if somebody is watching, send the report there too. This enables
10844 * the "am" command to report errors with more information.
10845 *
10846 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10847 * @param cn The component name of the instrumentation.
10848 * @param report The error report.
10849 */
10850 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10851 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010852 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010853 try {
10854 if (watcher != null) {
10855 Bundle results = new Bundle();
10856 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10857 results.putString("Error", report);
10858 watcher.instrumentationStatus(cn, -1, results);
10859 }
10860 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010861 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010862 }
10863 }
10864
10865 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10866 if (app.instrumentationWatcher != null) {
10867 try {
10868 // NOTE: IInstrumentationWatcher *must* be oneway here
10869 app.instrumentationWatcher.instrumentationFinished(
10870 app.instrumentationClass,
10871 resultCode,
10872 results);
10873 } catch (RemoteException e) {
10874 }
10875 }
10876 app.instrumentationWatcher = null;
10877 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010878 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010879 app.instrumentationProfileFile = null;
10880 app.instrumentationArguments = null;
10881
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010882 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010883 }
10884
10885 public void finishInstrumentation(IApplicationThread target,
10886 int resultCode, Bundle results) {
10887 // Refuse possible leaked file descriptors
10888 if (results != null && results.hasFileDescriptors()) {
10889 throw new IllegalArgumentException("File descriptors passed in Intent");
10890 }
10891
10892 synchronized(this) {
10893 ProcessRecord app = getRecordForAppLocked(target);
10894 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010895 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010896 return;
10897 }
10898 final long origId = Binder.clearCallingIdentity();
10899 finishInstrumentationLocked(app, resultCode, results);
10900 Binder.restoreCallingIdentity(origId);
10901 }
10902 }
10903
10904 // =========================================================
10905 // CONFIGURATION
10906 // =========================================================
10907
10908 public ConfigurationInfo getDeviceConfigurationInfo() {
10909 ConfigurationInfo config = new ConfigurationInfo();
10910 synchronized (this) {
10911 config.reqTouchScreen = mConfiguration.touchscreen;
10912 config.reqKeyboardType = mConfiguration.keyboard;
10913 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010914 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10915 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010916 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10917 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010918 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10919 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010920 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10921 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010922 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 }
10924 return config;
10925 }
10926
10927 public Configuration getConfiguration() {
10928 Configuration ci;
10929 synchronized(this) {
10930 ci = new Configuration(mConfiguration);
10931 }
10932 return ci;
10933 }
10934
10935 public void updateConfiguration(Configuration values) {
10936 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10937 "updateConfiguration()");
10938
10939 synchronized(this) {
10940 if (values == null && mWindowManager != null) {
10941 // sentinel: fetch the current configuration from the window manager
10942 values = mWindowManager.computeNewConfiguration();
10943 }
10944
10945 final long origId = Binder.clearCallingIdentity();
10946 updateConfigurationLocked(values, null);
10947 Binder.restoreCallingIdentity(origId);
10948 }
10949 }
10950
10951 /**
10952 * Do either or both things: (1) change the current configuration, and (2)
10953 * make sure the given activity is running with the (now) current
10954 * configuration. Returns true if the activity has been left running, or
10955 * false if <var>starting</var> is being destroyed to match the new
10956 * configuration.
10957 */
10958 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010959 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 int changes = 0;
10961
10962 boolean kept = true;
10963
10964 if (values != null) {
10965 Configuration newConfig = new Configuration(mConfiguration);
10966 changes = newConfig.updateFrom(values);
10967 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010968 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010969 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010970 }
10971
Doug Zongker2bec3d42009-12-04 12:52:44 -080010972 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010973
10974 if (values.locale != null) {
10975 saveLocaleLocked(values.locale,
10976 !values.locale.equals(mConfiguration.locale),
10977 values.userSetLocale);
10978 }
10979
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010980 mConfigurationSeq++;
10981 if (mConfigurationSeq <= 0) {
10982 mConfigurationSeq = 1;
10983 }
10984 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010986 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010987
10988 AttributeCache ac = AttributeCache.instance();
10989 if (ac != null) {
10990 ac.updateConfiguration(mConfiguration);
10991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010993 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10994 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10995 msg.obj = new Configuration(mConfiguration);
10996 mHandler.sendMessage(msg);
10997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010999 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11000 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 try {
11002 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011003 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011004 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011005 app.thread.scheduleConfigurationChanged(mConfiguration);
11006 }
11007 } catch (Exception e) {
11008 }
11009 }
11010 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011011 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11012 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11014 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011015 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11016 broadcastIntentLocked(null, null,
11017 new Intent(Intent.ACTION_LOCALE_CHANGED),
11018 null, null, 0, null, null,
11019 null, false, false, MY_PID, Process.SYSTEM_UID);
11020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 }
11022 }
11023
11024 if (changes != 0 && starting == null) {
11025 // If the configuration changed, and the caller is not already
11026 // in the process of starting an activity, then find the top
11027 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011028 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 }
11030
11031 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011032 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 if (kept) {
11034 // If this didn't result in the starting activity being
11035 // destroyed, then we need to make sure at this point that all
11036 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011037 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011038 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011039 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040 }
11041 }
11042
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011043 if (values != null && mWindowManager != null) {
11044 mWindowManager.setNewConfiguration(mConfiguration);
11045 }
11046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 return kept;
11048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049
11050 /**
11051 * Save the locale. You must be inside a synchronized (this) block.
11052 */
11053 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11054 if(isDiff) {
11055 SystemProperties.set("user.language", l.getLanguage());
11056 SystemProperties.set("user.region", l.getCountry());
11057 }
11058
11059 if(isPersist) {
11060 SystemProperties.set("persist.sys.language", l.getLanguage());
11061 SystemProperties.set("persist.sys.country", l.getCountry());
11062 SystemProperties.set("persist.sys.localevar", l.getVariant());
11063 }
11064 }
11065
11066 // =========================================================
11067 // LIFETIME MANAGEMENT
11068 // =========================================================
11069
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011070 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11071 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011073 // This adjustment has already been computed. If we are calling
11074 // from the top, we may have already computed our adjustment with
11075 // an earlier hidden adjustment that isn't really for us... if
11076 // so, use the new hidden adjustment.
11077 if (!recursed && app.hidden) {
11078 app.curAdj = hiddenAdj;
11079 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080 return app.curAdj;
11081 }
11082
11083 if (app.thread == null) {
11084 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011085 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011086 return (app.curAdj=EMPTY_APP_ADJ);
11087 }
11088
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011089 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11090 // The max adjustment doesn't allow this app to be anything
11091 // below foreground, so it is not worth doing work for it.
11092 app.adjType = "fixed";
11093 app.adjSeq = mAdjSeq;
11094 app.curRawAdj = app.maxAdj;
11095 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11096 return (app.curAdj=app.maxAdj);
11097 }
11098
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011099 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011100 app.adjSource = null;
11101 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011102 app.empty = false;
11103 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104
The Android Open Source Project4df24232009-03-05 14:34:35 -080011105 // Determine the importance of the process, starting with most
11106 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011107 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011108 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011110 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011111 // The last app on the list is the foreground app.
11112 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011113 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011114 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011115 } else if (app.instrumentationClass != null) {
11116 // Don't want to kill running instrumentation.
11117 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011118 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011119 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011120 } else if (app.persistentActivities > 0) {
11121 // Special persistent activities... shouldn't be used these days.
11122 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011123 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011124 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011125 } else if (app.curReceiver != null ||
11126 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11127 // An app that is currently receiving a broadcast also
11128 // counts as being in the foreground.
11129 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011130 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011131 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011132 } else if (app.executingServices.size() > 0) {
11133 // An app that is currently executing a service callback also
11134 // counts as being in the foreground.
11135 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011136 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011137 app.adjType = "exec-service";
11138 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011139 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011140 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011141 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011142 app.adjType = "foreground-service";
11143 } else if (app.forcingToForeground != null) {
11144 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011145 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011146 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011147 app.adjType = "force-foreground";
11148 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011149 } else if (app == mHeavyWeightProcess) {
11150 // We don't want to kill the current heavy-weight process.
11151 adj = HEAVY_WEIGHT_APP_ADJ;
11152 schedGroup = Process.THREAD_GROUP_DEFAULT;
11153 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011154 } else if (app == mHomeProcess) {
11155 // This process is hosting what we currently consider to be the
11156 // home app, so we don't want to let it go into the background.
11157 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011158 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011159 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011160 } else if ((N=app.activities.size()) != 0) {
11161 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011162 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011163 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011164 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011165 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011166 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011167 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011168 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011170 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011172 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011173 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011174 break;
11175 }
11176 }
11177 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011178 // A very not-needed process. If this is lower in the lru list,
11179 // we will push it in to the empty bucket.
11180 app.hidden = true;
11181 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011182 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011183 adj = hiddenAdj;
11184 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 }
11186
Joe Onorato8a9b2202010-02-26 18:56:32 -080011187 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011188
The Android Open Source Project4df24232009-03-05 14:34:35 -080011189 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011190 // there are applications dependent on our services or providers, but
11191 // this gives us a baseline and makes sure we don't get into an
11192 // infinite recursion.
11193 app.adjSeq = mAdjSeq;
11194 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011195
Christopher Tate6fa95972009-06-05 18:43:55 -070011196 if (mBackupTarget != null && app == mBackupTarget.app) {
11197 // If possible we want to avoid killing apps while they're being backed up
11198 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011199 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011200 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011201 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011202 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011203 }
11204 }
11205
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011206 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11207 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011208 final long now = SystemClock.uptimeMillis();
11209 // This process is more important if the top activity is
11210 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011211 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011213 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 if (s.startRequested) {
11215 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11216 // This service has seen some activity within
11217 // recent memory, so we will keep its process ahead
11218 // of the background processes.
11219 if (adj > SECONDARY_SERVER_ADJ) {
11220 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011221 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011222 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011223 }
11224 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011225 // If we have let the service slide into the background
11226 // state, still have some text describing what it is doing
11227 // even though the service no longer has an impact.
11228 if (adj > SECONDARY_SERVER_ADJ) {
11229 app.adjType = "started-bg-services";
11230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011232 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11233 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011234 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 = s.connections.values().iterator();
11236 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011237 ArrayList<ConnectionRecord> clist = kt.next();
11238 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11239 // XXX should compute this based on the max of
11240 // all connected clients.
11241 ConnectionRecord cr = clist.get(i);
11242 if (cr.binding.client == app) {
11243 // Binding to ourself is not interesting.
11244 continue;
11245 }
11246 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11247 ProcessRecord client = cr.binding.client;
11248 int myHiddenAdj = hiddenAdj;
11249 if (myHiddenAdj > client.hiddenAdj) {
11250 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11251 myHiddenAdj = client.hiddenAdj;
11252 } else {
11253 myHiddenAdj = VISIBLE_APP_ADJ;
11254 }
11255 }
11256 int clientAdj = computeOomAdjLocked(
11257 client, myHiddenAdj, TOP_APP, true);
11258 if (adj > clientAdj) {
11259 adj = clientAdj >= VISIBLE_APP_ADJ
11260 ? clientAdj : VISIBLE_APP_ADJ;
11261 if (!client.hidden) {
11262 app.hidden = false;
11263 }
11264 app.adjType = "service";
11265 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11266 .REASON_SERVICE_IN_USE;
11267 app.adjSource = cr.binding.client;
11268 app.adjTarget = s.name;
11269 }
11270 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11271 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11272 schedGroup = Process.THREAD_GROUP_DEFAULT;
11273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 }
11275 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011276 ActivityRecord a = cr.activity;
11277 //if (a != null) {
11278 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11279 //}
11280 if (a != null && adj > FOREGROUND_APP_ADJ &&
11281 (a.state == ActivityState.RESUMED
11282 || a.state == ActivityState.PAUSING)) {
11283 adj = FOREGROUND_APP_ADJ;
11284 schedGroup = Process.THREAD_GROUP_DEFAULT;
11285 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011286 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011287 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11288 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011289 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011290 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011292 }
11293 }
11294 }
11295 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011296
11297 // Finally, f this process has active services running in it, we
11298 // would like to avoid killing it unless it would prevent the current
11299 // application from running. By default we put the process in
11300 // with the rest of the background processes; as we scan through
11301 // its services we may bump it up from there.
11302 if (adj > hiddenAdj) {
11303 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011304 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011305 app.adjType = "bg-services";
11306 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011307 }
11308
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011309 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11310 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011311 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011312 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11313 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011314 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011315 if (cpr.clients.size() != 0) {
11316 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11317 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11318 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011319 if (client == app) {
11320 // Being our own client is not interesting.
11321 continue;
11322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011323 int myHiddenAdj = hiddenAdj;
11324 if (myHiddenAdj > client.hiddenAdj) {
11325 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11326 myHiddenAdj = client.hiddenAdj;
11327 } else {
11328 myHiddenAdj = FOREGROUND_APP_ADJ;
11329 }
11330 }
11331 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011332 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011333 if (adj > clientAdj) {
11334 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011335 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011336 if (!client.hidden) {
11337 app.hidden = false;
11338 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011339 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011340 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11341 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011342 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011343 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011344 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011345 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11346 schedGroup = Process.THREAD_GROUP_DEFAULT;
11347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011348 }
11349 }
11350 // If the provider has external (non-framework) process
11351 // dependencies, ensure that its adjustment is at least
11352 // FOREGROUND_APP_ADJ.
11353 if (cpr.externals != 0) {
11354 if (adj > FOREGROUND_APP_ADJ) {
11355 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011356 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011357 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011358 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011359 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 }
11361 }
11362 }
11363 }
11364
11365 app.curRawAdj = adj;
11366
Joe Onorato8a9b2202010-02-26 18:56:32 -080011367 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011368 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11369 if (adj > app.maxAdj) {
11370 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011371 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011372 schedGroup = Process.THREAD_GROUP_DEFAULT;
11373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011374 }
11375
11376 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011377 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011379 return adj;
11380 }
11381
11382 /**
11383 * Ask a given process to GC right now.
11384 */
11385 final void performAppGcLocked(ProcessRecord app) {
11386 try {
11387 app.lastRequestedGc = SystemClock.uptimeMillis();
11388 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011389 if (app.reportLowMemory) {
11390 app.reportLowMemory = false;
11391 app.thread.scheduleLowMemory();
11392 } else {
11393 app.thread.processInBackground();
11394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011395 }
11396 } catch (Exception e) {
11397 // whatever.
11398 }
11399 }
11400
11401 /**
11402 * Returns true if things are idle enough to perform GCs.
11403 */
Josh Bartel7f208742010-02-25 11:01:44 -060011404 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 return mParallelBroadcasts.size() == 0
11406 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011407 && (mSleeping || (mMainStack.mResumedActivity != null &&
11408 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011409 }
11410
11411 /**
11412 * Perform GCs on all processes that are waiting for it, but only
11413 * if things are idle.
11414 */
11415 final void performAppGcsLocked() {
11416 final int N = mProcessesToGc.size();
11417 if (N <= 0) {
11418 return;
11419 }
Josh Bartel7f208742010-02-25 11:01:44 -060011420 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011421 while (mProcessesToGc.size() > 0) {
11422 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011423 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011424 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11425 <= SystemClock.uptimeMillis()) {
11426 // To avoid spamming the system, we will GC processes one
11427 // at a time, waiting a few seconds between each.
11428 performAppGcLocked(proc);
11429 scheduleAppGcsLocked();
11430 return;
11431 } else {
11432 // It hasn't been long enough since we last GCed this
11433 // process... put it in the list to wait for its time.
11434 addProcessToGcListLocked(proc);
11435 break;
11436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011437 }
11438 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011439
11440 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011441 }
11442 }
11443
11444 /**
11445 * If all looks good, perform GCs on all processes waiting for them.
11446 */
11447 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011448 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011449 performAppGcsLocked();
11450 return;
11451 }
11452 // Still not idle, wait some more.
11453 scheduleAppGcsLocked();
11454 }
11455
11456 /**
11457 * Schedule the execution of all pending app GCs.
11458 */
11459 final void scheduleAppGcsLocked() {
11460 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011461
11462 if (mProcessesToGc.size() > 0) {
11463 // Schedule a GC for the time to the next process.
11464 ProcessRecord proc = mProcessesToGc.get(0);
11465 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11466
11467 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11468 long now = SystemClock.uptimeMillis();
11469 if (when < (now+GC_TIMEOUT)) {
11470 when = now + GC_TIMEOUT;
11471 }
11472 mHandler.sendMessageAtTime(msg, when);
11473 }
11474 }
11475
11476 /**
11477 * Add a process to the array of processes waiting to be GCed. Keeps the
11478 * list in sorted order by the last GC time. The process can't already be
11479 * on the list.
11480 */
11481 final void addProcessToGcListLocked(ProcessRecord proc) {
11482 boolean added = false;
11483 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11484 if (mProcessesToGc.get(i).lastRequestedGc <
11485 proc.lastRequestedGc) {
11486 added = true;
11487 mProcessesToGc.add(i+1, proc);
11488 break;
11489 }
11490 }
11491 if (!added) {
11492 mProcessesToGc.add(0, proc);
11493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011494 }
11495
11496 /**
11497 * Set up to ask a process to GC itself. This will either do it
11498 * immediately, or put it on the list of processes to gc the next
11499 * time things are idle.
11500 */
11501 final void scheduleAppGcLocked(ProcessRecord app) {
11502 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011503 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011504 return;
11505 }
11506 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011507 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011508 scheduleAppGcsLocked();
11509 }
11510 }
11511
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011512 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11513 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11514 if (mLastWakeLockCheckTime == 0) {
11515 doKills = false;
11516 }
11517 if (stats.isScreenOn()) {
11518 doKills = false;
11519 }
11520 final long curRealtime = SystemClock.elapsedRealtime();
11521 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11522 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011523 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011524 doKills = false;
11525 }
11526 int i = mLruProcesses.size();
11527 while (i > 0) {
11528 i--;
11529 ProcessRecord app = mLruProcesses.get(i);
11530 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11531 long wtime;
11532 synchronized (stats) {
11533 wtime = stats.getProcessWakeTime(app.info.uid,
11534 app.pid, curRealtime);
11535 }
11536 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011537 if (false) {
11538 StringBuilder sb = new StringBuilder(128);
11539 sb.append("Wake for ");
11540 app.toShortString(sb);
11541 sb.append(": over ");
11542 TimeUtils.formatDuration(timeSince, sb);
11543 sb.append(" used ");
11544 TimeUtils.formatDuration(timeUsed, sb);
11545 sb.append(" (");
11546 sb.append((timeUsed*100)/timeSince);
11547 sb.append("%)");
11548 Slog.i(TAG, sb.toString());
11549 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011550 // If a process has held a wake lock for more
11551 // than 50% of the time during this period,
11552 // that sounds pad. Kill!
11553 if (doKills && timeSince > 0
11554 && ((timeUsed*100)/timeSince) >= 50) {
11555 Slog.i(TAG, "Excessive wake lock in " + app.processName
11556 + " (pid " + app.pid + "): held " + timeUsed
11557 + " during " + timeSince);
11558 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11559 app.processName, app.setAdj, "excessive wake lock");
11560 Process.killProcessQuiet(app.pid);
11561 } else {
11562 app.lastWakeTime = wtime;
11563 }
11564 }
11565 }
11566 }
11567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011568 private final boolean updateOomAdjLocked(
11569 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11570 app.hiddenAdj = hiddenAdj;
11571
11572 if (app.thread == null) {
11573 return true;
11574 }
11575
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011576 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011577
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011578 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011579 if (app.curRawAdj != app.setRawAdj) {
11580 if (app.curRawAdj > FOREGROUND_APP_ADJ
11581 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11582 // If this app is transitioning from foreground to
11583 // non-foreground, have it do a gc.
11584 scheduleAppGcLocked(app);
11585 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11586 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11587 // Likewise do a gc when an app is moving in to the
11588 // background (such as a service stopping).
11589 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011590 // And note its current wake lock time.
11591 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11592 synchronized (stats) {
11593 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11594 app.pid, SystemClock.elapsedRealtime());
11595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011596 }
11597 app.setRawAdj = app.curRawAdj;
11598 }
11599 if (adj != app.setAdj) {
11600 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011601 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 TAG, "Set app " + app.processName +
11603 " oom adj to " + adj);
11604 app.setAdj = adj;
11605 } else {
11606 return false;
11607 }
11608 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011609 if (app.setSchedGroup != app.curSchedGroup) {
11610 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011611 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011612 "Setting process group of " + app.processName
11613 + " to " + app.curSchedGroup);
11614 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011615 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011616 try {
11617 Process.setProcessGroup(app.pid, app.curSchedGroup);
11618 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011619 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011620 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011621 e.printStackTrace();
11622 } finally {
11623 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011624 }
11625 }
11626 if (false) {
11627 if (app.thread != null) {
11628 try {
11629 app.thread.setSchedulingGroup(app.curSchedGroup);
11630 } catch (RemoteException e) {
11631 }
11632 }
11633 }
11634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011635 }
11636
11637 return true;
11638 }
11639
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011640 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011641 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011642 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011643 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011645 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011646 }
11647 }
11648 return resumedActivity;
11649 }
11650
11651 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011652 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11654 int curAdj = app.curAdj;
11655 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11656 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11657
11658 mAdjSeq++;
11659
11660 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11661 if (res) {
11662 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11663 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11664 if (nowHidden != wasHidden) {
11665 // Changed to/from hidden state, so apps after it in the LRU
11666 // list may also be changed.
11667 updateOomAdjLocked();
11668 }
11669 }
11670 return res;
11671 }
11672
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011673 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011674 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011675 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11677
11678 if (false) {
11679 RuntimeException e = new RuntimeException();
11680 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011681 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011682 }
11683
11684 mAdjSeq++;
11685
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011686 // Let's determine how many processes we have running vs.
11687 // how many slots we have for background processes; we may want
11688 // to put multiple processes in a slot of there are enough of
11689 // them.
11690 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11691 int factor = (mLruProcesses.size()-4)/numSlots;
11692 if (factor < 1) factor = 1;
11693 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011694 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011696 // First try updating the OOM adjustment for each of the
11697 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011698 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011699 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11700 while (i > 0) {
11701 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011702 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011703 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011704 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011705 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011707 step++;
11708 if (step >= factor) {
11709 step = 0;
11710 curHiddenAdj++;
11711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011713 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011714 if (!app.killedBackground) {
11715 numHidden++;
11716 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011717 Slog.i(TAG, "No longer want " + app.processName
11718 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011719 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11720 app.processName, app.setAdj, "too many background");
11721 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011722 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011723 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011724 }
11725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011726 } else {
11727 didOomAdj = false;
11728 }
11729 }
11730
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011731 // If we return false, we will fall back on killing processes to
11732 // have a fixed limit. Do this if a limit has been requested; else
11733 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011734 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11735 }
11736
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011737 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 synchronized (this) {
11739 int i;
11740
11741 // First remove any unused application processes whose package
11742 // has been removed.
11743 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11744 final ProcessRecord app = mRemovedProcesses.get(i);
11745 if (app.activities.size() == 0
11746 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011747 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011748 TAG, "Exiting empty application process "
11749 + app.processName + " ("
11750 + (app.thread != null ? app.thread.asBinder() : null)
11751 + ")\n");
11752 if (app.pid > 0 && app.pid != MY_PID) {
11753 Process.killProcess(app.pid);
11754 } else {
11755 try {
11756 app.thread.scheduleExit();
11757 } catch (Exception e) {
11758 // Ignore exceptions.
11759 }
11760 }
11761 cleanUpApplicationRecordLocked(app, false, -1);
11762 mRemovedProcesses.remove(i);
11763
11764 if (app.persistent) {
11765 if (app.persistent) {
11766 addAppLocked(app.info);
11767 }
11768 }
11769 }
11770 }
11771
11772 // Now try updating the OOM adjustment for each of the
11773 // application processes based on their current state.
11774 // If the setOomAdj() API is not supported, then go with our
11775 // back-up plan...
11776 if (!updateOomAdjLocked()) {
11777
11778 // Count how many processes are running services.
11779 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011780 for (i=mLruProcesses.size()-1; i>=0; i--) {
11781 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011782
11783 if (app.persistent || app.services.size() != 0
11784 || app.curReceiver != null
11785 || app.persistentActivities > 0) {
11786 // Don't count processes holding services against our
11787 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011788 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011789 TAG, "Not trimming app " + app + " with services: "
11790 + app.services);
11791 numServiceProcs++;
11792 }
11793 }
11794
11795 int curMaxProcs = mProcessLimit;
11796 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11797 if (mAlwaysFinishActivities) {
11798 curMaxProcs = 1;
11799 }
11800 curMaxProcs += numServiceProcs;
11801
11802 // Quit as many processes as we can to get down to the desired
11803 // process count. First remove any processes that no longer
11804 // have activites running in them.
11805 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011806 i<mLruProcesses.size()
11807 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011809 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011810 // Quit an application only if it is not currently
11811 // running any activities.
11812 if (!app.persistent && app.activities.size() == 0
11813 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011814 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011815 TAG, "Exiting empty application process "
11816 + app.processName + " ("
11817 + (app.thread != null ? app.thread.asBinder() : null)
11818 + ")\n");
11819 if (app.pid > 0 && app.pid != MY_PID) {
11820 Process.killProcess(app.pid);
11821 } else {
11822 try {
11823 app.thread.scheduleExit();
11824 } catch (Exception e) {
11825 // Ignore exceptions.
11826 }
11827 }
11828 // todo: For now we assume the application is not buggy
11829 // or evil, and will quit as a result of our request.
11830 // Eventually we need to drive this off of the death
11831 // notification, and kill the process if it takes too long.
11832 cleanUpApplicationRecordLocked(app, false, i);
11833 i--;
11834 }
11835 }
11836
11837 // If we still have too many processes, now from the least
11838 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011839 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011840 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011841 " of " + curMaxProcs + " processes");
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 the application only if we have a state saved for
11848 // all of its activities.
11849 boolean canQuit = !app.persistent && app.curReceiver == null
11850 && app.services.size() == 0
11851 && app.persistentActivities == 0;
11852 int NUMA = app.activities.size();
11853 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011854 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011855 TAG, "Looking to quit " + app.processName);
11856 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011857 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011858 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011859 TAG, " " + r.intent.getComponent().flattenToShortString()
11860 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11861 canQuit = (r.haveState || !r.stateNotNeeded)
11862 && !r.visible && r.stopped;
11863 }
11864 if (canQuit) {
11865 // Finish all of the activities, and then the app itself.
11866 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011867 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011868 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011869 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011870 }
11871 r.resultTo = null;
11872 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011873 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011874 + app.processName + " ("
11875 + (app.thread != null ? app.thread.asBinder() : null)
11876 + ")\n");
11877 if (app.pid > 0 && app.pid != MY_PID) {
11878 Process.killProcess(app.pid);
11879 } else {
11880 try {
11881 app.thread.scheduleExit();
11882 } catch (Exception e) {
11883 // Ignore exceptions.
11884 }
11885 }
11886 // todo: For now we assume the application is not buggy
11887 // or evil, and will quit as a result of our request.
11888 // Eventually we need to drive this off of the death
11889 // notification, and kill the process if it takes too long.
11890 cleanUpApplicationRecordLocked(app, false, i);
11891 i--;
11892 //dump();
11893 }
11894 }
11895
11896 }
11897
11898 int curMaxActivities = MAX_ACTIVITIES;
11899 if (mAlwaysFinishActivities) {
11900 curMaxActivities = 1;
11901 }
11902
11903 // Finally, if there are too many activities now running, try to
11904 // finish as many as we can to get back down to the limit.
11905 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011906 i<mMainStack.mLRUActivities.size()
11907 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011908 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011909 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011910 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011911
11912 // We can finish this one if we have its icicle saved and
11913 // it is not persistent.
11914 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11915 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011916 final int origSize = mMainStack.mLRUActivities.size();
11917 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011918
11919 // This will remove it from the LRU list, so keep
11920 // our index at the same value. Note that this check to
11921 // see if the size changes is just paranoia -- if
11922 // something unexpected happens, we don't want to end up
11923 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011924 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011925 i--;
11926 }
11927 }
11928 }
11929 }
11930 }
11931
11932 /** This method sends the specified signal to each of the persistent apps */
11933 public void signalPersistentProcesses(int sig) throws RemoteException {
11934 if (sig != Process.SIGNAL_USR1) {
11935 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11936 }
11937
11938 synchronized (this) {
11939 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11940 != PackageManager.PERMISSION_GRANTED) {
11941 throw new SecurityException("Requires permission "
11942 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11943 }
11944
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011945 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11946 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011947 if (r.thread != null && r.persistent) {
11948 Process.sendSignal(r.pid, sig);
11949 }
11950 }
11951 }
11952 }
11953
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011954 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011955 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011956
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011957 try {
11958 synchronized (this) {
11959 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11960 // its own permission.
11961 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11962 != PackageManager.PERMISSION_GRANTED) {
11963 throw new SecurityException("Requires permission "
11964 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011965 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011966
11967 if (start && fd == null) {
11968 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011969 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011970
11971 ProcessRecord proc = null;
11972 try {
11973 int pid = Integer.parseInt(process);
11974 synchronized (mPidsSelfLocked) {
11975 proc = mPidsSelfLocked.get(pid);
11976 }
11977 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011978 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011979
11980 if (proc == null) {
11981 HashMap<String, SparseArray<ProcessRecord>> all
11982 = mProcessNames.getMap();
11983 SparseArray<ProcessRecord> procs = all.get(process);
11984 if (procs != null && procs.size() > 0) {
11985 proc = procs.valueAt(0);
11986 }
11987 }
11988
11989 if (proc == null || proc.thread == null) {
11990 throw new IllegalArgumentException("Unknown process: " + process);
11991 }
11992
11993 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11994 if (isSecure) {
11995 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11996 throw new SecurityException("Process not debuggable: " + proc);
11997 }
11998 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011999
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012000 proc.thread.profilerControl(start, path, fd);
12001 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012002 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012003 }
12004 } catch (RemoteException e) {
12005 throw new IllegalStateException("Process disappeared");
12006 } finally {
12007 if (fd != null) {
12008 try {
12009 fd.close();
12010 } catch (IOException e) {
12011 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012012 }
12013 }
12014 }
12015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012016 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12017 public void monitor() {
12018 synchronized (this) { }
12019 }
12020}