blob: 483941d070035748e48bf17a48c4e12a799ac995 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
58import android.content.Intent;
59import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070060import android.content.IIntentReceiver;
61import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070062import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.content.pm.ActivityInfo;
64import android.content.pm.ApplicationInfo;
65import android.content.pm.ConfigurationInfo;
66import android.content.pm.IPackageDataObserver;
67import android.content.pm.IPackageManager;
68import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080069import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070071import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.ProviderInfo;
73import android.content.pm.ResolveInfo;
74import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070075import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.res.Configuration;
77import android.graphics.Bitmap;
78import android.net.Uri;
79import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080080import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070082import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.FileUtils;
87import android.os.Handler;
88import android.os.IBinder;
89import android.os.IPermissionController;
90import android.os.Looper;
91import android.os.Message;
92import android.os.Parcel;
93import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070095import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.RemoteException;
97import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070098import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.SystemClock;
100import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.Config;
103import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800104import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800105import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.util.PrintWriterPrinter;
107import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700108import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.view.Gravity;
110import android.view.LayoutInflater;
111import android.view.View;
112import android.view.WindowManager;
113import android.view.WindowManagerPolicy;
114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.File;
116import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200118import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800119import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.PrintWriter;
121import java.lang.IllegalStateException;
122import java.lang.ref.WeakReference;
123import java.util.ArrayList;
124import java.util.HashMap;
125import java.util.HashSet;
126import java.util.Iterator;
127import java.util.List;
128import java.util.Locale;
129import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700130import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700131import java.util.concurrent.atomic.AtomicBoolean;
132import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700134public final class ActivityManagerService extends ActivityManagerNative
135 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 static final String TAG = "ActivityManager";
137 static final boolean DEBUG = false;
138 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
139 static final boolean DEBUG_SWITCH = localLOGV || false;
140 static final boolean DEBUG_TASKS = localLOGV || false;
141 static final boolean DEBUG_PAUSE = localLOGV || false;
142 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
143 static final boolean DEBUG_TRANSITION = localLOGV || false;
144 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700145 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 static final boolean DEBUG_SERVICE = localLOGV || false;
147 static final boolean DEBUG_VISBILITY = localLOGV || false;
148 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700149 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800150 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700152 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700153 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700154 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean VALIDATE_TOKENS = false;
156 static final boolean SHOW_ACTIVITY_START_TIME = true;
157
158 // Control over CPU and battery monitoring.
159 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
160 static final boolean MONITOR_CPU_USAGE = true;
161 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
162 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
163 static final boolean MONITOR_THREAD_CPU_USAGE = false;
164
Dianne Hackborn1655be42009-05-08 14:29:01 -0700165 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700166 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 private static final String SYSTEM_SECURE = "ro.secure";
169
170 // This is the maximum number of application processes we would like
171 // to have running. Due to the asynchronous nature of things, we can
172 // temporarily go beyond this limit.
173 static final int MAX_PROCESSES = 2;
174
175 // Set to false to leave processes running indefinitely, relying on
176 // the kernel killing them as resources are required.
177 static final boolean ENFORCE_PROCESS_LIMIT = false;
178
179 // This is the maximum number of activities that we would like to have
180 // running at a given time.
181 static final int MAX_ACTIVITIES = 20;
182
183 // Maximum number of recent tasks that we can remember.
184 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700185
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700186 // Amount of time after a call to stopAppSwitches() during which we will
187 // prevent further untrusted switches from happening.
188 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
190 // How long we wait for a launched process to attach to the activity manager
191 // before we decide it's never going to come up for real.
192 static final int PROC_START_TIMEOUT = 10*1000;
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 // How long to wait after going idle before forcing apps to GC.
195 static final int GC_TIMEOUT = 5*1000;
196
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700197 // The minimum amount of time between successive GC requests for a process.
198 static final int GC_MIN_INTERVAL = 60*1000;
199
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700200 // The rate at which we check for apps using excessive wake locks -- 15 mins.
201 static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 // How long we allow a receiver to run before giving up on it.
204 static final int BROADCAST_TIMEOUT = 10*1000;
205
206 // How long we wait for a service to finish executing.
207 static final int SERVICE_TIMEOUT = 20*1000;
208
209 // How long a service needs to be running until restarting its process
210 // is no longer considered to be a relaunch of the service.
211 static final int SERVICE_RESTART_DURATION = 5*1000;
212
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700213 // How long a service needs to be running until it will start back at
214 // SERVICE_RESTART_DURATION after being killed.
215 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
216
217 // Multiplying factor to increase restart duration time by, for each time
218 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
219 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
220
221 // The minimum amount of time between restarting services that we allow.
222 // That is, when multiple services are restarting, we won't allow each
223 // to restart less than this amount of time from the last one.
224 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 // Maximum amount of time for there to be no activity on a service before
227 // we consider it non-essential and allow its process to go on the
228 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700229 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230
231 // How long we wait until we timeout on key dispatching.
232 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
233
234 // The minimum time we allow between crashes, for us to consider this
235 // application to be bad and stop and its services and reject broadcasts.
236 static final int MIN_CRASH_INTERVAL = 60*1000;
237
238 // How long we wait until we timeout on key dispatching during instrumentation.
239 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
240
241 // OOM adjustments for processes in various states:
242
243 // This is a process without anything currently running in it. Definitely
244 // the first to go! Value set in system/rootdir/init.rc on startup.
245 // This value is initalized in the constructor, careful when refering to
246 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800247 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248
249 // This is a process only hosting activities that are not visible,
250 // so it can be killed without any disruption. Value set in
251 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800252 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 static int HIDDEN_APP_MIN_ADJ;
254
The Android Open Source Project4df24232009-03-05 14:34:35 -0800255 // This is a process holding the home application -- we want to try
256 // avoiding killing it, even if it would normally be in the background,
257 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800258 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800259
Christopher Tate6fa95972009-06-05 18:43:55 -0700260 // This is a process currently hosting a backup operation. Killing it
261 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800262 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 // This is a process holding a secondary server -- killing it will not
265 // have much of an impact as far as the user is concerned. Value set in
266 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800267 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700269 // This is a process with a heavy-weight application. It is in the
270 // background, but we want to try to avoid killing it. Value set in
271 // system/rootdir/init.rc on startup.
272 static final int HEAVY_WEIGHT_APP_ADJ;
273
274 // This is a process only hosting components that are perceptible to the
275 // user, and we really want to avoid killing them, but they are not
276 // immediately visible. An example is background music playback. Value set in
277 // system/rootdir/init.rc on startup.
278 static final int PERCEPTIBLE_APP_ADJ;
279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 // This is a process only hosting activities that are visible to the
281 // user, so we'd prefer they don't disappear. Value set in
282 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800283 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
285 // This is the process running the current foreground app. We'd really
286 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800287 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 // This is a process running a core server, such as telephony. Definitely
290 // don't want to kill it, but doing so is not completely fatal.
291 static final int CORE_SERVER_ADJ = -12;
292
293 // The system process runs at the default adjustment.
294 static final int SYSTEM_ADJ = -16;
295
296 // Memory pages are 4K.
297 static final int PAGE_SIZE = 4*1024;
298
299 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800300 static final int EMPTY_APP_MEM;
301 static final int HIDDEN_APP_MEM;
302 static final int HOME_APP_MEM;
303 static final int BACKUP_APP_MEM;
304 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700305 static final int HEAVY_WEIGHT_APP_MEM;
306 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800307 static final int VISIBLE_APP_MEM;
308 static final int FOREGROUND_APP_MEM;
309
310 // The minimum number of hidden apps we want to be able to keep around,
311 // without empty apps being able to push them out of memory.
312 static final int MIN_HIDDEN_APPS = 2;
313
Dianne Hackborn8633e682010-04-22 16:03:41 -0700314 // The maximum number of hidden processes we will keep around before
315 // killing them; this is just a control to not let us go too crazy with
316 // keeping around processes on devices with large amounts of RAM.
317 static final int MAX_HIDDEN_APPS = 15;
318
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800319 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700320 // been idle for less than 15 seconds.
321 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800322
323 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700324 // been idle for less than 120 seconds.
325 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800326
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700327 static int getIntProp(String name, boolean allowZero) {
328 String str = SystemProperties.get(name);
329 if (str == null) {
330 throw new IllegalArgumentException("Property not defined: " + name);
331 }
332 int val = Integer.valueOf(str);
333 if (val == 0 && !allowZero) {
334 throw new IllegalArgumentException("Property must not be zero: " + name);
335 }
336 return val;
337 }
338
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339 static {
340 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700341 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
342 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
343 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
344 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
345 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
346 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
347 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
348 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
349 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
350 // These days we use the last empty slot for hidden apps as well.
351 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
352 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
353 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
354 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
355 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
356 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
357 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
358 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
359 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
360 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362
Dan Egnor42471dd2010-01-07 17:25:22 -0800363 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364
365 static final String[] EMPTY_STRING_ARRAY = new String[0];
366
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700367 public ActivityStack mMainStack;
368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700370 * Description of a request to start a new activity, which has been held
371 * due to app switches being disabled.
372 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700373 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700374 ActivityRecord r;
375 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700376 Uri[] grantedUriPermissions;
377 int grantedMode;
378 boolean onlyIfNeeded;
379 }
380
381 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
382 = new ArrayList<PendingActivityLaunch>();
383
384 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 * List of all active broadcasts that are to be executed immediately
386 * (without waiting for another broadcast to finish). Currently this only
387 * contains broadcasts to registered receivers, to avoid spinning up
388 * a bunch of processes to execute IntentReceiver components.
389 */
390 final ArrayList<BroadcastRecord> mParallelBroadcasts
391 = new ArrayList<BroadcastRecord>();
392
393 /**
394 * List of all active broadcasts that are to be executed one at a time.
395 * The object at the top of the list is the currently activity broadcasts;
396 * those after it are waiting for the top to finish..
397 */
398 final ArrayList<BroadcastRecord> mOrderedBroadcasts
399 = new ArrayList<BroadcastRecord>();
400
401 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800402 * Historical data of past broadcasts, for debugging.
403 */
404 static final int MAX_BROADCAST_HISTORY = 100;
405 final BroadcastRecord[] mBroadcastHistory
406 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
407
408 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 * Set when we current have a BROADCAST_INTENT_MSG in flight.
410 */
411 boolean mBroadcastsScheduled = false;
412
413 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 * Activity we have told the window manager to have key focus.
415 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700416 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700417 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 * List of intents that were used to start the most recent tasks.
419 */
420 final ArrayList<TaskRecord> mRecentTasks
421 = new ArrayList<TaskRecord>();
422
423 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 * All of the applications we currently have running organized by name.
425 * The keys are strings of the application package name (as
426 * returned by the package manager), and the keys are ApplicationRecord
427 * objects.
428 */
429 final ProcessMap<ProcessRecord> mProcessNames
430 = new ProcessMap<ProcessRecord>();
431
432 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700433 * The currently running heavy-weight process, if any.
434 */
435 ProcessRecord mHeavyWeightProcess = null;
436
437 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 * The last time that various processes have crashed.
439 */
440 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
441
442 /**
443 * Set of applications that we consider to be bad, and will reject
444 * incoming broadcasts from (which the user has no control over).
445 * Processes are added to this set when they have crashed twice within
446 * a minimum amount of time; they are removed from it when they are
447 * later restarted (hopefully due to some user action). The value is the
448 * time it was added to the list.
449 */
450 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
451
452 /**
453 * All of the processes we currently have running organized by pid.
454 * The keys are the pid running the application.
455 *
456 * <p>NOTE: This object is protected by its own lock, NOT the global
457 * activity manager lock!
458 */
459 final SparseArray<ProcessRecord> mPidsSelfLocked
460 = new SparseArray<ProcessRecord>();
461
462 /**
463 * All of the processes that have been forced to be foreground. The key
464 * is the pid of the caller who requested it (we hold a death
465 * link on it).
466 */
467 abstract class ForegroundToken implements IBinder.DeathRecipient {
468 int pid;
469 IBinder token;
470 }
471 final SparseArray<ForegroundToken> mForegroundProcesses
472 = new SparseArray<ForegroundToken>();
473
474 /**
475 * List of records for processes that someone had tried to start before the
476 * system was ready. We don't start them at that point, but ensure they
477 * are started by the time booting is complete.
478 */
479 final ArrayList<ProcessRecord> mProcessesOnHold
480 = new ArrayList<ProcessRecord>();
481
482 /**
483 * List of records for processes that we have started and are waiting
484 * for them to call back. This is really only needed when running in
485 * single processes mode, in which case we do not have a unique pid for
486 * each process.
487 */
488 final ArrayList<ProcessRecord> mStartingProcesses
489 = new ArrayList<ProcessRecord>();
490
491 /**
492 * List of persistent applications that are in the process
493 * of being started.
494 */
495 final ArrayList<ProcessRecord> mPersistentStartingProcesses
496 = new ArrayList<ProcessRecord>();
497
498 /**
499 * Processes that are being forcibly torn down.
500 */
501 final ArrayList<ProcessRecord> mRemovedProcesses
502 = new ArrayList<ProcessRecord>();
503
504 /**
505 * List of running applications, sorted by recent usage.
506 * The first entry in the list is the least recently used.
507 * It contains ApplicationRecord objects. This list does NOT include
508 * any persistent application records (since we never want to exit them).
509 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800510 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 = new ArrayList<ProcessRecord>();
512
513 /**
514 * List of processes that should gc as soon as things are idle.
515 */
516 final ArrayList<ProcessRecord> mProcessesToGc
517 = new ArrayList<ProcessRecord>();
518
519 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800520 * This is the process holding what we currently consider to be
521 * the "home" activity.
522 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700523 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800524
525 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 * Set of PendingResultRecord objects that are currently active.
527 */
528 final HashSet mPendingResultRecords = new HashSet();
529
530 /**
531 * Set of IntentSenderRecord objects that are currently active.
532 */
533 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
534 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
535
536 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700537 * Fingerprints (String.hashCode()) of stack traces that we've
538 * already logged DropBox entries for. Guarded by itself. If
539 * something (rogue user app) forces this over
540 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
541 */
542 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
543 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
544
545 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700546 * Strict Mode background batched logging state.
547 *
548 * The string buffer is guarded by itself, and its lock is also
549 * used to determine if another batched write is already
550 * in-flight.
551 */
552 private final StringBuilder mStrictModeBuffer = new StringBuilder();
553
554 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 * Intent broadcast that we have tried to start, but are
556 * waiting for its application's process to be created. We only
557 * need one (instead of a list) because we always process broadcasts
558 * one at a time, so no others can be started while waiting for this
559 * one.
560 */
561 BroadcastRecord mPendingBroadcast = null;
562
563 /**
564 * Keeps track of all IIntentReceivers that have been registered for
565 * broadcasts. Hash keys are the receiver IBinder, hash value is
566 * a ReceiverList.
567 */
568 final HashMap mRegisteredReceivers = new HashMap();
569
570 /**
571 * Resolver for broadcast intents to registered receivers.
572 * Holds BroadcastFilter (subclass of IntentFilter).
573 */
574 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
575 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
576 @Override
577 protected boolean allowFilterResult(
578 BroadcastFilter filter, List<BroadcastFilter> dest) {
579 IBinder target = filter.receiverList.receiver.asBinder();
580 for (int i=dest.size()-1; i>=0; i--) {
581 if (dest.get(i).receiverList.receiver.asBinder() == target) {
582 return false;
583 }
584 }
585 return true;
586 }
587 };
588
589 /**
590 * State of all active sticky broadcasts. Keys are the action of the
591 * sticky Intent, values are an ArrayList of all broadcasted intents with
592 * that action (which should usually be one).
593 */
594 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
595 new HashMap<String, ArrayList<Intent>>();
596
597 /**
598 * All currently running services.
599 */
600 final HashMap<ComponentName, ServiceRecord> mServices =
601 new HashMap<ComponentName, ServiceRecord>();
602
603 /**
604 * All currently running services indexed by the Intent used to start them.
605 */
606 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
607 new HashMap<Intent.FilterComparison, ServiceRecord>();
608
609 /**
610 * All currently bound service connections. Keys are the IBinder of
611 * the client's IServiceConnection.
612 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700613 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
614 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615
616 /**
617 * List of services that we have been asked to start,
618 * but haven't yet been able to. It is used to hold start requests
619 * while waiting for their corresponding application thread to get
620 * going.
621 */
622 final ArrayList<ServiceRecord> mPendingServices
623 = new ArrayList<ServiceRecord>();
624
625 /**
626 * List of services that are scheduled to restart following a crash.
627 */
628 final ArrayList<ServiceRecord> mRestartingServices
629 = new ArrayList<ServiceRecord>();
630
631 /**
632 * List of services that are in the process of being stopped.
633 */
634 final ArrayList<ServiceRecord> mStoppingServices
635 = new ArrayList<ServiceRecord>();
636
637 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700638 * Backup/restore process management
639 */
640 String mBackupAppName = null;
641 BackupRecord mBackupTarget = null;
642
643 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 * List of PendingThumbnailsRecord objects of clients who are still
645 * waiting to receive all of the thumbnails for a task.
646 */
647 final ArrayList mPendingThumbnails = new ArrayList();
648
649 /**
650 * List of HistoryRecord objects that have been finished and must
651 * still report back to a pending thumbnail receiver.
652 */
653 final ArrayList mCancelledThumbnails = new ArrayList();
654
655 /**
656 * All of the currently running global content providers. Keys are a
657 * string containing the provider name and values are a
658 * ContentProviderRecord object containing the data about it. Note
659 * that a single provider may be published under multiple names, so
660 * there may be multiple entries here for a single one in mProvidersByClass.
661 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700662 final HashMap<String, ContentProviderRecord> mProvidersByName
663 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664
665 /**
666 * All of the currently running global content providers. Keys are a
667 * string containing the provider's implementation class and values are a
668 * ContentProviderRecord object containing the data about it.
669 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700670 final HashMap<String, ContentProviderRecord> mProvidersByClass
671 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672
673 /**
674 * List of content providers who have clients waiting for them. The
675 * application is currently being launched and the provider will be
676 * removed from this list once it is published.
677 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700678 final ArrayList<ContentProviderRecord> mLaunchingProviders
679 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680
681 /**
682 * Global set of specific Uri permissions that have been granted.
683 */
684 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
685 = new SparseArray<HashMap<Uri, UriPermission>>();
686
687 /**
688 * Thread-local storage used to carry caller permissions over through
689 * indirect content-provider access.
690 * @see #ActivityManagerService.openContentUri()
691 */
692 private class Identity {
693 public int pid;
694 public int uid;
695
696 Identity(int _pid, int _uid) {
697 pid = _pid;
698 uid = _uid;
699 }
700 }
701 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
702
703 /**
704 * All information we have collected about the runtime performance of
705 * any user id that can impact battery performance.
706 */
707 final BatteryStatsService mBatteryStatsService;
708
709 /**
710 * information about component usage
711 */
712 final UsageStatsService mUsageStatsService;
713
714 /**
715 * Current configuration information. HistoryRecord objects are given
716 * a reference to this object to indicate which configuration they are
717 * currently running in, so this object must be kept immutable.
718 */
719 Configuration mConfiguration = new Configuration();
720
721 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800722 * Current sequencing integer of the configuration, for skipping old
723 * configurations.
724 */
725 int mConfigurationSeq = 0;
726
727 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700728 * Hardware-reported OpenGLES version.
729 */
730 final int GL_ES_VERSION;
731
732 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 * List of initialization arguments to pass to all processes when binding applications to them.
734 * For example, references to the commonly used services.
735 */
736 HashMap<String, IBinder> mAppBindArgs;
737
738 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700739 * Temporary to avoid allocations. Protected by main lock.
740 */
741 final StringBuilder mStringBuilder = new StringBuilder(256);
742
743 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 * Used to control how we initialize the service.
745 */
746 boolean mStartRunning = false;
747 ComponentName mTopComponent;
748 String mTopAction;
749 String mTopData;
750 boolean mSystemReady = false;
751 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700752 boolean mWaitingUpdate = false;
753 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700754 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700755 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756
757 Context mContext;
758
759 int mFactoryTest;
760
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700761 boolean mCheckedForSetup;
762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700764 * The time at which we will allow normal application switches again,
765 * after a call to {@link #stopAppSwitches()}.
766 */
767 long mAppSwitchesAllowedTime;
768
769 /**
770 * This is set to true after the first switch after mAppSwitchesAllowedTime
771 * is set; any switches after that will clear the time.
772 */
773 boolean mDidAppSwitch;
774
775 /**
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700776 * Last time (in realtime) at which we checked for wake lock usage.
777 */
778 long mLastWakeLockCheckTime;
779
780 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 * Set while we are wanting to sleep, to prevent any
782 * activities from being started/resumed.
783 */
784 boolean mSleeping = false;
785
786 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700787 * Set if we are shutting down the system, similar to sleeping.
788 */
789 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790
791 /**
792 * Task identifier that activities are currently being started
793 * in. Incremented each time a new task is created.
794 * todo: Replace this with a TokenSpace class that generates non-repeating
795 * integers that won't wrap.
796 */
797 int mCurTask = 1;
798
799 /**
800 * Current sequence id for oom_adj computation traversal.
801 */
802 int mAdjSeq = 0;
803
804 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700805 * Current sequence id for process LRU updating.
806 */
807 int mLruSeq = 0;
808
809 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
811 * is set, indicating the user wants processes started in such a way
812 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
813 * running in each process (thus no pre-initialized process, etc).
814 */
815 boolean mSimpleProcessManagement = false;
816
817 /**
818 * System monitoring: number of processes that died since the last
819 * N procs were started.
820 */
821 int[] mProcDeaths = new int[20];
822
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700823 /**
824 * This is set if we had to do a delayed dexopt of an app before launching
825 * it, to increasing the ANR timeouts in that case.
826 */
827 boolean mDidDexOpt;
828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 String mDebugApp = null;
830 boolean mWaitForDebugger = false;
831 boolean mDebugTransient = false;
832 String mOrigDebugApp = null;
833 boolean mOrigWaitForDebugger = false;
834 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700835 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700837 final RemoteCallbackList<IActivityWatcher> mWatchers
838 = new RemoteCallbackList<IActivityWatcher>();
839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 /**
841 * Callback of last caller to {@link #requestPss}.
842 */
843 Runnable mRequestPssCallback;
844
845 /**
846 * Remaining processes for which we are waiting results from the last
847 * call to {@link #requestPss}.
848 */
849 final ArrayList<ProcessRecord> mRequestPssList
850 = new ArrayList<ProcessRecord>();
851
852 /**
853 * Runtime statistics collection thread. This object's lock is used to
854 * protect all related state.
855 */
856 final Thread mProcessStatsThread;
857
858 /**
859 * Used to collect process stats when showing not responding dialog.
860 * Protected by mProcessStatsThread.
861 */
862 final ProcessStats mProcessStats = new ProcessStats(
863 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700864 final AtomicLong mLastCpuTime = new AtomicLong(0);
865 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 long mLastWriteTime = 0;
868
869 /**
870 * Set to true after the system has finished booting.
871 */
872 boolean mBooted = false;
873
874 int mProcessLimit = 0;
875
876 WindowManagerService mWindowManager;
877
878 static ActivityManagerService mSelf;
879 static ActivityThread mSystemThread;
880
881 private final class AppDeathRecipient implements IBinder.DeathRecipient {
882 final ProcessRecord mApp;
883 final int mPid;
884 final IApplicationThread mAppThread;
885
886 AppDeathRecipient(ProcessRecord app, int pid,
887 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800888 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 TAG, "New death recipient " + this
890 + " for thread " + thread.asBinder());
891 mApp = app;
892 mPid = pid;
893 mAppThread = thread;
894 }
895
896 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800897 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 TAG, "Death received in " + this
899 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 synchronized(ActivityManagerService.this) {
901 appDiedLocked(mApp, mPid, mAppThread);
902 }
903 }
904 }
905
906 static final int SHOW_ERROR_MSG = 1;
907 static final int SHOW_NOT_RESPONDING_MSG = 2;
908 static final int SHOW_FACTORY_ERROR_MSG = 3;
909 static final int UPDATE_CONFIGURATION_MSG = 4;
910 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
911 static final int WAIT_FOR_DEBUGGER_MSG = 6;
912 static final int BROADCAST_INTENT_MSG = 7;
913 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 static final int SERVICE_TIMEOUT_MSG = 12;
915 static final int UPDATE_TIME_ZONE = 13;
916 static final int SHOW_UID_ERROR_MSG = 14;
917 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700919 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700920 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800921 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700922 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
923 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700924 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700925 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926
927 AlertDialog mUidAlert;
928
929 final Handler mHandler = new Handler() {
930 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800931 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 //}
933
934 public void handleMessage(Message msg) {
935 switch (msg.what) {
936 case SHOW_ERROR_MSG: {
937 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 synchronized (ActivityManagerService.this) {
939 ProcessRecord proc = (ProcessRecord)data.get("app");
940 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800941 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 return;
943 }
944 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700945 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800946 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 d.show();
948 proc.crashDialog = d;
949 } else {
950 // The device is asleep, so just pretend that the user
951 // saw a crash dialog and hit "force quit".
952 res.set(0);
953 }
954 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700955
956 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 } break;
958 case SHOW_NOT_RESPONDING_MSG: {
959 synchronized (ActivityManagerService.this) {
960 HashMap data = (HashMap) msg.obj;
961 ProcessRecord proc = (ProcessRecord)data.get("app");
962 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800963 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 return;
965 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800966
967 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
968 null, null, 0, null, null, null,
969 false, false, MY_PID, Process.SYSTEM_UID);
970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700972 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 d.show();
974 proc.anrDialog = d;
975 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700976
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700977 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700979 case SHOW_STRICT_MODE_VIOLATION_MSG: {
980 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
981 synchronized (ActivityManagerService.this) {
982 ProcessRecord proc = (ProcessRecord) data.get("app");
983 if (proc == null) {
984 Slog.e(TAG, "App not found when showing strict mode dialog.");
985 break;
986 }
987 if (proc.crashDialog != null) {
988 Slog.e(TAG, "App already has strict mode dialog: " + proc);
989 return;
990 }
991 AppErrorResult res = (AppErrorResult) data.get("result");
992 if (!mSleeping && !mShuttingDown) {
993 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
994 d.show();
995 proc.crashDialog = d;
996 } else {
997 // The device is asleep, so just pretend that the user
998 // saw a crash dialog and hit "force quit".
999 res.set(0);
1000 }
1001 }
1002 ensureBootCompleted();
1003 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 case SHOW_FACTORY_ERROR_MSG: {
1005 Dialog d = new FactoryErrorDialog(
1006 mContext, msg.getData().getCharSequence("msg"));
1007 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001008 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 } break;
1010 case UPDATE_CONFIGURATION_MSG: {
1011 final ContentResolver resolver = mContext.getContentResolver();
1012 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1013 } break;
1014 case GC_BACKGROUND_PROCESSES_MSG: {
1015 synchronized (ActivityManagerService.this) {
1016 performAppGcsIfAppropriateLocked();
1017 }
1018 } break;
1019 case WAIT_FOR_DEBUGGER_MSG: {
1020 synchronized (ActivityManagerService.this) {
1021 ProcessRecord app = (ProcessRecord)msg.obj;
1022 if (msg.arg1 != 0) {
1023 if (!app.waitedForDebugger) {
1024 Dialog d = new AppWaitingForDebuggerDialog(
1025 ActivityManagerService.this,
1026 mContext, app);
1027 app.waitDialog = d;
1028 app.waitedForDebugger = true;
1029 d.show();
1030 }
1031 } else {
1032 if (app.waitDialog != null) {
1033 app.waitDialog.dismiss();
1034 app.waitDialog = null;
1035 }
1036 }
1037 }
1038 } break;
1039 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001040 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 TAG, "Received BROADCAST_INTENT_MSG");
1042 processNextBroadcast(true);
1043 } break;
1044 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001045 if (mDidDexOpt) {
1046 mDidDexOpt = false;
1047 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1048 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1049 return;
1050 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001051 // Only process broadcast timeouts if the system is ready. That way
1052 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1053 // to do heavy lifting for system up
1054 if (mSystemReady) {
1055 broadcastTimeout();
1056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001059 if (mDidDexOpt) {
1060 mDidDexOpt = false;
1061 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1062 nmsg.obj = msg.obj;
1063 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1064 return;
1065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 serviceTimeout((ProcessRecord)msg.obj);
1067 } break;
1068 case UPDATE_TIME_ZONE: {
1069 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001070 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1071 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 if (r.thread != null) {
1073 try {
1074 r.thread.updateTimeZone();
1075 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001076 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 }
1078 }
1079 }
1080 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001081 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 case SHOW_UID_ERROR_MSG: {
1083 // XXX This is a temporary dialog, no need to localize.
1084 AlertDialog d = new BaseErrorDialog(mContext);
1085 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1086 d.setCancelable(false);
1087 d.setTitle("System UIDs Inconsistent");
1088 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1089 d.setButton("I'm Feeling Lucky",
1090 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1091 mUidAlert = d;
1092 d.show();
1093 } break;
1094 case IM_FEELING_LUCKY_MSG: {
1095 if (mUidAlert != null) {
1096 mUidAlert.dismiss();
1097 mUidAlert = null;
1098 }
1099 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001101 if (mDidDexOpt) {
1102 mDidDexOpt = false;
1103 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1104 nmsg.obj = msg.obj;
1105 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1106 return;
1107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 ProcessRecord app = (ProcessRecord)msg.obj;
1109 synchronized (ActivityManagerService.this) {
1110 processStartTimedOutLocked(app);
1111 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001112 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001113 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1114 synchronized (ActivityManagerService.this) {
1115 doPendingActivityLaunchesLocked(true);
1116 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001117 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001118 case KILL_APPLICATION_MSG: {
1119 synchronized (ActivityManagerService.this) {
1120 int uid = msg.arg1;
1121 boolean restart = (msg.arg2 == 1);
1122 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001123 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001124 }
1125 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001126 case FINALIZE_PENDING_INTENT_MSG: {
1127 ((PendingIntentRecord)msg.obj).completeFinalize();
1128 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001129 case POST_HEAVY_NOTIFICATION_MSG: {
1130 INotificationManager inm = NotificationManager.getService();
1131 if (inm == null) {
1132 return;
1133 }
1134
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001135 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001136 ProcessRecord process = root.app;
1137 if (process == null) {
1138 return;
1139 }
1140
1141 try {
1142 Context context = mContext.createPackageContext(process.info.packageName, 0);
1143 String text = mContext.getString(R.string.heavy_weight_notification,
1144 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1145 Notification notification = new Notification();
1146 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1147 notification.when = 0;
1148 notification.flags = Notification.FLAG_ONGOING_EVENT;
1149 notification.tickerText = text;
1150 notification.defaults = 0; // please be quiet
1151 notification.sound = null;
1152 notification.vibrate = null;
1153 notification.setLatestEventInfo(context, text,
1154 mContext.getText(R.string.heavy_weight_notification_detail),
1155 PendingIntent.getActivity(mContext, 0, root.intent,
1156 PendingIntent.FLAG_CANCEL_CURRENT));
1157
1158 try {
1159 int[] outId = new int[1];
1160 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1161 notification, outId);
1162 } catch (RuntimeException e) {
1163 Slog.w(ActivityManagerService.TAG,
1164 "Error showing notification for heavy-weight app", e);
1165 } catch (RemoteException e) {
1166 }
1167 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001168 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001169 }
1170 } break;
1171 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1172 INotificationManager inm = NotificationManager.getService();
1173 if (inm == null) {
1174 return;
1175 }
1176 try {
1177 inm.cancelNotification("android",
1178 R.string.heavy_weight_notification);
1179 } catch (RuntimeException e) {
1180 Slog.w(ActivityManagerService.TAG,
1181 "Error canceling notification for service", e);
1182 } catch (RemoteException e) {
1183 }
1184 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001185 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1186 synchronized (ActivityManagerService.this) {
1187 checkExcessiveWakeLocksLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001188 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001189 if (mSleeping) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001190 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1191 sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001192 }
1193 }
1194 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 }
1196 }
1197 };
1198
1199 public static void setSystemProcess() {
1200 try {
1201 ActivityManagerService m = mSelf;
1202
1203 ServiceManager.addService("activity", m);
1204 ServiceManager.addService("meminfo", new MemBinder(m));
1205 if (MONITOR_CPU_USAGE) {
1206 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 ServiceManager.addService("permission", new PermissionController(m));
1209
1210 ApplicationInfo info =
1211 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001212 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001213 mSystemThread.installSystemApplicationInfo(info);
1214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 synchronized (mSelf) {
1216 ProcessRecord app = mSelf.newProcessRecordLocked(
1217 mSystemThread.getApplicationThread(), info,
1218 info.processName);
1219 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001220 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 app.maxAdj = SYSTEM_ADJ;
1222 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1223 synchronized (mSelf.mPidsSelfLocked) {
1224 mSelf.mPidsSelfLocked.put(app.pid, app);
1225 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001226 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 }
1228 } catch (PackageManager.NameNotFoundException e) {
1229 throw new RuntimeException(
1230 "Unable to find android system package", e);
1231 }
1232 }
1233
1234 public void setWindowManager(WindowManagerService wm) {
1235 mWindowManager = wm;
1236 }
1237
1238 public static final Context main(int factoryTest) {
1239 AThread thr = new AThread();
1240 thr.start();
1241
1242 synchronized (thr) {
1243 while (thr.mService == null) {
1244 try {
1245 thr.wait();
1246 } catch (InterruptedException e) {
1247 }
1248 }
1249 }
1250
1251 ActivityManagerService m = thr.mService;
1252 mSelf = m;
1253 ActivityThread at = ActivityThread.systemMain();
1254 mSystemThread = at;
1255 Context context = at.getSystemContext();
1256 m.mContext = context;
1257 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001258 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259
1260 m.mBatteryStatsService.publish(context);
1261 m.mUsageStatsService.publish(context);
1262
1263 synchronized (thr) {
1264 thr.mReady = true;
1265 thr.notifyAll();
1266 }
1267
1268 m.startRunning(null, null, null, null);
1269
1270 return context;
1271 }
1272
1273 public static ActivityManagerService self() {
1274 return mSelf;
1275 }
1276
1277 static class AThread extends Thread {
1278 ActivityManagerService mService;
1279 boolean mReady = false;
1280
1281 public AThread() {
1282 super("ActivityManager");
1283 }
1284
1285 public void run() {
1286 Looper.prepare();
1287
1288 android.os.Process.setThreadPriority(
1289 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001290 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291
1292 ActivityManagerService m = new ActivityManagerService();
1293
1294 synchronized (this) {
1295 mService = m;
1296 notifyAll();
1297 }
1298
1299 synchronized (this) {
1300 while (!mReady) {
1301 try {
1302 wait();
1303 } catch (InterruptedException e) {
1304 }
1305 }
1306 }
1307
1308 Looper.loop();
1309 }
1310 }
1311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312 static class MemBinder extends Binder {
1313 ActivityManagerService mActivityManagerService;
1314 MemBinder(ActivityManagerService activityManagerService) {
1315 mActivityManagerService = activityManagerService;
1316 }
1317
1318 @Override
1319 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1320 ActivityManagerService service = mActivityManagerService;
1321 ArrayList<ProcessRecord> procs;
1322 synchronized (mActivityManagerService) {
1323 if (args != null && args.length > 0
1324 && args[0].charAt(0) != '-') {
1325 procs = new ArrayList<ProcessRecord>();
1326 int pid = -1;
1327 try {
1328 pid = Integer.parseInt(args[0]);
1329 } catch (NumberFormatException e) {
1330
1331 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001332 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1333 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 if (proc.pid == pid) {
1335 procs.add(proc);
1336 } else if (proc.processName.equals(args[0])) {
1337 procs.add(proc);
1338 }
1339 }
1340 if (procs.size() <= 0) {
1341 pw.println("No process found for: " + args[0]);
1342 return;
1343 }
1344 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001345 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 }
1347 }
1348 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1349 }
1350 }
1351
1352 static class CpuBinder extends Binder {
1353 ActivityManagerService mActivityManagerService;
1354 CpuBinder(ActivityManagerService activityManagerService) {
1355 mActivityManagerService = activityManagerService;
1356 }
1357
1358 @Override
1359 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1360 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001361 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1362 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1363 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 }
1365 }
1366 }
1367
1368 private ActivityManagerService() {
1369 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1370 if (v != null && Integer.getInteger(v) != 0) {
1371 mSimpleProcessManagement = true;
1372 }
1373 v = System.getenv("ANDROID_DEBUG_APP");
1374 if (v != null) {
1375 mSimpleProcessManagement = true;
1376 }
1377
Joe Onorato8a9b2202010-02-26 18:56:32 -08001378 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 File dataDir = Environment.getDataDirectory();
1381 File systemDir = new File(dataDir, "system");
1382 systemDir.mkdirs();
1383 mBatteryStatsService = new BatteryStatsService(new File(
1384 systemDir, "batterystats.bin").toString());
1385 mBatteryStatsService.getActiveStatistics().readLocked();
1386 mBatteryStatsService.getActiveStatistics().writeLocked();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001387 mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
1388 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001390 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001391 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392
Jack Palevichb90d28c2009-07-22 15:35:24 -07001393 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1394 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1395
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001396 mConfiguration.setToDefaults();
1397 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 mProcessStats.init();
1399
1400 // Add ourself to the Watchdog monitors.
1401 Watchdog.getInstance().addMonitor(this);
1402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 mProcessStatsThread = new Thread("ProcessStats") {
1404 public void run() {
1405 while (true) {
1406 try {
1407 try {
1408 synchronized(this) {
1409 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001410 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001412 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 // + ", write delay=" + nextWriteDelay);
1414 if (nextWriteDelay < nextCpuDelay) {
1415 nextCpuDelay = nextWriteDelay;
1416 }
1417 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001418 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 this.wait(nextCpuDelay);
1420 }
1421 }
1422 } catch (InterruptedException e) {
1423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 updateCpuStatsNow();
1425 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001426 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 }
1428 }
1429 }
1430 };
1431 mProcessStatsThread.start();
1432 }
1433
1434 @Override
1435 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1436 throws RemoteException {
1437 try {
1438 return super.onTransact(code, data, reply, flags);
1439 } catch (RuntimeException e) {
1440 // The activity manager only throws security exceptions, so let's
1441 // log all others.
1442 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001443 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 }
1445 throw e;
1446 }
1447 }
1448
1449 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001450 final long now = SystemClock.uptimeMillis();
1451 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1452 return;
1453 }
1454 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1455 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 mProcessStatsThread.notify();
1457 }
1458 }
1459 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 void updateCpuStatsNow() {
1462 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001463 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 final long now = SystemClock.uptimeMillis();
1465 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001468 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1469 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 haveNewCpuStats = true;
1471 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001472 //Slog.i(TAG, mProcessStats.printCurrentState());
1473 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 // + mProcessStats.getTotalCpuPercent() + "%");
1475
Joe Onorato8a9b2202010-02-26 18:56:32 -08001476 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 if ("true".equals(SystemProperties.get("events.cpu"))) {
1478 int user = mProcessStats.getLastUserTime();
1479 int system = mProcessStats.getLastSystemTime();
1480 int iowait = mProcessStats.getLastIoWaitTime();
1481 int irq = mProcessStats.getLastIrqTime();
1482 int softIrq = mProcessStats.getLastSoftIrqTime();
1483 int idle = mProcessStats.getLastIdleTime();
1484
1485 int total = user + system + iowait + irq + softIrq + idle;
1486 if (total == 0) total = 1;
1487
Doug Zongker2bec3d42009-12-04 12:52:44 -08001488 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 ((user+system+iowait+irq+softIrq) * 100) / total,
1490 (user * 100) / total,
1491 (system * 100) / total,
1492 (iowait * 100) / total,
1493 (irq * 100) / total,
1494 (softIrq * 100) / total);
1495 }
1496 }
1497
Amith Yamasanie43530a2009-08-21 13:11:37 -07001498 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001499 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001500 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 synchronized(mPidsSelfLocked) {
1502 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001503 if (mOnBattery) {
1504 int perc = bstats.startAddingCpuLocked();
1505 int totalUTime = 0;
1506 int totalSTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 final int N = mProcessStats.countWorkingStats();
1508 for (int i=0; i<N; i++) {
1509 ProcessStats.Stats st
1510 = mProcessStats.getWorkingStats(i);
1511 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001512 int otherUTime = (st.rel_utime*perc)/100;
1513 int otherSTime = (st.rel_stime*perc)/100;
1514 totalUTime += otherUTime;
1515 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 if (pr != null) {
1517 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001518 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1519 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001520 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001521 } else {
1522 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001523 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001524 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001525 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1526 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001527 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 }
1530 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001531 bstats.finishAddingCpuLocked(perc, totalUTime,
1532 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 }
1534 }
1535 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1538 mLastWriteTime = now;
1539 mBatteryStatsService.getActiveStatistics().writeLocked();
1540 }
1541 }
1542 }
1543 }
1544
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001545 @Override
1546 public void batteryNeedsCpuUpdate() {
1547 updateCpuStatsNow();
1548 }
1549
1550 @Override
1551 public void batteryPowerChanged(boolean onBattery) {
1552 // When plugging in, update the CPU stats first before changing
1553 // the plug state.
1554 updateCpuStatsNow();
1555 synchronized (this) {
1556 synchronized(mPidsSelfLocked) {
1557 mOnBattery = onBattery;
1558 }
1559 }
1560 }
1561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 /**
1563 * Initialize the application bind args. These are passed to each
1564 * process when the bindApplication() IPC is sent to the process. They're
1565 * lazily setup to make sure the services are running when they're asked for.
1566 */
1567 private HashMap<String, IBinder> getCommonServicesLocked() {
1568 if (mAppBindArgs == null) {
1569 mAppBindArgs = new HashMap<String, IBinder>();
1570
1571 // Setup the application init args
1572 mAppBindArgs.put("package", ServiceManager.getService("package"));
1573 mAppBindArgs.put("window", ServiceManager.getService("window"));
1574 mAppBindArgs.put(Context.ALARM_SERVICE,
1575 ServiceManager.getService(Context.ALARM_SERVICE));
1576 }
1577 return mAppBindArgs;
1578 }
1579
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001580 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 if (mFocusedActivity != r) {
1582 mFocusedActivity = r;
1583 mWindowManager.setFocusedApp(r, true);
1584 }
1585 }
1586
Dianne Hackborn906497c2010-05-10 15:57:38 -07001587 private final void updateLruProcessInternalLocked(ProcessRecord app,
1588 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001590 int lrui = mLruProcesses.indexOf(app);
1591 if (lrui >= 0) mLruProcesses.remove(lrui);
1592
1593 int i = mLruProcesses.size()-1;
1594 int skipTop = 0;
1595
Dianne Hackborn906497c2010-05-10 15:57:38 -07001596 app.lruSeq = mLruSeq;
1597
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001598 // compute the new weight for this process.
1599 if (updateActivityTime) {
1600 app.lastActivityTime = SystemClock.uptimeMillis();
1601 }
1602 if (app.activities.size() > 0) {
1603 // If this process has activities, we more strongly want to keep
1604 // it around.
1605 app.lruWeight = app.lastActivityTime;
1606 } else if (app.pubProviders.size() > 0) {
1607 // If this process contains content providers, we want to keep
1608 // it a little more strongly.
1609 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1610 // Also don't let it kick out the first few "real" hidden processes.
1611 skipTop = MIN_HIDDEN_APPS;
1612 } else {
1613 // If this process doesn't have activities, we less strongly
1614 // want to keep it around, and generally want to avoid getting
1615 // in front of any very recently used activities.
1616 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1617 // Also don't let it kick out the first few "real" hidden processes.
1618 skipTop = MIN_HIDDEN_APPS;
1619 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001620
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001621 while (i >= 0) {
1622 ProcessRecord p = mLruProcesses.get(i);
1623 // If this app shouldn't be in front of the first N background
1624 // apps, then skip over that many that are currently hidden.
1625 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1626 skipTop--;
1627 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001628 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001629 mLruProcesses.add(i+1, app);
1630 break;
1631 }
1632 i--;
1633 }
1634 if (i < 0) {
1635 mLruProcesses.add(0, app);
1636 }
1637
Dianne Hackborn906497c2010-05-10 15:57:38 -07001638 // If the app is currently using a content provider or service,
1639 // bump those processes as well.
1640 if (app.connections.size() > 0) {
1641 for (ConnectionRecord cr : app.connections) {
1642 if (cr.binding != null && cr.binding.service != null
1643 && cr.binding.service.app != null
1644 && cr.binding.service.app.lruSeq != mLruSeq) {
1645 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1646 updateActivityTime, i+1);
1647 }
1648 }
1649 }
1650 if (app.conProviders.size() > 0) {
1651 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1652 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1653 updateLruProcessInternalLocked(cpr.app, oomAdj,
1654 updateActivityTime, i+1);
1655 }
1656 }
1657 }
1658
Joe Onorato8a9b2202010-02-26 18:56:32 -08001659 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 if (oomAdj) {
1661 updateOomAdjLocked();
1662 }
1663 }
1664
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001665 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001666 boolean oomAdj, boolean updateActivityTime) {
1667 mLruSeq++;
1668 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1669 }
1670
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001671 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 String processName, int uid) {
1673 if (uid == Process.SYSTEM_UID) {
1674 // The system gets to run in any process. If there are multiple
1675 // processes with the same uid, just pick the first (this
1676 // should never happen).
1677 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1678 processName);
1679 return procs != null ? procs.valueAt(0) : null;
1680 }
1681 ProcessRecord proc = mProcessNames.get(processName, uid);
1682 return proc;
1683 }
1684
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001685 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001686 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001687 try {
1688 if (pm.performDexOpt(packageName)) {
1689 mDidDexOpt = true;
1690 }
1691 } catch (RemoteException e) {
1692 }
1693 }
1694
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001695 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 int transit = mWindowManager.getPendingAppTransition();
1697 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1698 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1699 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1700 }
1701
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001702 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001704 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1706 // We don't have to do anything more if:
1707 // (1) There is an existing application record; and
1708 // (2) The caller doesn't think it is dead, OR there is no thread
1709 // object attached to it so we know it couldn't have crashed; and
1710 // (3) There is a pid assigned to it, so it is either starting or
1711 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001712 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 + " app=" + app + " knownToBeDead=" + knownToBeDead
1714 + " thread=" + (app != null ? app.thread : null)
1715 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001716 if (app != null && app.pid > 0) {
1717 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001718 // We already have the app running, or are waiting for it to
1719 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001720 return app;
1721 } else {
1722 // An application record is attached to a previous process,
1723 // clean it up now.
1724 handleAppDiedLocked(app, true);
1725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 String hostingNameStr = hostingName != null
1729 ? hostingName.flattenToShortString() : null;
1730
1731 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1732 // If we are in the background, then check to see if this process
1733 // is bad. If so, we will just silently fail.
1734 if (mBadProcesses.get(info.processName, info.uid) != null) {
1735 return null;
1736 }
1737 } else {
1738 // When the user is explicitly starting a process, then clear its
1739 // crash count so that we won't make it bad until they see at
1740 // least one crash dialog again, and make the process good again
1741 // if it had been bad.
1742 mProcessCrashTimes.remove(info.processName, info.uid);
1743 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001744 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 info.processName);
1746 mBadProcesses.remove(info.processName, info.uid);
1747 if (app != null) {
1748 app.bad = false;
1749 }
1750 }
1751 }
1752
1753 if (app == null) {
1754 app = newProcessRecordLocked(null, info, processName);
1755 mProcessNames.put(processName, info.uid, app);
1756 } else {
1757 // If this is a new package in the process, add the package to the list
1758 app.addPackage(info.packageName);
1759 }
1760
1761 // If the system is not ready yet, then hold off on starting this
1762 // process until it is.
1763 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001764 && !isAllowedWhileBooting(info)
1765 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 if (!mProcessesOnHold.contains(app)) {
1767 mProcessesOnHold.add(app);
1768 }
1769 return app;
1770 }
1771
1772 startProcessLocked(app, hostingType, hostingNameStr);
1773 return (app.pid != 0) ? app : null;
1774 }
1775
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001776 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1777 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1778 }
1779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 private final void startProcessLocked(ProcessRecord app,
1781 String hostingType, String hostingNameStr) {
1782 if (app.pid > 0 && app.pid != MY_PID) {
1783 synchronized (mPidsSelfLocked) {
1784 mPidsSelfLocked.remove(app.pid);
1785 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1786 }
1787 app.pid = 0;
1788 }
1789
1790 mProcessesOnHold.remove(app);
1791
1792 updateCpuStats();
1793
1794 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1795 mProcDeaths[0] = 0;
1796
1797 try {
1798 int uid = app.info.uid;
1799 int[] gids = null;
1800 try {
1801 gids = mContext.getPackageManager().getPackageGids(
1802 app.info.packageName);
1803 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001804 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 }
1806 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1807 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1808 && mTopComponent != null
1809 && app.processName.equals(mTopComponent.getPackageName())) {
1810 uid = 0;
1811 }
1812 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1813 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1814 uid = 0;
1815 }
1816 }
1817 int debugFlags = 0;
1818 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1819 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1820 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001821 // Run the app in safe mode if its manifest requests so or the
1822 // system is booted in safe mode.
1823 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1824 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001825 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1826 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1828 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1829 }
1830 if ("1".equals(SystemProperties.get("debug.assert"))) {
1831 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1832 }
1833 int pid = Process.start("android.app.ActivityThread",
1834 mSimpleProcessManagement ? app.processName : null, uid, uid,
1835 gids, debugFlags, null);
1836 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1837 synchronized (bs) {
1838 if (bs.isOnBattery()) {
1839 app.batteryStats.incStartsLocked();
1840 }
1841 }
1842
Doug Zongker2bec3d42009-12-04 12:52:44 -08001843 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 app.processName, hostingType,
1845 hostingNameStr != null ? hostingNameStr : "");
1846
1847 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001848 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 }
1850
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001851 StringBuilder buf = mStringBuilder;
1852 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 buf.append("Start proc ");
1854 buf.append(app.processName);
1855 buf.append(" for ");
1856 buf.append(hostingType);
1857 if (hostingNameStr != null) {
1858 buf.append(" ");
1859 buf.append(hostingNameStr);
1860 }
1861 buf.append(": pid=");
1862 buf.append(pid);
1863 buf.append(" uid=");
1864 buf.append(uid);
1865 buf.append(" gids={");
1866 if (gids != null) {
1867 for (int gi=0; gi<gids.length; gi++) {
1868 if (gi != 0) buf.append(", ");
1869 buf.append(gids[gi]);
1870
1871 }
1872 }
1873 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001874 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875 if (pid == 0 || pid == MY_PID) {
1876 // Processes are being emulated with threads.
1877 app.pid = MY_PID;
1878 app.removed = false;
1879 mStartingProcesses.add(app);
1880 } else if (pid > 0) {
1881 app.pid = pid;
1882 app.removed = false;
1883 synchronized (mPidsSelfLocked) {
1884 this.mPidsSelfLocked.put(pid, app);
1885 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1886 msg.obj = app;
1887 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1888 }
1889 } else {
1890 app.pid = 0;
1891 RuntimeException e = new RuntimeException(
1892 "Failure starting process " + app.processName
1893 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001894 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 }
1896 } catch (RuntimeException e) {
1897 // XXX do better error recovery.
1898 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001899 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001900 }
1901 }
1902
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001903 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001904 if (resumed) {
1905 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1906 } else {
1907 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1908 }
1909 }
1910
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001911 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001912 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1913 && mTopAction == null) {
1914 // We are running in factory test mode, but unable to find
1915 // the factory test app, so just sit around displaying the
1916 // error message and don't try to start anything.
1917 return false;
1918 }
1919 Intent intent = new Intent(
1920 mTopAction,
1921 mTopData != null ? Uri.parse(mTopData) : null);
1922 intent.setComponent(mTopComponent);
1923 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1924 intent.addCategory(Intent.CATEGORY_HOME);
1925 }
1926 ActivityInfo aInfo =
1927 intent.resolveActivityInfo(mContext.getPackageManager(),
1928 STOCK_PM_FLAGS);
1929 if (aInfo != null) {
1930 intent.setComponent(new ComponentName(
1931 aInfo.applicationInfo.packageName, aInfo.name));
1932 // Don't do this if the home app is currently being
1933 // instrumented.
1934 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1935 aInfo.applicationInfo.uid);
1936 if (app == null || app.instrumentationClass == null) {
1937 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001938 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001939 null, null, 0, 0, 0, false, false);
1940 }
1941 }
1942
1943
1944 return true;
1945 }
1946
1947 /**
1948 * Starts the "new version setup screen" if appropriate.
1949 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001950 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001951 // Only do this once per boot.
1952 if (mCheckedForSetup) {
1953 return;
1954 }
1955
1956 // We will show this screen if the current one is a different
1957 // version than the last one shown, and we are not running in
1958 // low-level factory test mode.
1959 final ContentResolver resolver = mContext.getContentResolver();
1960 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1961 Settings.Secure.getInt(resolver,
1962 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1963 mCheckedForSetup = true;
1964
1965 // See if we should be showing the platform update setup UI.
1966 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1967 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1968 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1969
1970 // We don't allow third party apps to replace this.
1971 ResolveInfo ri = null;
1972 for (int i=0; ris != null && i<ris.size(); i++) {
1973 if ((ris.get(i).activityInfo.applicationInfo.flags
1974 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1975 ri = ris.get(i);
1976 break;
1977 }
1978 }
1979
1980 if (ri != null) {
1981 String vers = ri.activityInfo.metaData != null
1982 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1983 : null;
1984 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1985 vers = ri.activityInfo.applicationInfo.metaData.getString(
1986 Intent.METADATA_SETUP_VERSION);
1987 }
1988 String lastVers = Settings.Secure.getString(
1989 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1990 if (vers != null && !vers.equals(lastVers)) {
1991 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1992 intent.setComponent(new ComponentName(
1993 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001994 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001995 null, null, 0, 0, 0, false, false);
1996 }
1997 }
1998 }
1999 }
2000
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002001 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002002 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002003
2004 final int identHash = System.identityHashCode(r);
2005 updateUsageStats(r, true);
2006
2007 int i = mWatchers.beginBroadcast();
2008 while (i > 0) {
2009 i--;
2010 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2011 if (w != null) {
2012 try {
2013 w.activityResuming(identHash);
2014 } catch (RemoteException e) {
2015 }
2016 }
2017 }
2018 mWatchers.finishBroadcast();
2019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002021 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002022 final int N = mPendingActivityLaunches.size();
2023 if (N <= 0) {
2024 return;
2025 }
2026 for (int i=0; i<N; i++) {
2027 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002028 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002029 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2030 doResume && i == (N-1));
2031 }
2032 mPendingActivityLaunches.clear();
2033 }
2034
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002035 public final int startActivity(IApplicationThread caller,
2036 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2037 int grantedMode, IBinder resultTo,
2038 String resultWho, int requestCode, boolean onlyIfNeeded,
2039 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002040 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002041 grantedUriPermissions, grantedMode, resultTo, resultWho,
2042 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002043 }
2044
2045 public final WaitResult startActivityAndWait(IApplicationThread caller,
2046 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2047 int grantedMode, IBinder resultTo,
2048 String resultWho, int requestCode, boolean onlyIfNeeded,
2049 boolean debug) {
2050 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002051 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002052 grantedUriPermissions, grantedMode, resultTo, resultWho,
2053 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002054 return res;
2055 }
2056
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002057 public final int startActivityWithConfig(IApplicationThread caller,
2058 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2059 int grantedMode, IBinder resultTo,
2060 String resultWho, int requestCode, boolean onlyIfNeeded,
2061 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002062 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002063 grantedUriPermissions, grantedMode, resultTo, resultWho,
2064 requestCode, onlyIfNeeded, debug, null, config);
2065 }
2066
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002067 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002068 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002069 IBinder resultTo, String resultWho, int requestCode,
2070 int flagsMask, int flagsValues) {
2071 // Refuse possible leaked file descriptors
2072 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2073 throw new IllegalArgumentException("File descriptors passed in Intent");
2074 }
2075
2076 IIntentSender sender = intent.getTarget();
2077 if (!(sender instanceof PendingIntentRecord)) {
2078 throw new IllegalArgumentException("Bad PendingIntent object");
2079 }
2080
2081 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002082
2083 synchronized (this) {
2084 // If this is coming from the currently resumed activity, it is
2085 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002086 if (mMainStack.mResumedActivity != null
2087 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002088 Binder.getCallingUid()) {
2089 mAppSwitchesAllowedTime = 0;
2090 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002091 }
2092
2093 return pir.sendInner(0, fillInIntent, resolvedType,
2094 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2095 }
2096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 public boolean startNextMatchingActivity(IBinder callingActivity,
2098 Intent intent) {
2099 // Refuse possible leaked file descriptors
2100 if (intent != null && intent.hasFileDescriptors() == true) {
2101 throw new IllegalArgumentException("File descriptors passed in Intent");
2102 }
2103
2104 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002105 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002106 if (index < 0) {
2107 return false;
2108 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002109 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 if (r.app == null || r.app.thread == null) {
2111 // The caller is not running... d'oh!
2112 return false;
2113 }
2114 intent = new Intent(intent);
2115 // The caller is not allowed to change the data.
2116 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2117 // And we are resetting to find the next component...
2118 intent.setComponent(null);
2119
2120 ActivityInfo aInfo = null;
2121 try {
2122 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002123 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002125 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126
2127 // Look for the original activity in the list...
2128 final int N = resolves != null ? resolves.size() : 0;
2129 for (int i=0; i<N; i++) {
2130 ResolveInfo rInfo = resolves.get(i);
2131 if (rInfo.activityInfo.packageName.equals(r.packageName)
2132 && rInfo.activityInfo.name.equals(r.info.name)) {
2133 // We found the current one... the next matching is
2134 // after it.
2135 i++;
2136 if (i<N) {
2137 aInfo = resolves.get(i).activityInfo;
2138 }
2139 break;
2140 }
2141 }
2142 } catch (RemoteException e) {
2143 }
2144
2145 if (aInfo == null) {
2146 // Nobody who is next!
2147 return false;
2148 }
2149
2150 intent.setComponent(new ComponentName(
2151 aInfo.applicationInfo.packageName, aInfo.name));
2152 intent.setFlags(intent.getFlags()&~(
2153 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2154 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2155 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2156 Intent.FLAG_ACTIVITY_NEW_TASK));
2157
2158 // Okay now we need to start the new activity, replacing the
2159 // currently running activity. This is a little tricky because
2160 // we want to start the new one as if the current one is finished,
2161 // but not finish the current one first so that there is no flicker.
2162 // And thus...
2163 final boolean wasFinishing = r.finishing;
2164 r.finishing = true;
2165
2166 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002167 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168 final String resultWho = r.resultWho;
2169 final int requestCode = r.requestCode;
2170 r.resultTo = null;
2171 if (resultTo != null) {
2172 resultTo.removeResultsLocked(r, resultWho, requestCode);
2173 }
2174
2175 final long origId = Binder.clearCallingIdentity();
2176 // XXX we are not dealing with propagating grantedUriPermissions...
2177 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002178 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002180 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 Binder.restoreCallingIdentity(origId);
2182
2183 r.finishing = wasFinishing;
2184 if (res != START_SUCCESS) {
2185 return false;
2186 }
2187 return true;
2188 }
2189 }
2190
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002191 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 Intent intent, String resolvedType, IBinder resultTo,
2193 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002194
2195 // This is so super not safe, that only the system (or okay root)
2196 // can do it.
2197 final int callingUid = Binder.getCallingUid();
2198 if (callingUid != 0 && callingUid != Process.myUid()) {
2199 throw new SecurityException(
2200 "startActivityInPackage only available to the system");
2201 }
2202
The Android Open Source Project4df24232009-03-05 14:34:35 -08002203 final boolean componentSpecified = intent.getComponent() != null;
2204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205 // Don't modify the client's object!
2206 intent = new Intent(intent);
2207
2208 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002209 ActivityInfo aInfo;
2210 try {
2211 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002212 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002214 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 aInfo = rInfo != null ? rInfo.activityInfo : null;
2216 } catch (RemoteException e) {
2217 aInfo = null;
2218 }
2219
2220 if (aInfo != null) {
2221 // Store the found target back into the intent, because now that
2222 // we have it we never want to do this again. For example, if the
2223 // user navigates back to this point in the history, we should
2224 // always restart the exact same activity.
2225 intent.setComponent(new ComponentName(
2226 aInfo.applicationInfo.packageName, aInfo.name));
2227 }
2228
2229 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002230 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002232 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 }
2234 }
2235
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002236 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 // Remove any existing entries that are the same kind of task.
2238 int N = mRecentTasks.size();
2239 for (int i=0; i<N; i++) {
2240 TaskRecord tr = mRecentTasks.get(i);
2241 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2242 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2243 mRecentTasks.remove(i);
2244 i--;
2245 N--;
2246 if (task.intent == null) {
2247 // If the new recent task we are adding is not fully
2248 // specified, then replace it with the existing recent task.
2249 task = tr;
2250 }
2251 }
2252 }
2253 if (N >= MAX_RECENT_TASKS) {
2254 mRecentTasks.remove(N-1);
2255 }
2256 mRecentTasks.add(0, task);
2257 }
2258
2259 public void setRequestedOrientation(IBinder token,
2260 int requestedOrientation) {
2261 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002262 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263 if (index < 0) {
2264 return;
2265 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002266 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 final long origId = Binder.clearCallingIdentity();
2268 mWindowManager.setAppOrientation(r, requestedOrientation);
2269 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002270 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002271 r.mayFreezeScreenLocked(r.app) ? r : null);
2272 if (config != null) {
2273 r.frozenBeforeDestroy = true;
2274 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002275 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 }
2277 }
2278 Binder.restoreCallingIdentity(origId);
2279 }
2280 }
2281
2282 public int getRequestedOrientation(IBinder token) {
2283 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002284 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 if (index < 0) {
2286 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2287 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002288 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 return mWindowManager.getAppOrientation(r);
2290 }
2291 }
2292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 /**
2294 * This is the internal entry point for handling Activity.finish().
2295 *
2296 * @param token The Binder token referencing the Activity we want to finish.
2297 * @param resultCode Result code, if any, from this Activity.
2298 * @param resultData Result data (Intent), if any, from this Activity.
2299 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002300 * @return Returns true if the activity successfully finished, or false if it is still running.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301 */
2302 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2303 // Refuse possible leaked file descriptors
2304 if (resultData != null && resultData.hasFileDescriptors() == true) {
2305 throw new IllegalArgumentException("File descriptors passed in Intent");
2306 }
2307
2308 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002309 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002310 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002311 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 if (next != null) {
2313 // ask watcher if this is allowed
2314 boolean resumeOK = true;
2315 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002316 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002318 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002319 }
2320
2321 if (!resumeOK) {
2322 return false;
2323 }
2324 }
2325 }
2326 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002327 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 resultData, "app-request");
2329 Binder.restoreCallingIdentity(origId);
2330 return res;
2331 }
2332 }
2333
Dianne Hackborn860755f2010-06-03 18:47:52 -07002334 public final void finishHeavyWeightApp() {
2335 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2336 != PackageManager.PERMISSION_GRANTED) {
2337 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2338 + Binder.getCallingPid()
2339 + ", uid=" + Binder.getCallingUid()
2340 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2341 Slog.w(TAG, msg);
2342 throw new SecurityException(msg);
2343 }
2344
2345 synchronized(this) {
2346 if (mHeavyWeightProcess == null) {
2347 return;
2348 }
2349
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002350 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002351 mHeavyWeightProcess.activities);
2352 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002353 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002354 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002355 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002356 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002357 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002358 null, "finish-heavy");
2359 }
2360 }
2361 }
2362
2363 mHeavyWeightProcess = null;
2364 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2365 }
2366 }
2367
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002368 public void crashApplication(int uid, int initialPid, String packageName,
2369 String message) {
2370 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2371 != PackageManager.PERMISSION_GRANTED) {
2372 String msg = "Permission Denial: crashApplication() from pid="
2373 + Binder.getCallingPid()
2374 + ", uid=" + Binder.getCallingUid()
2375 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2376 Slog.w(TAG, msg);
2377 throw new SecurityException(msg);
2378 }
2379
2380 synchronized(this) {
2381 ProcessRecord proc = null;
2382
2383 // Figure out which process to kill. We don't trust that initialPid
2384 // still has any relation to current pids, so must scan through the
2385 // list.
2386 synchronized (mPidsSelfLocked) {
2387 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2388 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2389 if (p.info.uid != uid) {
2390 continue;
2391 }
2392 if (p.pid == initialPid) {
2393 proc = p;
2394 break;
2395 }
2396 for (String str : p.pkgList) {
2397 if (str.equals(packageName)) {
2398 proc = p;
2399 }
2400 }
2401 }
2402 }
2403
2404 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002405 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002406 + " initialPid=" + initialPid
2407 + " packageName=" + packageName);
2408 return;
2409 }
2410
2411 if (proc.thread != null) {
2412 long ident = Binder.clearCallingIdentity();
2413 try {
2414 proc.thread.scheduleCrash(message);
2415 } catch (RemoteException e) {
2416 }
2417 Binder.restoreCallingIdentity(ident);
2418 }
2419 }
2420 }
2421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 public final void finishSubActivity(IBinder token, String resultWho,
2423 int requestCode) {
2424 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002425 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 if (index < 0) {
2427 return;
2428 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002429 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002430
2431 final long origId = Binder.clearCallingIdentity();
2432
2433 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002434 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2435 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 if (r.resultTo == self && r.requestCode == requestCode) {
2437 if ((r.resultWho == null && resultWho == null) ||
2438 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002439 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002440 Activity.RESULT_CANCELED, null, "request-sub");
2441 }
2442 }
2443 }
2444
2445 Binder.restoreCallingIdentity(origId);
2446 }
2447 }
2448
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002449 public boolean willActivityBeVisible(IBinder token) {
2450 synchronized(this) {
2451 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002452 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2453 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002454 if (r == token) {
2455 return true;
2456 }
2457 if (r.fullscreen && !r.finishing) {
2458 return false;
2459 }
2460 }
2461 return true;
2462 }
2463 }
2464
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002465 public void overridePendingTransition(IBinder token, String packageName,
2466 int enterAnim, int exitAnim) {
2467 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002468 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002469 if (index < 0) {
2470 return;
2471 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002472 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002473
2474 final long origId = Binder.clearCallingIdentity();
2475
2476 if (self.state == ActivityState.RESUMED
2477 || self.state == ActivityState.PAUSING) {
2478 mWindowManager.overridePendingAppTransition(packageName,
2479 enterAnim, exitAnim);
2480 }
2481
2482 Binder.restoreCallingIdentity(origId);
2483 }
2484 }
2485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002487 * Main function for removing an existing process from the activity manager
2488 * as a result of that process going away. Clears out all connections
2489 * to the process.
2490 */
2491 private final void handleAppDiedLocked(ProcessRecord app,
2492 boolean restarting) {
2493 cleanUpApplicationRecordLocked(app, restarting, -1);
2494 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002495 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496 }
2497
2498 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002499 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2500 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2501 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002503 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2504 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 }
2506
2507 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002508 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509
2510 boolean atTop = true;
2511 boolean hasVisibleActivities = false;
2512
2513 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002514 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002515 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 TAG, "Removing app " + app + " from history with " + i + " entries");
2517 while (i > 0) {
2518 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002519 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002520 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2522 if (r.app == app) {
2523 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002524 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 TAG, "Removing this entry! frozen=" + r.haveState
2526 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002527 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528
2529 r.inHistory = false;
2530 mWindowManager.removeAppToken(r);
2531 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002532 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002533 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002534 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535
2536 } else {
2537 // We have the current state for this activity, so
2538 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002539 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 TAG, "Keeping entry, setting app to null");
2541 if (r.visible) {
2542 hasVisibleActivities = true;
2543 }
2544 r.app = null;
2545 r.nowVisible = false;
2546 if (!r.haveState) {
2547 r.icicle = null;
2548 }
2549 }
2550
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002551 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 r.state = ActivityState.STOPPED;
2553 }
2554 atTop = false;
2555 }
2556
2557 app.activities.clear();
2558
2559 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002560 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 + " running instrumentation " + app.instrumentationClass);
2562 Bundle info = new Bundle();
2563 info.putString("shortMsg", "Process crashed.");
2564 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2565 }
2566
2567 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002568 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 // If there was nothing to resume, and we are not already
2570 // restarting this process, but there is a visible activity that
2571 // is hosted by the process... then make sure all visible
2572 // activities are running, taking care of restarting this
2573 // process.
2574 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002575 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 }
2577 }
2578 }
2579 }
2580
2581 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2582 IBinder threadBinder = thread.asBinder();
2583
2584 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002585 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2586 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2588 return i;
2589 }
2590 }
2591 return -1;
2592 }
2593
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002594 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 IApplicationThread thread) {
2596 if (thread == null) {
2597 return null;
2598 }
2599
2600 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002601 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002602 }
2603
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002604 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 IApplicationThread thread) {
2606
2607 mProcDeaths[0]++;
2608
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002609 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2610 synchronized (stats) {
2611 stats.noteProcessDiedLocked(app.info.uid, pid);
2612 }
2613
Magnus Edlund7bb25812010-02-24 15:45:06 +01002614 // Clean up already done if the process has been re-started.
2615 if (app.pid == pid && app.thread != null &&
2616 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002617 if (!app.killedBackground) {
2618 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2619 + ") has died.");
2620 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002621 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002622 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 TAG, "Dying app: " + app + ", pid: " + pid
2624 + ", thread: " + thread.asBinder());
2625 boolean doLowMem = app.instrumentationClass == null;
2626 handleAppDiedLocked(app, false);
2627
2628 if (doLowMem) {
2629 // If there are no longer any background processes running,
2630 // and the app that died was not running instrumentation,
2631 // then tell everyone we are now low on memory.
2632 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002633 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2634 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2636 haveBg = true;
2637 break;
2638 }
2639 }
2640
2641 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002642 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002643 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002644 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002645 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2646 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002647 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002648 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2649 // The low memory report is overriding any current
2650 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002651 // heavy/important/visible/foreground processes first.
2652 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002653 rec.lastRequestedGc = 0;
2654 } else {
2655 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002656 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002657 rec.reportLowMemory = true;
2658 rec.lastLowMemory = now;
2659 mProcessesToGc.remove(rec);
2660 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 }
2662 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002663 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 }
2665 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002666 } else if (app.pid != pid) {
2667 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002668 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002669 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002670 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002671 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002672 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002673 + thread.asBinder());
2674 }
2675 }
2676
Dan Egnor42471dd2010-01-07 17:25:22 -08002677 /**
2678 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002679 * @param clearTraces causes the dump file to be erased prior to the new
2680 * traces being written, if true; when false, the new traces will be
2681 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002682 * @param firstPids of dalvik VM processes to dump stack traces for first
2683 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002684 * @return file containing stack traces, or null if no dump file is configured
2685 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002686 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2687 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002688 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2689 if (tracesPath == null || tracesPath.length() == 0) {
2690 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002692
2693 File tracesFile = new File(tracesPath);
2694 try {
2695 File tracesDir = tracesFile.getParentFile();
2696 if (!tracesDir.exists()) tracesFile.mkdirs();
2697 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2698
Christopher Tate6ee412d2010-05-28 12:01:56 -07002699 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002700 tracesFile.createNewFile();
2701 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2702 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002703 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002704 return null;
2705 }
2706
2707 // Use a FileObserver to detect when traces finish writing.
2708 // The order of traces is considered important to maintain for legibility.
2709 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2710 public synchronized void onEvent(int event, String path) { notify(); }
2711 };
2712
2713 try {
2714 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002715
2716 // First collect all of the stacks of the most important pids.
2717 try {
2718 int num = firstPids.size();
2719 for (int i = 0; i < num; i++) {
2720 synchronized (observer) {
2721 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2722 observer.wait(200); // Wait for write-close, give up after 200msec
2723 }
2724 }
2725 } catch (InterruptedException e) {
2726 Log.wtf(TAG, e);
2727 }
2728
2729 // Next measure CPU usage.
2730 if (processStats != null) {
2731 processStats.init();
2732 System.gc();
2733 processStats.update();
2734 try {
2735 synchronized (processStats) {
2736 processStats.wait(500); // measure over 1/2 second.
2737 }
2738 } catch (InterruptedException e) {
2739 }
2740 processStats.update();
2741
2742 // We'll take the stack crawls of just the top apps using CPU.
2743 final int N = processStats.countWorkingStats();
2744 int numProcs = 0;
2745 for (int i=0; i<N && numProcs<5; i++) {
2746 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2747 if (lastPids.indexOfKey(stats.pid) >= 0) {
2748 numProcs++;
2749 try {
2750 synchronized (observer) {
2751 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2752 observer.wait(200); // Wait for write-close, give up after 200msec
2753 }
2754 } catch (InterruptedException e) {
2755 Log.wtf(TAG, e);
2756 }
2757
2758 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002759 }
2760 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002761
2762 return tracesFile;
2763
Dan Egnor42471dd2010-01-07 17:25:22 -08002764 } finally {
2765 observer.stopWatching();
2766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 }
2768
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002769 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2770 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002771 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2772 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2773
2774 long anrTime = SystemClock.uptimeMillis();
2775 if (MONITOR_CPU_USAGE) {
2776 updateCpuStatsNow();
2777 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002778
2779 synchronized (this) {
2780 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2781 if (mShuttingDown) {
2782 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2783 return;
2784 } else if (app.notResponding) {
2785 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2786 return;
2787 } else if (app.crashing) {
2788 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2789 return;
2790 }
2791
2792 // In case we come through here for the same app before completing
2793 // this one, mark as anring now so we will bail out.
2794 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002795
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002796 // Log the ANR to the event log.
2797 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2798 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002799
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002800 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002801 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002802
2803 int parentPid = app.pid;
2804 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002805 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002806
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002807 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002808
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002809 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2810 ProcessRecord r = mLruProcesses.get(i);
2811 if (r != null && r.thread != null) {
2812 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002813 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2814 if (r.persistent) {
2815 firstPids.add(pid);
2816 } else {
2817 lastPids.put(pid, Boolean.TRUE);
2818 }
2819 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002820 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002821 }
2822 }
2823
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002824 final ProcessStats processStats = new ProcessStats(true);
2825
2826 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002827
2828 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002829 StringBuilder info = mStringBuilder;
2830 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002831 info.append("ANR in ").append(app.processName);
2832 if (activity != null && activity.shortComponentName != null) {
2833 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002834 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002835 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002837 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002838 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002839 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002840 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002842
Dan Egnor42471dd2010-01-07 17:25:22 -08002843 String cpuInfo = null;
2844 if (MONITOR_CPU_USAGE) {
2845 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002846 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002847 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002848 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002849 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002850 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 }
2852
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002853 info.append(processStats.printCurrentState(anrTime));
2854
Joe Onorato8a9b2202010-02-26 18:56:32 -08002855 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002856 if (tracesFile == null) {
2857 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2858 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2859 }
2860
2861 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2862
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002863 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002865 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2866 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002867 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002868 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2869 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002870 }
2871 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002872 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002873 }
2874 }
2875
Dan Egnor42471dd2010-01-07 17:25:22 -08002876 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2877 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2878 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002879
2880 synchronized (this) {
2881 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2882 Process.killProcess(app.pid);
2883 return;
2884 }
2885
2886 // Set the app's notResponding state, and look up the errorReportReceiver
2887 makeAppNotRespondingLocked(app,
2888 activity != null ? activity.shortComponentName : null,
2889 annotation != null ? "ANR " + annotation : "ANR",
2890 info.toString());
2891
2892 // Bring up the infamous App Not Responding dialog
2893 Message msg = Message.obtain();
2894 HashMap map = new HashMap();
2895 msg.what = SHOW_NOT_RESPONDING_MSG;
2896 msg.obj = map;
2897 map.put("app", app);
2898 if (activity != null) {
2899 map.put("activity", activity);
2900 }
2901
2902 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904 }
2905
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002906 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2907 if (!mLaunchWarningShown) {
2908 mLaunchWarningShown = true;
2909 mHandler.post(new Runnable() {
2910 @Override
2911 public void run() {
2912 synchronized (ActivityManagerService.this) {
2913 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2914 d.show();
2915 mHandler.postDelayed(new Runnable() {
2916 @Override
2917 public void run() {
2918 synchronized (ActivityManagerService.this) {
2919 d.dismiss();
2920 mLaunchWarningShown = false;
2921 }
2922 }
2923 }, 4000);
2924 }
2925 }
2926 });
2927 }
2928 }
2929
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002930 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931 app.persistentActivities--;
2932 if (app.persistentActivities > 0) {
2933 // Still more of 'em...
2934 return;
2935 }
2936 if (app.persistent) {
2937 // Ah, but the application itself is persistent. Whatever!
2938 return;
2939 }
2940
2941 // App is no longer persistent... make sure it and the ones
2942 // following it in the LRU list have the correc oom_adj.
2943 updateOomAdjLocked();
2944 }
2945
2946 public void setPersistent(IBinder token, boolean isPersistent) {
2947 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2948 != PackageManager.PERMISSION_GRANTED) {
2949 String msg = "Permission Denial: setPersistent() from pid="
2950 + Binder.getCallingPid()
2951 + ", uid=" + Binder.getCallingUid()
2952 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002953 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 throw new SecurityException(msg);
2955 }
2956
2957 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002958 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 if (index < 0) {
2960 return;
2961 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002962 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 ProcessRecord app = r.app;
2964
Joe Onorato8a9b2202010-02-26 18:56:32 -08002965 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002966 TAG, "Setting persistence " + isPersistent + ": " + r);
2967
2968 if (isPersistent) {
2969 if (r.persistent) {
2970 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002971 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 return;
2973 }
2974 r.persistent = true;
2975 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002976 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 if (app.persistentActivities > 1) {
2978 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002979 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 return;
2981 }
2982 if (app.persistent) {
2983 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002984 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 return;
2986 }
2987
2988 // App is now persistent... make sure it and the ones
2989 // following it now have the correct oom_adj.
2990 final long origId = Binder.clearCallingIdentity();
2991 updateOomAdjLocked();
2992 Binder.restoreCallingIdentity(origId);
2993
2994 } else {
2995 if (!r.persistent) {
2996 // Okay okay, I heard you already!
2997 return;
2998 }
2999 r.persistent = false;
3000 final long origId = Binder.clearCallingIdentity();
3001 decPersistentCountLocked(app);
3002 Binder.restoreCallingIdentity(origId);
3003
3004 }
3005 }
3006 }
3007
3008 public boolean clearApplicationUserData(final String packageName,
3009 final IPackageDataObserver observer) {
3010 int uid = Binder.getCallingUid();
3011 int pid = Binder.getCallingPid();
3012 long callingId = Binder.clearCallingIdentity();
3013 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003014 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 int pkgUid = -1;
3016 synchronized(this) {
3017 try {
3018 pkgUid = pm.getPackageUid(packageName);
3019 } catch (RemoteException e) {
3020 }
3021 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003022 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 return false;
3024 }
3025 if (uid == pkgUid || checkComponentPermission(
3026 android.Manifest.permission.CLEAR_APP_USER_DATA,
3027 pid, uid, -1)
3028 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003029 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 } else {
3031 throw new SecurityException(pid+" does not have permission:"+
3032 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3033 "for process:"+packageName);
3034 }
3035 }
3036
3037 try {
3038 //clear application user data
3039 pm.clearApplicationUserData(packageName, observer);
3040 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3041 Uri.fromParts("package", packageName, null));
3042 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06003043 synchronized (this) {
3044 broadcastIntentLocked(null, null, intent,
3045 null, null, 0, null, null, null,
3046 false, false, MY_PID, Process.SYSTEM_UID);
3047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 } catch (RemoteException e) {
3049 }
3050 } finally {
3051 Binder.restoreCallingIdentity(callingId);
3052 }
3053 return true;
3054 }
3055
Dianne Hackborn03abb812010-01-04 18:43:19 -08003056 public void killBackgroundProcesses(final String packageName) {
3057 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3058 != PackageManager.PERMISSION_GRANTED &&
3059 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3060 != PackageManager.PERMISSION_GRANTED) {
3061 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 + Binder.getCallingPid()
3063 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003064 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003065 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 throw new SecurityException(msg);
3067 }
3068
3069 long callingId = Binder.clearCallingIdentity();
3070 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003071 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 int pkgUid = -1;
3073 synchronized(this) {
3074 try {
3075 pkgUid = pm.getPackageUid(packageName);
3076 } catch (RemoteException e) {
3077 }
3078 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003079 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 return;
3081 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003082 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003083 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003084 }
3085 } finally {
3086 Binder.restoreCallingIdentity(callingId);
3087 }
3088 }
3089
3090 public void forceStopPackage(final String packageName) {
3091 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3092 != PackageManager.PERMISSION_GRANTED) {
3093 String msg = "Permission Denial: forceStopPackage() from pid="
3094 + Binder.getCallingPid()
3095 + ", uid=" + Binder.getCallingUid()
3096 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003097 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003098 throw new SecurityException(msg);
3099 }
3100
3101 long callingId = Binder.clearCallingIdentity();
3102 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003103 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003104 int pkgUid = -1;
3105 synchronized(this) {
3106 try {
3107 pkgUid = pm.getPackageUid(packageName);
3108 } catch (RemoteException e) {
3109 }
3110 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003111 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003112 return;
3113 }
3114 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 }
3116 } finally {
3117 Binder.restoreCallingIdentity(callingId);
3118 }
3119 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003120
3121 /*
3122 * The pkg name and uid have to be specified.
3123 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3124 */
3125 public void killApplicationWithUid(String pkg, int uid) {
3126 if (pkg == null) {
3127 return;
3128 }
3129 // Make sure the uid is valid.
3130 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003131 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003132 return;
3133 }
3134 int callerUid = Binder.getCallingUid();
3135 // Only the system server can kill an application
3136 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003137 // Post an aysnc message to kill the application
3138 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3139 msg.arg1 = uid;
3140 msg.arg2 = 0;
3141 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003142 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003143 } else {
3144 throw new SecurityException(callerUid + " cannot kill pkg: " +
3145 pkg);
3146 }
3147 }
3148
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003149 public void closeSystemDialogs(String reason) {
3150 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3151 if (reason != null) {
3152 intent.putExtra("reason", reason);
3153 }
3154
3155 final int uid = Binder.getCallingUid();
3156 final long origId = Binder.clearCallingIdentity();
3157 synchronized (this) {
3158 int i = mWatchers.beginBroadcast();
3159 while (i > 0) {
3160 i--;
3161 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3162 if (w != null) {
3163 try {
3164 w.closingSystemDialogs(reason);
3165 } catch (RemoteException e) {
3166 }
3167 }
3168 }
3169 mWatchers.finishBroadcast();
3170
Dianne Hackbornffa42482009-09-23 22:20:11 -07003171 mWindowManager.closeSystemDialogs(reason);
3172
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003173 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3174 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003175 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003176 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003177 Activity.RESULT_CANCELED, null, "close-sys");
3178 }
3179 }
3180
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003181 broadcastIntentLocked(null, null, intent, null,
3182 null, 0, null, null, null, false, false, -1, uid);
3183 }
3184 Binder.restoreCallingIdentity(origId);
3185 }
3186
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003187 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003188 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003189 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3190 for (int i=pids.length-1; i>=0; i--) {
3191 infos[i] = new Debug.MemoryInfo();
3192 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003193 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003194 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003195 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003196
3197 public void killApplicationProcess(String processName, int uid) {
3198 if (processName == null) {
3199 return;
3200 }
3201
3202 int callerUid = Binder.getCallingUid();
3203 // Only the system server can kill an application
3204 if (callerUid == Process.SYSTEM_UID) {
3205 synchronized (this) {
3206 ProcessRecord app = getProcessRecordLocked(processName, uid);
3207 if (app != null) {
3208 try {
3209 app.thread.scheduleSuicide();
3210 } catch (RemoteException e) {
3211 // If the other end already died, then our work here is done.
3212 }
3213 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003214 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003215 + processName + " / " + uid);
3216 }
3217 }
3218 } else {
3219 throw new SecurityException(callerUid + " cannot kill app process: " +
3220 processName);
3221 }
3222 }
3223
Dianne Hackborn03abb812010-01-04 18:43:19 -08003224 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003225 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3227 Uri.fromParts("package", packageName, null));
3228 intent.putExtra(Intent.EXTRA_UID, uid);
3229 broadcastIntentLocked(null, null, intent,
3230 null, null, 0, null, null, null,
3231 false, false, MY_PID, Process.SYSTEM_UID);
3232 }
3233
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003234 private final boolean killPackageProcessesLocked(String packageName, int uid,
3235 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003236 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237
Dianne Hackborn03abb812010-01-04 18:43:19 -08003238 // Remove all processes this package may have touched: all with the
3239 // same UID (except for the system or root user), and all whose name
3240 // matches the package name.
3241 final String procNamePrefix = packageName + ":";
3242 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3243 final int NA = apps.size();
3244 for (int ia=0; ia<NA; ia++) {
3245 ProcessRecord app = apps.valueAt(ia);
3246 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003247 if (doit) {
3248 procs.add(app);
3249 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003250 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3251 || app.processName.equals(packageName)
3252 || app.processName.startsWith(procNamePrefix)) {
3253 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003254 if (!doit) {
3255 return true;
3256 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003257 app.removed = true;
3258 procs.add(app);
3259 }
3260 }
3261 }
3262 }
3263
3264 int N = procs.size();
3265 for (int i=0; i<N; i++) {
3266 removeProcessLocked(procs.get(i), callerWillRestart);
3267 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003268 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003269 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003270
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003271 private final boolean forceStopPackageLocked(String name, int uid,
3272 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273 int i, N;
3274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003275 if (uid < 0) {
3276 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003277 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 } catch (RemoteException e) {
3279 }
3280 }
3281
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003282 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003283 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003284
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003285 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3286 while (badApps.hasNext()) {
3287 SparseArray<Long> ba = badApps.next();
3288 if (ba.get(uid) != null) {
3289 badApps.remove();
3290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003291 }
3292 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003293
3294 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3295 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003296
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003297 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3298 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003300 if (!doit) {
3301 return true;
3302 }
3303 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003304 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 if (r.app != null) {
3306 r.app.removed = true;
3307 }
3308 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003309 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 }
3311 }
3312
3313 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3314 for (ServiceRecord service : mServices.values()) {
3315 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003316 if (!doit) {
3317 return true;
3318 }
3319 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003320 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003321 if (service.app != null) {
3322 service.app.removed = true;
3323 }
3324 service.app = null;
3325 services.add(service);
3326 }
3327 }
3328
3329 N = services.size();
3330 for (i=0; i<N; i++) {
3331 bringDownServiceLocked(services.get(i), true);
3332 }
3333
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003334 if (doit) {
3335 if (purgeCache) {
3336 AttributeCache ac = AttributeCache.instance();
3337 if (ac != null) {
3338 ac.removePackage(name);
3339 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003340 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003341 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003342 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003343
3344 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 }
3346
3347 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3348 final String name = app.processName;
3349 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003350 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003351 TAG, "Force removing process " + app + " (" + name
3352 + "/" + uid + ")");
3353
3354 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003355 if (mHeavyWeightProcess == app) {
3356 mHeavyWeightProcess = null;
3357 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 boolean needRestart = false;
3360 if (app.pid > 0 && app.pid != MY_PID) {
3361 int pid = app.pid;
3362 synchronized (mPidsSelfLocked) {
3363 mPidsSelfLocked.remove(pid);
3364 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3365 }
3366 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003367 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 Process.killProcess(pid);
3369
3370 if (app.persistent) {
3371 if (!callerWillRestart) {
3372 addAppLocked(app.info);
3373 } else {
3374 needRestart = true;
3375 }
3376 }
3377 } else {
3378 mRemovedProcesses.add(app);
3379 }
3380
3381 return needRestart;
3382 }
3383
3384 private final void processStartTimedOutLocked(ProcessRecord app) {
3385 final int pid = app.pid;
3386 boolean gone = false;
3387 synchronized (mPidsSelfLocked) {
3388 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3389 if (knownApp != null && knownApp.thread == null) {
3390 mPidsSelfLocked.remove(pid);
3391 gone = true;
3392 }
3393 }
3394
3395 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003396 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003397 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003398 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003399 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003400 if (mHeavyWeightProcess == app) {
3401 mHeavyWeightProcess = null;
3402 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3403 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003404 // Take care of any launching providers waiting for this process.
3405 checkAppInLaunchingProvidersLocked(app, true);
3406 // Take care of any services that are waiting for the process.
3407 for (int i=0; i<mPendingServices.size(); i++) {
3408 ServiceRecord sr = mPendingServices.get(i);
3409 if (app.info.uid == sr.appInfo.uid
3410 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003411 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003412 mPendingServices.remove(i);
3413 i--;
3414 bringDownServiceLocked(sr, true);
3415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003416 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003417 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003418 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003419 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003420 try {
3421 IBackupManager bm = IBackupManager.Stub.asInterface(
3422 ServiceManager.getService(Context.BACKUP_SERVICE));
3423 bm.agentDisconnected(app.info.packageName);
3424 } catch (RemoteException e) {
3425 // Can't happen; the backup manager is local
3426 }
3427 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003428 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003429 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003430 mPendingBroadcast = null;
3431 scheduleBroadcastsLocked();
3432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003434 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 }
3436 }
3437
3438 private final boolean attachApplicationLocked(IApplicationThread thread,
3439 int pid) {
3440
3441 // Find the application record that is being attached... either via
3442 // the pid if we are running in multiple processes, or just pull the
3443 // next app record if we are emulating process with anonymous threads.
3444 ProcessRecord app;
3445 if (pid != MY_PID && pid >= 0) {
3446 synchronized (mPidsSelfLocked) {
3447 app = mPidsSelfLocked.get(pid);
3448 }
3449 } else if (mStartingProcesses.size() > 0) {
3450 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003451 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 } else {
3453 app = null;
3454 }
3455
3456 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003457 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003458 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003459 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 if (pid > 0 && pid != MY_PID) {
3461 Process.killProcess(pid);
3462 } else {
3463 try {
3464 thread.scheduleExit();
3465 } catch (Exception e) {
3466 // Ignore exceptions.
3467 }
3468 }
3469 return false;
3470 }
3471
3472 // If this application record is still attached to a previous
3473 // process, clean it up now.
3474 if (app.thread != null) {
3475 handleAppDiedLocked(app, true);
3476 }
3477
3478 // Tell the process all about itself.
3479
Joe Onorato8a9b2202010-02-26 18:56:32 -08003480 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 TAG, "Binding process pid " + pid + " to record " + app);
3482
3483 String processName = app.processName;
3484 try {
3485 thread.asBinder().linkToDeath(new AppDeathRecipient(
3486 app, pid, thread), 0);
3487 } catch (RemoteException e) {
3488 app.resetPackageList();
3489 startProcessLocked(app, "link fail", processName);
3490 return false;
3491 }
3492
Doug Zongker2bec3d42009-12-04 12:52:44 -08003493 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494
3495 app.thread = thread;
3496 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003497 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3498 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003499 app.forcingToForeground = null;
3500 app.foregroundServices = false;
3501 app.debugging = false;
3502
3503 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3504
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003505 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3506 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003508 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003509 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003510 }
3511
Joe Onorato8a9b2202010-02-26 18:56:32 -08003512 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 TAG, "New app record " + app
3514 + " thread=" + thread.asBinder() + " pid=" + pid);
3515 try {
3516 int testMode = IApplicationThread.DEBUG_OFF;
3517 if (mDebugApp != null && mDebugApp.equals(processName)) {
3518 testMode = mWaitForDebugger
3519 ? IApplicationThread.DEBUG_WAIT
3520 : IApplicationThread.DEBUG_ON;
3521 app.debugging = true;
3522 if (mDebugTransient) {
3523 mDebugApp = mOrigDebugApp;
3524 mWaitForDebugger = mOrigWaitForDebugger;
3525 }
3526 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003527
Christopher Tate181fafa2009-05-14 11:12:14 -07003528 // If the app is being launched for restore or full backup, set it up specially
3529 boolean isRestrictedBackupMode = false;
3530 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3531 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3532 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3533 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003534
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003535 ensurePackageDexOpt(app.instrumentationInfo != null
3536 ? app.instrumentationInfo.packageName
3537 : app.info.packageName);
3538 if (app.instrumentationClass != null) {
3539 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003540 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003541 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003542 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003543 thread.bindApplication(processName, app.instrumentationInfo != null
3544 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 app.instrumentationClass, app.instrumentationProfileFile,
3546 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003547 isRestrictedBackupMode || !normalMode,
3548 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003549 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003550 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 } catch (Exception e) {
3552 // todo: Yikes! What should we do? For now we will try to
3553 // start another process, but that could easily get us in
3554 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003555 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556
3557 app.resetPackageList();
3558 startProcessLocked(app, "bind fail", processName);
3559 return false;
3560 }
3561
3562 // Remove this record from the list of starting applications.
3563 mPersistentStartingProcesses.remove(app);
3564 mProcessesOnHold.remove(app);
3565
3566 boolean badApp = false;
3567 boolean didSomething = false;
3568
3569 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003570 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003571 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3573 && processName.equals(hr.processName)) {
3574 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003575 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003576 didSomething = true;
3577 }
3578 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003579 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 + hr.intent.getComponent().flattenToShortString(), e);
3581 badApp = true;
3582 }
3583 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003584 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003585 }
3586 }
3587
3588 // Find any services that should be running in this process...
3589 if (!badApp && mPendingServices.size() > 0) {
3590 ServiceRecord sr = null;
3591 try {
3592 for (int i=0; i<mPendingServices.size(); i++) {
3593 sr = mPendingServices.get(i);
3594 if (app.info.uid != sr.appInfo.uid
3595 || !processName.equals(sr.processName)) {
3596 continue;
3597 }
3598
3599 mPendingServices.remove(i);
3600 i--;
3601 realStartServiceLocked(sr, app);
3602 didSomething = true;
3603 }
3604 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003605 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003606 + sr.shortName, e);
3607 badApp = true;
3608 }
3609 }
3610
3611 // Check if the next broadcast receiver is in this process...
3612 BroadcastRecord br = mPendingBroadcast;
3613 if (!badApp && br != null && br.curApp == app) {
3614 try {
3615 mPendingBroadcast = null;
3616 processCurBroadcastLocked(br, app);
3617 didSomething = true;
3618 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003619 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 + br.curComponent.flattenToShortString(), e);
3621 badApp = true;
3622 logBroadcastReceiverDiscard(br);
3623 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3624 br.resultExtras, br.resultAbort, true);
3625 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003626 // We need to reset the state if we fails to start the receiver.
3627 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 }
3629 }
3630
Christopher Tate181fafa2009-05-14 11:12:14 -07003631 // Check whether the next backup agent is in this process...
3632 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003633 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003634 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003635 try {
3636 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3637 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003638 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003639 e.printStackTrace();
3640 }
3641 }
3642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643 if (badApp) {
3644 // todo: Also need to kill application to deal with all
3645 // kinds of exceptions.
3646 handleAppDiedLocked(app, false);
3647 return false;
3648 }
3649
3650 if (!didSomething) {
3651 updateOomAdjLocked();
3652 }
3653
3654 return true;
3655 }
3656
3657 public final void attachApplication(IApplicationThread thread) {
3658 synchronized (this) {
3659 int callingPid = Binder.getCallingPid();
3660 final long origId = Binder.clearCallingIdentity();
3661 attachApplicationLocked(thread, callingPid);
3662 Binder.restoreCallingIdentity(origId);
3663 }
3664 }
3665
Dianne Hackborne88846e2009-09-30 21:34:25 -07003666 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003668 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 Binder.restoreCallingIdentity(origId);
3670 }
3671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003673 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003674 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 mWindowManager.enableScreenAfterBoot();
3676 }
3677
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003678 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003679 IntentFilter pkgFilter = new IntentFilter();
3680 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3681 pkgFilter.addDataScheme("package");
3682 mContext.registerReceiver(new BroadcastReceiver() {
3683 @Override
3684 public void onReceive(Context context, Intent intent) {
3685 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3686 if (pkgs != null) {
3687 for (String pkg : pkgs) {
3688 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3689 setResultCode(Activity.RESULT_OK);
3690 return;
3691 }
3692 }
3693 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003694 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003695 }, pkgFilter);
3696
3697 synchronized (this) {
3698 // Ensure that any processes we had put on hold are now started
3699 // up.
3700 final int NP = mProcessesOnHold.size();
3701 if (NP > 0) {
3702 ArrayList<ProcessRecord> procs =
3703 new ArrayList<ProcessRecord>(mProcessesOnHold);
3704 for (int ip=0; ip<NP; ip++) {
3705 this.startProcessLocked(procs.get(ip), "on-hold", null);
3706 }
3707 }
3708
3709 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003710 // Start looking for apps that are abusing wake locks.
3711 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
3712 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003713 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003714 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003715 broadcastIntentLocked(null, null,
3716 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3717 null, null, 0, null, null,
3718 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3719 false, false, MY_PID, Process.SYSTEM_UID);
3720 }
3721 }
3722 }
3723
3724 final void ensureBootCompleted() {
3725 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003726 boolean enableScreen;
3727 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003728 booting = mBooting;
3729 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003730 enableScreen = !mBooted;
3731 mBooted = true;
3732 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003733
3734 if (booting) {
3735 finishBooting();
3736 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003737
3738 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003739 enableScreenAfterBoot();
3740 }
3741 }
3742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 public final void activityPaused(IBinder token, Bundle icicle) {
3744 // Refuse possible leaked file descriptors
3745 if (icicle != null && icicle.hasFileDescriptors()) {
3746 throw new IllegalArgumentException("File descriptors passed in Bundle");
3747 }
3748
3749 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003750 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 Binder.restoreCallingIdentity(origId);
3752 }
3753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 public final void activityStopped(IBinder token, Bitmap thumbnail,
3755 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003756 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 TAG, "Activity stopped: token=" + token);
3758
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003759 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760
3761 final long origId = Binder.clearCallingIdentity();
3762
3763 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003764 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003766 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 r.thumbnail = thumbnail;
3768 r.description = description;
3769 r.stopped = true;
3770 r.state = ActivityState.STOPPED;
3771 if (!r.finishing) {
3772 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003773 r.stack.destroyActivityLocked(r, true);
3774 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 }
3776 }
3777 }
3778 }
3779
3780 if (r != null) {
3781 sendPendingThumbnail(r, null, null, null, false);
3782 }
3783
3784 trimApplications();
3785
3786 Binder.restoreCallingIdentity(origId);
3787 }
3788
3789 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003790 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003791 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792 }
3793
3794 public String getCallingPackage(IBinder token) {
3795 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003796 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003797 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 }
3799 }
3800
3801 public ComponentName getCallingActivity(IBinder token) {
3802 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003803 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 return r != null ? r.intent.getComponent() : null;
3805 }
3806 }
3807
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003808 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003809 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003811 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003812 if (r != null) {
3813 return r.resultTo;
3814 }
3815 }
3816 return null;
3817 }
3818
3819 public ComponentName getActivityClassForToken(IBinder token) {
3820 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003821 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003823 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 return r.intent.getComponent();
3825 }
3826 return null;
3827 }
3828 }
3829
3830 public String getPackageForToken(IBinder token) {
3831 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003832 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003833 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003834 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 return r.packageName;
3836 }
3837 return null;
3838 }
3839 }
3840
3841 public IIntentSender getIntentSender(int type,
3842 String packageName, IBinder token, String resultWho,
3843 int requestCode, Intent intent, String resolvedType, int flags) {
3844 // Refuse possible leaked file descriptors
3845 if (intent != null && intent.hasFileDescriptors() == true) {
3846 throw new IllegalArgumentException("File descriptors passed in Intent");
3847 }
3848
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003849 if (type == INTENT_SENDER_BROADCAST) {
3850 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3851 throw new IllegalArgumentException(
3852 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3853 }
3854 }
3855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 synchronized(this) {
3857 int callingUid = Binder.getCallingUid();
3858 try {
3859 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3860 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003861 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 .getPackageUid(packageName);
3863 if (uid != Binder.getCallingUid()) {
3864 String msg = "Permission Denial: getIntentSender() from pid="
3865 + Binder.getCallingPid()
3866 + ", uid=" + Binder.getCallingUid()
3867 + ", (need uid=" + uid + ")"
3868 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003869 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 throw new SecurityException(msg);
3871 }
3872 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003873
3874 return getIntentSenderLocked(type, packageName, callingUid,
3875 token, resultWho, requestCode, intent, resolvedType, flags);
3876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 } catch (RemoteException e) {
3878 throw new SecurityException(e);
3879 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003880 }
3881 }
3882
3883 IIntentSender getIntentSenderLocked(int type,
3884 String packageName, int callingUid, IBinder token, String resultWho,
3885 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003886 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003887 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003888 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003889 if (index < 0) {
3890 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003891 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003892 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003893 if (activity.finishing) {
3894 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003896 }
3897
3898 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3899 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3900 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3901 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3902 |PendingIntent.FLAG_UPDATE_CURRENT);
3903
3904 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3905 type, packageName, activity, resultWho,
3906 requestCode, intent, resolvedType, flags);
3907 WeakReference<PendingIntentRecord> ref;
3908 ref = mIntentSenderRecords.get(key);
3909 PendingIntentRecord rec = ref != null ? ref.get() : null;
3910 if (rec != null) {
3911 if (!cancelCurrent) {
3912 if (updateCurrent) {
3913 rec.key.requestIntent.replaceExtras(intent);
3914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003915 return rec;
3916 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003917 rec.canceled = true;
3918 mIntentSenderRecords.remove(key);
3919 }
3920 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003921 return rec;
3922 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003923 rec = new PendingIntentRecord(this, key, callingUid);
3924 mIntentSenderRecords.put(key, rec.ref);
3925 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3926 if (activity.pendingResults == null) {
3927 activity.pendingResults
3928 = new HashSet<WeakReference<PendingIntentRecord>>();
3929 }
3930 activity.pendingResults.add(rec.ref);
3931 }
3932 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 }
3934
3935 public void cancelIntentSender(IIntentSender sender) {
3936 if (!(sender instanceof PendingIntentRecord)) {
3937 return;
3938 }
3939 synchronized(this) {
3940 PendingIntentRecord rec = (PendingIntentRecord)sender;
3941 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003942 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 .getPackageUid(rec.key.packageName);
3944 if (uid != Binder.getCallingUid()) {
3945 String msg = "Permission Denial: cancelIntentSender() from pid="
3946 + Binder.getCallingPid()
3947 + ", uid=" + Binder.getCallingUid()
3948 + " is not allowed to cancel packges "
3949 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003950 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 throw new SecurityException(msg);
3952 }
3953 } catch (RemoteException e) {
3954 throw new SecurityException(e);
3955 }
3956 cancelIntentSenderLocked(rec, true);
3957 }
3958 }
3959
3960 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3961 rec.canceled = true;
3962 mIntentSenderRecords.remove(rec.key);
3963 if (cleanActivity && rec.key.activity != null) {
3964 rec.key.activity.pendingResults.remove(rec.ref);
3965 }
3966 }
3967
3968 public String getPackageForIntentSender(IIntentSender pendingResult) {
3969 if (!(pendingResult instanceof PendingIntentRecord)) {
3970 return null;
3971 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003972 try {
3973 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3974 return res.key.packageName;
3975 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976 }
3977 return null;
3978 }
3979
3980 public void setProcessLimit(int max) {
3981 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3982 "setProcessLimit()");
3983 mProcessLimit = max;
3984 }
3985
3986 public int getProcessLimit() {
3987 return mProcessLimit;
3988 }
3989
3990 void foregroundTokenDied(ForegroundToken token) {
3991 synchronized (ActivityManagerService.this) {
3992 synchronized (mPidsSelfLocked) {
3993 ForegroundToken cur
3994 = mForegroundProcesses.get(token.pid);
3995 if (cur != token) {
3996 return;
3997 }
3998 mForegroundProcesses.remove(token.pid);
3999 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4000 if (pr == null) {
4001 return;
4002 }
4003 pr.forcingToForeground = null;
4004 pr.foregroundServices = false;
4005 }
4006 updateOomAdjLocked();
4007 }
4008 }
4009
4010 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4011 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4012 "setProcessForeground()");
4013 synchronized(this) {
4014 boolean changed = false;
4015
4016 synchronized (mPidsSelfLocked) {
4017 ProcessRecord pr = mPidsSelfLocked.get(pid);
4018 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004019 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 return;
4021 }
4022 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4023 if (oldToken != null) {
4024 oldToken.token.unlinkToDeath(oldToken, 0);
4025 mForegroundProcesses.remove(pid);
4026 pr.forcingToForeground = null;
4027 changed = true;
4028 }
4029 if (isForeground && token != null) {
4030 ForegroundToken newToken = new ForegroundToken() {
4031 public void binderDied() {
4032 foregroundTokenDied(this);
4033 }
4034 };
4035 newToken.pid = pid;
4036 newToken.token = token;
4037 try {
4038 token.linkToDeath(newToken, 0);
4039 mForegroundProcesses.put(pid, newToken);
4040 pr.forcingToForeground = token;
4041 changed = true;
4042 } catch (RemoteException e) {
4043 // If the process died while doing this, we will later
4044 // do the cleanup with the process death link.
4045 }
4046 }
4047 }
4048
4049 if (changed) {
4050 updateOomAdjLocked();
4051 }
4052 }
4053 }
4054
4055 // =========================================================
4056 // PERMISSIONS
4057 // =========================================================
4058
4059 static class PermissionController extends IPermissionController.Stub {
4060 ActivityManagerService mActivityManagerService;
4061 PermissionController(ActivityManagerService activityManagerService) {
4062 mActivityManagerService = activityManagerService;
4063 }
4064
4065 public boolean checkPermission(String permission, int pid, int uid) {
4066 return mActivityManagerService.checkPermission(permission, pid,
4067 uid) == PackageManager.PERMISSION_GRANTED;
4068 }
4069 }
4070
4071 /**
4072 * This can be called with or without the global lock held.
4073 */
4074 int checkComponentPermission(String permission, int pid, int uid,
4075 int reqUid) {
4076 // We might be performing an operation on behalf of an indirect binder
4077 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4078 // client identity accordingly before proceeding.
4079 Identity tlsIdentity = sCallerIdentity.get();
4080 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004081 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4083 uid = tlsIdentity.uid;
4084 pid = tlsIdentity.pid;
4085 }
4086
4087 // Root, system server and our own process get to do everything.
4088 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4089 !Process.supportsProcesses()) {
4090 return PackageManager.PERMISSION_GRANTED;
4091 }
4092 // If the target requires a specific UID, always fail for others.
4093 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004094 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095 return PackageManager.PERMISSION_DENIED;
4096 }
4097 if (permission == null) {
4098 return PackageManager.PERMISSION_GRANTED;
4099 }
4100 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004101 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 .checkUidPermission(permission, uid);
4103 } catch (RemoteException e) {
4104 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004105 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 }
4107 return PackageManager.PERMISSION_DENIED;
4108 }
4109
4110 /**
4111 * As the only public entry point for permissions checking, this method
4112 * can enforce the semantic that requesting a check on a null global
4113 * permission is automatically denied. (Internally a null permission
4114 * string is used when calling {@link #checkComponentPermission} in cases
4115 * when only uid-based security is needed.)
4116 *
4117 * This can be called with or without the global lock held.
4118 */
4119 public int checkPermission(String permission, int pid, int uid) {
4120 if (permission == null) {
4121 return PackageManager.PERMISSION_DENIED;
4122 }
4123 return checkComponentPermission(permission, pid, uid, -1);
4124 }
4125
4126 /**
4127 * Binder IPC calls go through the public entry point.
4128 * This can be called with or without the global lock held.
4129 */
4130 int checkCallingPermission(String permission) {
4131 return checkPermission(permission,
4132 Binder.getCallingPid(),
4133 Binder.getCallingUid());
4134 }
4135
4136 /**
4137 * This can be called with or without the global lock held.
4138 */
4139 void enforceCallingPermission(String permission, String func) {
4140 if (checkCallingPermission(permission)
4141 == PackageManager.PERMISSION_GRANTED) {
4142 return;
4143 }
4144
4145 String msg = "Permission Denial: " + func + " from pid="
4146 + Binder.getCallingPid()
4147 + ", uid=" + Binder.getCallingUid()
4148 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004149 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 throw new SecurityException(msg);
4151 }
4152
4153 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4154 ProviderInfo pi, int uid, int modeFlags) {
4155 try {
4156 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4157 if ((pi.readPermission != null) &&
4158 (pm.checkUidPermission(pi.readPermission, uid)
4159 != PackageManager.PERMISSION_GRANTED)) {
4160 return false;
4161 }
4162 }
4163 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4164 if ((pi.writePermission != null) &&
4165 (pm.checkUidPermission(pi.writePermission, uid)
4166 != PackageManager.PERMISSION_GRANTED)) {
4167 return false;
4168 }
4169 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004170 if (!pi.exported && pi.applicationInfo.uid != uid) {
4171 return false;
4172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 return true;
4174 } catch (RemoteException e) {
4175 return false;
4176 }
4177 }
4178
4179 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4180 int modeFlags) {
4181 // Root gets to do everything.
4182 if (uid == 0 || !Process.supportsProcesses()) {
4183 return true;
4184 }
4185 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4186 if (perms == null) return false;
4187 UriPermission perm = perms.get(uri);
4188 if (perm == null) return false;
4189 return (modeFlags&perm.modeFlags) == modeFlags;
4190 }
4191
4192 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4193 // Another redirected-binder-call permissions check as in
4194 // {@link checkComponentPermission}.
4195 Identity tlsIdentity = sCallerIdentity.get();
4196 if (tlsIdentity != null) {
4197 uid = tlsIdentity.uid;
4198 pid = tlsIdentity.pid;
4199 }
4200
4201 // Our own process gets to do everything.
4202 if (pid == MY_PID) {
4203 return PackageManager.PERMISSION_GRANTED;
4204 }
4205 synchronized(this) {
4206 return checkUriPermissionLocked(uri, uid, modeFlags)
4207 ? PackageManager.PERMISSION_GRANTED
4208 : PackageManager.PERMISSION_DENIED;
4209 }
4210 }
4211
Dianne Hackborn39792d22010-08-19 18:01:52 -07004212 /**
4213 * Check if the targetPkg can be granted permission to access uri by
4214 * the callingUid using the given modeFlags. Throws a security exception
4215 * if callingUid is not allowed to do this. Returns the uid of the target
4216 * if the URI permission grant should be performed; returns -1 if it is not
4217 * needed (for example targetPkg already has permission to access the URI).
4218 */
4219 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4220 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4222 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4223 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004224 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 }
4226
Joe Onorato8a9b2202010-02-26 18:56:32 -08004227 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004228 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004229
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004230 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004231
4232 // If this is not a content: uri, we can't do anything with it.
4233 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004234 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004235 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004236 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 }
4238
4239 String name = uri.getAuthority();
4240 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004241 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 if (cpr != null) {
4243 pi = cpr.info;
4244 } else {
4245 try {
4246 pi = pm.resolveContentProvider(name,
4247 PackageManager.GET_URI_PERMISSION_PATTERNS);
4248 } catch (RemoteException ex) {
4249 }
4250 }
4251 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004252 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004253 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 }
4255
4256 int targetUid;
4257 try {
4258 targetUid = pm.getPackageUid(targetPkg);
4259 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004260 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004261 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004262 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004263 }
4264 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004265 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004266 }
4267
4268 // First... does the target actually need this permission?
4269 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4270 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004271 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004272 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004273 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 }
4275
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004276 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 if (!pi.grantUriPermissions) {
4278 throw new SecurityException("Provider " + pi.packageName
4279 + "/" + pi.name
4280 + " does not allow granting of Uri permissions (uri "
4281 + uri + ")");
4282 }
4283 if (pi.uriPermissionPatterns != null) {
4284 final int N = pi.uriPermissionPatterns.length;
4285 boolean allowed = false;
4286 for (int i=0; i<N; i++) {
4287 if (pi.uriPermissionPatterns[i] != null
4288 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4289 allowed = true;
4290 break;
4291 }
4292 }
4293 if (!allowed) {
4294 throw new SecurityException("Provider " + pi.packageName
4295 + "/" + pi.name
4296 + " does not allow granting of permission to path of Uri "
4297 + uri);
4298 }
4299 }
4300
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004301 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 // this uri?
4303 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4304 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4305 throw new SecurityException("Uid " + callingUid
4306 + " does not have permission to uri " + uri);
4307 }
4308 }
4309
Dianne Hackborn39792d22010-08-19 18:01:52 -07004310 return targetUid;
4311 }
4312
4313 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4314 Uri uri, int modeFlags, UriPermissionOwner owner) {
4315 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4316 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4317 if (modeFlags == 0) {
4318 return;
4319 }
4320
4321 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004322 // to the uri, and the target doesn't. Let's now give this to
4323 // the target.
4324
Joe Onorato8a9b2202010-02-26 18:56:32 -08004325 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004326 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004328 HashMap<Uri, UriPermission> targetUris
4329 = mGrantedUriPermissions.get(targetUid);
4330 if (targetUris == null) {
4331 targetUris = new HashMap<Uri, UriPermission>();
4332 mGrantedUriPermissions.put(targetUid, targetUris);
4333 }
4334
4335 UriPermission perm = targetUris.get(uri);
4336 if (perm == null) {
4337 perm = new UriPermission(targetUid, uri);
4338 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004342 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 perm.globalModeFlags |= modeFlags;
4344 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004345 perm.readOwners.add(owner);
4346 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004348 perm.writeOwners.add(owner);
4349 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 }
4351 }
4352
Dianne Hackborn39792d22010-08-19 18:01:52 -07004353 void grantUriPermissionLocked(int callingUid,
4354 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4355 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4356 if (targetUid < 0) {
4357 return;
4358 }
4359
4360 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4361 }
4362
4363 /**
4364 * Like checkGrantUriPermissionLocked, but takes an Intent.
4365 */
4366 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4367 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004368 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004369 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004370 + " from " + intent + "; flags=0x"
4371 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004374 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004375 }
4376 Uri data = intent.getData();
4377 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004378 return -1;
4379 }
4380 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4381 intent.getFlags());
4382 }
4383
4384 /**
4385 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4386 */
4387 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4388 String targetPkg, Intent intent, UriPermissionOwner owner) {
4389 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4390 intent.getFlags(), owner);
4391 }
4392
4393 void grantUriPermissionFromIntentLocked(int callingUid,
4394 String targetPkg, Intent intent, UriPermissionOwner owner) {
4395 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4396 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 return;
4398 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004399
4400 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004401 }
4402
4403 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4404 Uri uri, int modeFlags) {
4405 synchronized(this) {
4406 final ProcessRecord r = getRecordForAppLocked(caller);
4407 if (r == null) {
4408 throw new SecurityException("Unable to find app for caller "
4409 + caller
4410 + " when granting permission to uri " + uri);
4411 }
4412 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004413 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 }
4415 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004416 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 }
4418
4419 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4420 null);
4421 }
4422 }
4423
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004424 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4426 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4427 HashMap<Uri, UriPermission> perms
4428 = mGrantedUriPermissions.get(perm.uid);
4429 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004430 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004431 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 perms.remove(perm.uri);
4433 if (perms.size() == 0) {
4434 mGrantedUriPermissions.remove(perm.uid);
4435 }
4436 }
4437 }
4438 }
4439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4441 int modeFlags) {
4442 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4443 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4444 if (modeFlags == 0) {
4445 return;
4446 }
4447
Joe Onorato8a9b2202010-02-26 18:56:32 -08004448 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004449 "Revoking all granted permissions to " + uri);
4450
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004451 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004452
4453 final String authority = uri.getAuthority();
4454 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004455 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 if (cpr != null) {
4457 pi = cpr.info;
4458 } else {
4459 try {
4460 pi = pm.resolveContentProvider(authority,
4461 PackageManager.GET_URI_PERMISSION_PATTERNS);
4462 } catch (RemoteException ex) {
4463 }
4464 }
4465 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004466 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 return;
4468 }
4469
4470 // Does the caller have this permission on the URI?
4471 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4472 // Right now, if you are not the original owner of the permission,
4473 // you are not allowed to revoke it.
4474 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4475 throw new SecurityException("Uid " + callingUid
4476 + " does not have permission to uri " + uri);
4477 //}
4478 }
4479
4480 // Go through all of the permissions and remove any that match.
4481 final List<String> SEGMENTS = uri.getPathSegments();
4482 if (SEGMENTS != null) {
4483 final int NS = SEGMENTS.size();
4484 int N = mGrantedUriPermissions.size();
4485 for (int i=0; i<N; i++) {
4486 HashMap<Uri, UriPermission> perms
4487 = mGrantedUriPermissions.valueAt(i);
4488 Iterator<UriPermission> it = perms.values().iterator();
4489 toploop:
4490 while (it.hasNext()) {
4491 UriPermission perm = it.next();
4492 Uri targetUri = perm.uri;
4493 if (!authority.equals(targetUri.getAuthority())) {
4494 continue;
4495 }
4496 List<String> targetSegments = targetUri.getPathSegments();
4497 if (targetSegments == null) {
4498 continue;
4499 }
4500 if (targetSegments.size() < NS) {
4501 continue;
4502 }
4503 for (int j=0; j<NS; j++) {
4504 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4505 continue toploop;
4506 }
4507 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004508 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004509 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 perm.clearModes(modeFlags);
4511 if (perm.modeFlags == 0) {
4512 it.remove();
4513 }
4514 }
4515 if (perms.size() == 0) {
4516 mGrantedUriPermissions.remove(
4517 mGrantedUriPermissions.keyAt(i));
4518 N--;
4519 i--;
4520 }
4521 }
4522 }
4523 }
4524
4525 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4526 int modeFlags) {
4527 synchronized(this) {
4528 final ProcessRecord r = getRecordForAppLocked(caller);
4529 if (r == null) {
4530 throw new SecurityException("Unable to find app for caller "
4531 + caller
4532 + " when revoking permission to uri " + uri);
4533 }
4534 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004535 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 return;
4537 }
4538
4539 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4540 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4541 if (modeFlags == 0) {
4542 return;
4543 }
4544
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004545 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004546
4547 final String authority = uri.getAuthority();
4548 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004549 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 if (cpr != null) {
4551 pi = cpr.info;
4552 } else {
4553 try {
4554 pi = pm.resolveContentProvider(authority,
4555 PackageManager.GET_URI_PERMISSION_PATTERNS);
4556 } catch (RemoteException ex) {
4557 }
4558 }
4559 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004560 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 return;
4562 }
4563
4564 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4565 }
4566 }
4567
Dianne Hackborn7e269642010-08-25 19:50:20 -07004568 @Override
4569 public IBinder newUriPermissionOwner(String name) {
4570 synchronized(this) {
4571 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4572 return owner.getExternalTokenLocked();
4573 }
4574 }
4575
4576 @Override
4577 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4578 Uri uri, int modeFlags) {
4579 synchronized(this) {
4580 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4581 if (owner == null) {
4582 throw new IllegalArgumentException("Unknown owner: " + token);
4583 }
4584 if (fromUid != Binder.getCallingUid()) {
4585 if (Binder.getCallingUid() != Process.myUid()) {
4586 // Only system code can grant URI permissions on behalf
4587 // of other users.
4588 throw new SecurityException("nice try");
4589 }
4590 }
4591 if (targetPkg == null) {
4592 throw new IllegalArgumentException("null target");
4593 }
4594 if (uri == null) {
4595 throw new IllegalArgumentException("null uri");
4596 }
4597
4598 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4599 }
4600 }
4601
4602 @Override
4603 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4604 synchronized(this) {
4605 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4606 if (owner == null) {
4607 throw new IllegalArgumentException("Unknown owner: " + token);
4608 }
4609
4610 if (uri == null) {
4611 owner.removeUriPermissionsLocked(mode);
4612 } else {
4613 owner.removeUriPermissionLocked(uri, mode);
4614 }
4615 }
4616 }
4617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4619 synchronized (this) {
4620 ProcessRecord app =
4621 who != null ? getRecordForAppLocked(who) : null;
4622 if (app == null) return;
4623
4624 Message msg = Message.obtain();
4625 msg.what = WAIT_FOR_DEBUGGER_MSG;
4626 msg.obj = app;
4627 msg.arg1 = waiting ? 1 : 0;
4628 mHandler.sendMessage(msg);
4629 }
4630 }
4631
4632 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4633 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004634 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004636 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 }
4638
4639 // =========================================================
4640 // TASK MANAGEMENT
4641 // =========================================================
4642
4643 public List getTasks(int maxNum, int flags,
4644 IThumbnailReceiver receiver) {
4645 ArrayList list = new ArrayList();
4646
4647 PendingThumbnailsRecord pending = null;
4648 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004649 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650
4651 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004652 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4654 + ", receiver=" + receiver);
4655
4656 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4657 != PackageManager.PERMISSION_GRANTED) {
4658 if (receiver != null) {
4659 // If the caller wants to wait for pending thumbnails,
4660 // it ain't gonna get them.
4661 try {
4662 receiver.finished();
4663 } catch (RemoteException ex) {
4664 }
4665 }
4666 String msg = "Permission Denial: getTasks() from pid="
4667 + Binder.getCallingPid()
4668 + ", uid=" + Binder.getCallingUid()
4669 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004670 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004671 throw new SecurityException(msg);
4672 }
4673
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004674 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004675 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004676 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004677 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 CharSequence topDescription = null;
4679 TaskRecord curTask = null;
4680 int numActivities = 0;
4681 int numRunning = 0;
4682 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004683 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004685 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686
4687 // Initialize state for next task if needed.
4688 if (top == null ||
4689 (top.state == ActivityState.INITIALIZING
4690 && top.task == r.task)) {
4691 top = r;
4692 topDescription = r.description;
4693 curTask = r.task;
4694 numActivities = numRunning = 0;
4695 }
4696
4697 // Add 'r' into the current task.
4698 numActivities++;
4699 if (r.app != null && r.app.thread != null) {
4700 numRunning++;
4701 }
4702 if (topDescription == null) {
4703 topDescription = r.description;
4704 }
4705
Joe Onorato8a9b2202010-02-26 18:56:32 -08004706 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 TAG, r.intent.getComponent().flattenToShortString()
4708 + ": task=" + r.task);
4709
4710 // If the next one is a different task, generate a new
4711 // TaskInfo entry for what we have.
4712 if (next == null || next.task != curTask) {
4713 ActivityManager.RunningTaskInfo ci
4714 = new ActivityManager.RunningTaskInfo();
4715 ci.id = curTask.taskId;
4716 ci.baseActivity = r.intent.getComponent();
4717 ci.topActivity = top.intent.getComponent();
4718 ci.thumbnail = top.thumbnail;
4719 ci.description = topDescription;
4720 ci.numActivities = numActivities;
4721 ci.numRunning = numRunning;
4722 //System.out.println(
4723 // "#" + maxNum + ": " + " descr=" + ci.description);
4724 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004725 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 TAG, "State=" + top.state + "Idle=" + top.idle
4727 + " app=" + top.app
4728 + " thr=" + (top.app != null ? top.app.thread : null));
4729 if (top.state == ActivityState.RESUMED
4730 || top.state == ActivityState.PAUSING) {
4731 if (top.idle && top.app != null
4732 && top.app.thread != null) {
4733 topRecord = top;
4734 topThumbnail = top.app.thread;
4735 } else {
4736 top.thumbnailNeeded = true;
4737 }
4738 }
4739 if (pending == null) {
4740 pending = new PendingThumbnailsRecord(receiver);
4741 }
4742 pending.pendingRecords.add(top);
4743 }
4744 list.add(ci);
4745 maxNum--;
4746 top = null;
4747 }
4748 }
4749
4750 if (pending != null) {
4751 mPendingThumbnails.add(pending);
4752 }
4753 }
4754
Joe Onorato8a9b2202010-02-26 18:56:32 -08004755 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756
4757 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004758 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 try {
4760 topThumbnail.requestThumbnail(topRecord);
4761 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004762 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 sendPendingThumbnail(null, topRecord, null, null, true);
4764 }
4765 }
4766
4767 if (pending == null && receiver != null) {
4768 // In this case all thumbnails were available and the client
4769 // is being asked to be told when the remaining ones come in...
4770 // which is unusually, since the top-most currently running
4771 // activity should never have a canned thumbnail! Oh well.
4772 try {
4773 receiver.finished();
4774 } catch (RemoteException ex) {
4775 }
4776 }
4777
4778 return list;
4779 }
4780
4781 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4782 int flags) {
4783 synchronized (this) {
4784 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4785 "getRecentTasks()");
4786
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004787 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004789 final int N = mRecentTasks.size();
4790 ArrayList<ActivityManager.RecentTaskInfo> res
4791 = new ArrayList<ActivityManager.RecentTaskInfo>(
4792 maxNum < N ? maxNum : N);
4793 for (int i=0; i<N && maxNum > 0; i++) {
4794 TaskRecord tr = mRecentTasks.get(i);
4795 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4796 || (tr.intent == null)
4797 || ((tr.intent.getFlags()
4798 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4799 ActivityManager.RecentTaskInfo rti
4800 = new ActivityManager.RecentTaskInfo();
4801 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4802 rti.baseIntent = new Intent(
4803 tr.intent != null ? tr.intent : tr.affinityIntent);
4804 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004805
4806 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4807 // Check whether this activity is currently available.
4808 try {
4809 if (rti.origActivity != null) {
4810 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4811 continue;
4812 }
4813 } else if (rti.baseIntent != null) {
4814 if (pm.queryIntentActivities(rti.baseIntent,
4815 null, 0) == null) {
4816 continue;
4817 }
4818 }
4819 } catch (RemoteException e) {
4820 // Will never happen.
4821 }
4822 }
4823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824 res.add(rti);
4825 maxNum--;
4826 }
4827 }
4828 return res;
4829 }
4830 }
4831
4832 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4833 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004834 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 TaskRecord jt = startTask;
4836
4837 // First look backwards
4838 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004839 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 if (r.task != jt) {
4841 jt = r.task;
4842 if (affinity.equals(jt.affinity)) {
4843 return j;
4844 }
4845 }
4846 }
4847
4848 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004849 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004850 jt = startTask;
4851 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004852 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 if (r.task != jt) {
4854 if (affinity.equals(jt.affinity)) {
4855 return j;
4856 }
4857 jt = r.task;
4858 }
4859 }
4860
4861 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004862 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004863 return N-1;
4864 }
4865
4866 return -1;
4867 }
4868
4869 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004870 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004871 */
4872 public void moveTaskToFront(int task) {
4873 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4874 "moveTaskToFront()");
4875
4876 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004877 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4878 Binder.getCallingUid(), "Task to front")) {
4879 return;
4880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 final long origId = Binder.clearCallingIdentity();
4882 try {
4883 int N = mRecentTasks.size();
4884 for (int i=0; i<N; i++) {
4885 TaskRecord tr = mRecentTasks.get(i);
4886 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004887 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004888 return;
4889 }
4890 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004891 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4892 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004893 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004894 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 return;
4896 }
4897 }
4898 } finally {
4899 Binder.restoreCallingIdentity(origId);
4900 }
4901 }
4902 }
4903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 public void moveTaskToBack(int task) {
4905 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4906 "moveTaskToBack()");
4907
4908 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004909 if (mMainStack.mResumedActivity != null
4910 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004911 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4912 Binder.getCallingUid(), "Task to back")) {
4913 return;
4914 }
4915 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004916 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004917 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004918 Binder.restoreCallingIdentity(origId);
4919 }
4920 }
4921
4922 /**
4923 * Moves an activity, and all of the other activities within the same task, to the bottom
4924 * of the history stack. The activity's order within the task is unchanged.
4925 *
4926 * @param token A reference to the activity we wish to move
4927 * @param nonRoot If false then this only works if the activity is the root
4928 * of a task; if true it will work for any activity in a task.
4929 * @return Returns true if the move completed, false if not.
4930 */
4931 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4932 synchronized(this) {
4933 final long origId = Binder.clearCallingIdentity();
4934 int taskId = getTaskForActivityLocked(token, !nonRoot);
4935 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004936 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 }
4938 Binder.restoreCallingIdentity(origId);
4939 }
4940 return false;
4941 }
4942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004943 public void moveTaskBackwards(int task) {
4944 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4945 "moveTaskBackwards()");
4946
4947 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004948 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4949 Binder.getCallingUid(), "Task backwards")) {
4950 return;
4951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 final long origId = Binder.clearCallingIdentity();
4953 moveTaskBackwardsLocked(task);
4954 Binder.restoreCallingIdentity(origId);
4955 }
4956 }
4957
4958 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004959 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 }
4961
4962 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4963 synchronized(this) {
4964 return getTaskForActivityLocked(token, onlyRoot);
4965 }
4966 }
4967
4968 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004969 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970 TaskRecord lastTask = null;
4971 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004972 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004973 if (r == token) {
4974 if (!onlyRoot || lastTask != r.task) {
4975 return r.task.taskId;
4976 }
4977 return -1;
4978 }
4979 lastTask = r.task;
4980 }
4981
4982 return -1;
4983 }
4984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 public void finishOtherInstances(IBinder token, ComponentName className) {
4986 synchronized(this) {
4987 final long origId = Binder.clearCallingIdentity();
4988
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004989 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 TaskRecord lastTask = null;
4991 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004992 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 if (r.realActivity.equals(className)
4994 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004995 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 null, "others")) {
4997 i--;
4998 N--;
4999 }
5000 }
5001 lastTask = r.task;
5002 }
5003
5004 Binder.restoreCallingIdentity(origId);
5005 }
5006 }
5007
5008 // =========================================================
5009 // THUMBNAILS
5010 // =========================================================
5011
5012 public void reportThumbnail(IBinder token,
5013 Bitmap thumbnail, CharSequence description) {
5014 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5015 final long origId = Binder.clearCallingIdentity();
5016 sendPendingThumbnail(null, token, thumbnail, description, true);
5017 Binder.restoreCallingIdentity(origId);
5018 }
5019
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005020 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005021 Bitmap thumbnail, CharSequence description, boolean always) {
5022 TaskRecord task = null;
5023 ArrayList receivers = null;
5024
5025 //System.out.println("Send pending thumbnail: " + r);
5026
5027 synchronized(this) {
5028 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005029 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 if (index < 0) {
5031 return;
5032 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005033 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 }
5035 if (thumbnail == null) {
5036 thumbnail = r.thumbnail;
5037 description = r.description;
5038 }
5039 if (thumbnail == null && !always) {
5040 // If there is no thumbnail, and this entry is not actually
5041 // going away, then abort for now and pick up the next
5042 // thumbnail we get.
5043 return;
5044 }
5045 task = r.task;
5046
5047 int N = mPendingThumbnails.size();
5048 int i=0;
5049 while (i<N) {
5050 PendingThumbnailsRecord pr =
5051 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5052 //System.out.println("Looking in " + pr.pendingRecords);
5053 if (pr.pendingRecords.remove(r)) {
5054 if (receivers == null) {
5055 receivers = new ArrayList();
5056 }
5057 receivers.add(pr);
5058 if (pr.pendingRecords.size() == 0) {
5059 pr.finished = true;
5060 mPendingThumbnails.remove(i);
5061 N--;
5062 continue;
5063 }
5064 }
5065 i++;
5066 }
5067 }
5068
5069 if (receivers != null) {
5070 final int N = receivers.size();
5071 for (int i=0; i<N; i++) {
5072 try {
5073 PendingThumbnailsRecord pr =
5074 (PendingThumbnailsRecord)receivers.get(i);
5075 pr.receiver.newThumbnail(
5076 task != null ? task.taskId : -1, thumbnail, description);
5077 if (pr.finished) {
5078 pr.receiver.finished();
5079 }
5080 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005081 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 }
5083 }
5084 }
5085 }
5086
5087 // =========================================================
5088 // CONTENT PROVIDERS
5089 // =========================================================
5090
5091 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5092 List providers = null;
5093 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005094 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005095 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005096 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 } catch (RemoteException ex) {
5098 }
5099 if (providers != null) {
5100 final int N = providers.size();
5101 for (int i=0; i<N; i++) {
5102 ProviderInfo cpi =
5103 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005104 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 if (cpr == null) {
5106 cpr = new ContentProviderRecord(cpi, app.info);
5107 mProvidersByClass.put(cpi.name, cpr);
5108 }
5109 app.pubProviders.put(cpi.name, cpr);
5110 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005111 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 }
5113 }
5114 return providers;
5115 }
5116
5117 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005118 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5120 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5121 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5122 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005123 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 return null;
5125 }
5126 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5127 cpi.exported ? -1 : cpi.applicationInfo.uid)
5128 == PackageManager.PERMISSION_GRANTED) {
5129 return null;
5130 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005131
5132 PathPermission[] pps = cpi.pathPermissions;
5133 if (pps != null) {
5134 int i = pps.length;
5135 while (i > 0) {
5136 i--;
5137 PathPermission pp = pps[i];
5138 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5139 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005140 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005141 return null;
5142 }
5143 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5144 cpi.exported ? -1 : cpi.applicationInfo.uid)
5145 == PackageManager.PERMISSION_GRANTED) {
5146 return null;
5147 }
5148 }
5149 }
5150
Dianne Hackbornb424b632010-08-18 15:59:05 -07005151 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5152 if (perms != null) {
5153 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5154 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5155 return null;
5156 }
5157 }
5158 }
5159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 String msg = "Permission Denial: opening provider " + cpi.name
5161 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5162 + ", uid=" + callingUid + ") requires "
5163 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005164 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 return msg;
5166 }
5167
5168 private final ContentProviderHolder getContentProviderImpl(
5169 IApplicationThread caller, String name) {
5170 ContentProviderRecord cpr;
5171 ProviderInfo cpi = null;
5172
5173 synchronized(this) {
5174 ProcessRecord r = null;
5175 if (caller != null) {
5176 r = getRecordForAppLocked(caller);
5177 if (r == null) {
5178 throw new SecurityException(
5179 "Unable to find app for caller " + caller
5180 + " (pid=" + Binder.getCallingPid()
5181 + ") when getting content provider " + name);
5182 }
5183 }
5184
5185 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005186 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005187 if (cpr != null) {
5188 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005189 String msg;
5190 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5191 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 }
5193
5194 if (r != null && cpr.canRunHere(r)) {
5195 // This provider has been published or is in the process
5196 // of being published... but it is also allowed to run
5197 // in the caller's process, so don't make a connection
5198 // and just let the caller instantiate its own instance.
5199 if (cpr.provider != null) {
5200 // don't give caller the provider object, it needs
5201 // to make its own.
5202 cpr = new ContentProviderRecord(cpr);
5203 }
5204 return cpr;
5205 }
5206
5207 final long origId = Binder.clearCallingIdentity();
5208
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005209 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 // return it right away.
5211 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005212 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005213 "Adding provider requested by "
5214 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005215 + cpr.info.processName);
5216 Integer cnt = r.conProviders.get(cpr);
5217 if (cnt == null) {
5218 r.conProviders.put(cpr, new Integer(1));
5219 } else {
5220 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005222 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005223 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5224 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005225 // make sure to count it as being accessed and thus
5226 // back up on the LRU list. This is good because
5227 // content providers are often expensive to start.
5228 updateLruProcessLocked(cpr.app, false, true);
5229 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005230 } else {
5231 cpr.externals++;
5232 }
5233
5234 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 updateOomAdjLocked(cpr.app);
5236 }
5237
5238 Binder.restoreCallingIdentity(origId);
5239
5240 } else {
5241 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005242 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005243 resolveContentProvider(name,
5244 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 } catch (RemoteException ex) {
5246 }
5247 if (cpi == null) {
5248 return null;
5249 }
5250
Dianne Hackbornb424b632010-08-18 15:59:05 -07005251 String msg;
5252 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5253 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 }
5255
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005256 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5257 && !cpi.processName.equals("system")) {
5258 // If this content provider does not run in the system
5259 // process, and the system is not yet ready to run other
5260 // processes, then fail fast instead of hanging.
5261 throw new IllegalArgumentException(
5262 "Attempt to launch content provider before system ready");
5263 }
5264
Dianne Hackborn860755f2010-06-03 18:47:52 -07005265 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 final boolean firstClass = cpr == null;
5267 if (firstClass) {
5268 try {
5269 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005270 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 getApplicationInfo(
5272 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005273 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005275 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 + cpi.name);
5277 return null;
5278 }
5279 cpr = new ContentProviderRecord(cpi, ai);
5280 } catch (RemoteException ex) {
5281 // pm is in same process, this will never happen.
5282 }
5283 }
5284
5285 if (r != null && cpr.canRunHere(r)) {
5286 // If this is a multiprocess provider, then just return its
5287 // info and allow the caller to instantiate it. Only do
5288 // this if the provider is the same user as the caller's
5289 // process, or can run as root (so can be in any process).
5290 return cpr;
5291 }
5292
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005293 if (DEBUG_PROVIDER) {
5294 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005295 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005296 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005297 }
5298
5299 // This is single process, and our app is now connecting to it.
5300 // See if we are already in the process of launching this
5301 // provider.
5302 final int N = mLaunchingProviders.size();
5303 int i;
5304 for (i=0; i<N; i++) {
5305 if (mLaunchingProviders.get(i) == cpr) {
5306 break;
5307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005308 }
5309
5310 // If the provider is not already being launched, then get it
5311 // started.
5312 if (i >= N) {
5313 final long origId = Binder.clearCallingIdentity();
5314 ProcessRecord proc = startProcessLocked(cpi.processName,
5315 cpr.appInfo, false, 0, "content provider",
5316 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005317 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005319 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 + cpi.applicationInfo.packageName + "/"
5321 + cpi.applicationInfo.uid + " for provider "
5322 + name + ": process is bad");
5323 return null;
5324 }
5325 cpr.launchingApp = proc;
5326 mLaunchingProviders.add(cpr);
5327 Binder.restoreCallingIdentity(origId);
5328 }
5329
5330 // Make sure the provider is published (the same provider class
5331 // may be published under multiple names).
5332 if (firstClass) {
5333 mProvidersByClass.put(cpi.name, cpr);
5334 }
5335 mProvidersByName.put(name, cpr);
5336
5337 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005338 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005339 "Adding provider requested by "
5340 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005341 + cpr.info.processName);
5342 Integer cnt = r.conProviders.get(cpr);
5343 if (cnt == null) {
5344 r.conProviders.put(cpr, new Integer(1));
5345 } else {
5346 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 cpr.clients.add(r);
5349 } else {
5350 cpr.externals++;
5351 }
5352 }
5353 }
5354
5355 // Wait for the provider to be published...
5356 synchronized (cpr) {
5357 while (cpr.provider == null) {
5358 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005359 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005360 + cpi.applicationInfo.packageName + "/"
5361 + cpi.applicationInfo.uid + " for provider "
5362 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005363 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 cpi.applicationInfo.packageName,
5365 cpi.applicationInfo.uid, name);
5366 return null;
5367 }
5368 try {
5369 cpr.wait();
5370 } catch (InterruptedException ex) {
5371 }
5372 }
5373 }
5374 return cpr;
5375 }
5376
5377 public final ContentProviderHolder getContentProvider(
5378 IApplicationThread caller, String name) {
5379 if (caller == null) {
5380 String msg = "null IApplicationThread when getting content provider "
5381 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005382 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005383 throw new SecurityException(msg);
5384 }
5385
5386 return getContentProviderImpl(caller, name);
5387 }
5388
5389 private ContentProviderHolder getContentProviderExternal(String name) {
5390 return getContentProviderImpl(null, name);
5391 }
5392
5393 /**
5394 * Drop a content provider from a ProcessRecord's bookkeeping
5395 * @param cpr
5396 */
5397 public void removeContentProvider(IApplicationThread caller, String name) {
5398 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005399 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005400 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005401 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005402 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005403 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 return;
5405 }
5406 final ProcessRecord r = getRecordForAppLocked(caller);
5407 if (r == null) {
5408 throw new SecurityException(
5409 "Unable to find app for caller " + caller +
5410 " when removing content provider " + name);
5411 }
5412 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005413 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005414 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005415 + r.info.processName + " from process "
5416 + localCpr.appInfo.processName);
5417 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005418 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005419 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005420 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 return;
5422 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005423 Integer cnt = r.conProviders.get(localCpr);
5424 if (cnt == null || cnt.intValue() <= 1) {
5425 localCpr.clients.remove(r);
5426 r.conProviders.remove(localCpr);
5427 } else {
5428 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005430 }
5431 updateOomAdjLocked();
5432 }
5433 }
5434
5435 private void removeContentProviderExternal(String name) {
5436 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005437 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438 if(cpr == null) {
5439 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005440 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005441 return;
5442 }
5443
5444 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005445 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 localCpr.externals--;
5447 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005448 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 }
5450 updateOomAdjLocked();
5451 }
5452 }
5453
5454 public final void publishContentProviders(IApplicationThread caller,
5455 List<ContentProviderHolder> providers) {
5456 if (providers == null) {
5457 return;
5458 }
5459
5460 synchronized(this) {
5461 final ProcessRecord r = getRecordForAppLocked(caller);
5462 if (r == null) {
5463 throw new SecurityException(
5464 "Unable to find app for caller " + caller
5465 + " (pid=" + Binder.getCallingPid()
5466 + ") when publishing content providers");
5467 }
5468
5469 final long origId = Binder.clearCallingIdentity();
5470
5471 final int N = providers.size();
5472 for (int i=0; i<N; i++) {
5473 ContentProviderHolder src = providers.get(i);
5474 if (src == null || src.info == null || src.provider == null) {
5475 continue;
5476 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005477 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 if (dst != null) {
5479 mProvidersByClass.put(dst.info.name, dst);
5480 String names[] = dst.info.authority.split(";");
5481 for (int j = 0; j < names.length; j++) {
5482 mProvidersByName.put(names[j], dst);
5483 }
5484
5485 int NL = mLaunchingProviders.size();
5486 int j;
5487 for (j=0; j<NL; j++) {
5488 if (mLaunchingProviders.get(j) == dst) {
5489 mLaunchingProviders.remove(j);
5490 j--;
5491 NL--;
5492 }
5493 }
5494 synchronized (dst) {
5495 dst.provider = src.provider;
5496 dst.app = r;
5497 dst.notifyAll();
5498 }
5499 updateOomAdjLocked(r);
5500 }
5501 }
5502
5503 Binder.restoreCallingIdentity(origId);
5504 }
5505 }
5506
5507 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005508 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005509 synchronized (mSelf) {
5510 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5511 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005512 if (providers != null) {
5513 for (int i=providers.size()-1; i>=0; i--) {
5514 ProviderInfo pi = (ProviderInfo)providers.get(i);
5515 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5516 Slog.w(TAG, "Not installing system proc provider " + pi.name
5517 + ": not system .apk");
5518 providers.remove(i);
5519 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005520 }
5521 }
5522 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005523 if (providers != null) {
5524 mSystemThread.installSystemProviders(providers);
5525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526 }
5527
5528 // =========================================================
5529 // GLOBAL MANAGEMENT
5530 // =========================================================
5531
5532 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5533 ApplicationInfo info, String customProcess) {
5534 String proc = customProcess != null ? customProcess : info.processName;
5535 BatteryStatsImpl.Uid.Proc ps = null;
5536 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5537 synchronized (stats) {
5538 ps = stats.getProcessStatsLocked(info.uid, proc);
5539 }
5540 return new ProcessRecord(ps, thread, info, proc);
5541 }
5542
5543 final ProcessRecord addAppLocked(ApplicationInfo info) {
5544 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5545
5546 if (app == null) {
5547 app = newProcessRecordLocked(null, info, null);
5548 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005549 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005550 }
5551
5552 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5553 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5554 app.persistent = true;
5555 app.maxAdj = CORE_SERVER_ADJ;
5556 }
5557 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5558 mPersistentStartingProcesses.add(app);
5559 startProcessLocked(app, "added application", app.processName);
5560 }
5561
5562 return app;
5563 }
5564
5565 public void unhandledBack() {
5566 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5567 "unhandledBack()");
5568
5569 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005570 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005571 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005572 TAG, "Performing unhandledBack(): stack size = " + count);
5573 if (count > 1) {
5574 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005575 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5577 Binder.restoreCallingIdentity(origId);
5578 }
5579 }
5580 }
5581
5582 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5583 String name = uri.getAuthority();
5584 ContentProviderHolder cph = getContentProviderExternal(name);
5585 ParcelFileDescriptor pfd = null;
5586 if (cph != null) {
5587 // We record the binder invoker's uid in thread-local storage before
5588 // going to the content provider to open the file. Later, in the code
5589 // that handles all permissions checks, we look for this uid and use
5590 // that rather than the Activity Manager's own uid. The effect is that
5591 // we do the check against the caller's permissions even though it looks
5592 // to the content provider like the Activity Manager itself is making
5593 // the request.
5594 sCallerIdentity.set(new Identity(
5595 Binder.getCallingPid(), Binder.getCallingUid()));
5596 try {
5597 pfd = cph.provider.openFile(uri, "r");
5598 } catch (FileNotFoundException e) {
5599 // do nothing; pfd will be returned null
5600 } finally {
5601 // Ensure that whatever happens, we clean up the identity state
5602 sCallerIdentity.remove();
5603 }
5604
5605 // We've got the fd now, so we're done with the provider.
5606 removeContentProviderExternal(name);
5607 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005608 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005609 }
5610 return pfd;
5611 }
5612
5613 public void goingToSleep() {
5614 synchronized(this) {
5615 mSleeping = true;
5616 mWindowManager.setEventDispatching(false);
5617
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005618 if (mMainStack.mResumedActivity != null) {
5619 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005621 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005623
5624 // Initialize the wake times of all processes.
5625 checkExcessiveWakeLocksLocked(false);
5626 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5627 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5628 mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 }
5630 }
5631
Dianne Hackborn55280a92009-05-07 15:53:46 -07005632 public boolean shutdown(int timeout) {
5633 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5634 != PackageManager.PERMISSION_GRANTED) {
5635 throw new SecurityException("Requires permission "
5636 + android.Manifest.permission.SHUTDOWN);
5637 }
5638
5639 boolean timedout = false;
5640
5641 synchronized(this) {
5642 mShuttingDown = true;
5643 mWindowManager.setEventDispatching(false);
5644
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005645 if (mMainStack.mResumedActivity != null) {
5646 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005647 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005648 while (mMainStack.mResumedActivity != null
5649 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005650 long delay = endTime - System.currentTimeMillis();
5651 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005652 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005653 timedout = true;
5654 break;
5655 }
5656 try {
5657 this.wait();
5658 } catch (InterruptedException e) {
5659 }
5660 }
5661 }
5662 }
5663
5664 mUsageStatsService.shutdown();
5665 mBatteryStatsService.shutdown();
5666
5667 return timedout;
5668 }
5669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005670 public void wakingUp() {
5671 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005672 if (mMainStack.mGoingToSleep.isHeld()) {
5673 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 }
5675 mWindowManager.setEventDispatching(true);
5676 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005677 mMainStack.resumeTopActivityLocked(null);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005678 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 }
5680 }
5681
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005682 public void stopAppSwitches() {
5683 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5684 != PackageManager.PERMISSION_GRANTED) {
5685 throw new SecurityException("Requires permission "
5686 + android.Manifest.permission.STOP_APP_SWITCHES);
5687 }
5688
5689 synchronized(this) {
5690 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5691 + APP_SWITCH_DELAY_TIME;
5692 mDidAppSwitch = false;
5693 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5694 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5695 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5696 }
5697 }
5698
5699 public void resumeAppSwitches() {
5700 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5701 != PackageManager.PERMISSION_GRANTED) {
5702 throw new SecurityException("Requires permission "
5703 + android.Manifest.permission.STOP_APP_SWITCHES);
5704 }
5705
5706 synchronized(this) {
5707 // Note that we don't execute any pending app switches... we will
5708 // let those wait until either the timeout, or the next start
5709 // activity request.
5710 mAppSwitchesAllowedTime = 0;
5711 }
5712 }
5713
5714 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5715 String name) {
5716 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5717 return true;
5718 }
5719
5720 final int perm = checkComponentPermission(
5721 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5722 callingUid, -1);
5723 if (perm == PackageManager.PERMISSION_GRANTED) {
5724 return true;
5725 }
5726
Joe Onorato8a9b2202010-02-26 18:56:32 -08005727 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005728 return false;
5729 }
5730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005731 public void setDebugApp(String packageName, boolean waitForDebugger,
5732 boolean persistent) {
5733 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5734 "setDebugApp()");
5735
5736 // Note that this is not really thread safe if there are multiple
5737 // callers into it at the same time, but that's not a situation we
5738 // care about.
5739 if (persistent) {
5740 final ContentResolver resolver = mContext.getContentResolver();
5741 Settings.System.putString(
5742 resolver, Settings.System.DEBUG_APP,
5743 packageName);
5744 Settings.System.putInt(
5745 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5746 waitForDebugger ? 1 : 0);
5747 }
5748
5749 synchronized (this) {
5750 if (!persistent) {
5751 mOrigDebugApp = mDebugApp;
5752 mOrigWaitForDebugger = mWaitForDebugger;
5753 }
5754 mDebugApp = packageName;
5755 mWaitForDebugger = waitForDebugger;
5756 mDebugTransient = !persistent;
5757 if (packageName != null) {
5758 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005759 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 Binder.restoreCallingIdentity(origId);
5761 }
5762 }
5763 }
5764
5765 public void setAlwaysFinish(boolean enabled) {
5766 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5767 "setAlwaysFinish()");
5768
5769 Settings.System.putInt(
5770 mContext.getContentResolver(),
5771 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5772
5773 synchronized (this) {
5774 mAlwaysFinishActivities = enabled;
5775 }
5776 }
5777
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005778 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005779 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005780 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005782 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005783 }
5784 }
5785
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005786 public boolean isUserAMonkey() {
5787 // For now the fact that there is a controller implies
5788 // we have a monkey.
5789 synchronized (this) {
5790 return mController != null;
5791 }
5792 }
5793
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005794 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005795 synchronized (this) {
5796 mWatchers.register(watcher);
5797 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005798 }
5799
5800 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005801 synchronized (this) {
5802 mWatchers.unregister(watcher);
5803 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005804 }
5805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 public final void enterSafeMode() {
5807 synchronized(this) {
5808 // It only makes sense to do this before the system is ready
5809 // and started launching other packages.
5810 if (!mSystemReady) {
5811 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005812 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005813 } catch (RemoteException e) {
5814 }
5815
5816 View v = LayoutInflater.from(mContext).inflate(
5817 com.android.internal.R.layout.safe_mode, null);
5818 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5819 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5820 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5821 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5822 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5823 lp.format = v.getBackground().getOpacity();
5824 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5825 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5826 ((WindowManager)mContext.getSystemService(
5827 Context.WINDOW_SERVICE)).addView(v, lp);
5828 }
5829 }
5830 }
5831
5832 public void noteWakeupAlarm(IIntentSender sender) {
5833 if (!(sender instanceof PendingIntentRecord)) {
5834 return;
5835 }
5836 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5837 synchronized (stats) {
5838 if (mBatteryStatsService.isOnBattery()) {
5839 mBatteryStatsService.enforceCallingPermission();
5840 PendingIntentRecord rec = (PendingIntentRecord)sender;
5841 int MY_UID = Binder.getCallingUid();
5842 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5843 BatteryStatsImpl.Uid.Pkg pkg =
5844 stats.getPackageStatsLocked(uid, rec.key.packageName);
5845 pkg.incWakeupsLocked();
5846 }
5847 }
5848 }
5849
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005850 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005852 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005854 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005855 // XXX Note: don't acquire main activity lock here, because the window
5856 // manager calls in with its locks held.
5857
5858 boolean killed = false;
5859 synchronized (mPidsSelfLocked) {
5860 int[] types = new int[pids.length];
5861 int worstType = 0;
5862 for (int i=0; i<pids.length; i++) {
5863 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5864 if (proc != null) {
5865 int type = proc.setAdj;
5866 types[i] = type;
5867 if (type > worstType) {
5868 worstType = type;
5869 }
5870 }
5871 }
5872
5873 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5874 // then constrain it so we will kill all hidden procs.
5875 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5876 worstType = HIDDEN_APP_MIN_ADJ;
5877 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005878 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 for (int i=0; i<pids.length; i++) {
5880 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5881 if (proc == null) {
5882 continue;
5883 }
5884 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005885 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005886 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005887 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5888 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005889 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005890 proc.killedBackground = true;
5891 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005892 }
5893 }
5894 }
5895 return killed;
5896 }
5897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005898 public final void startRunning(String pkg, String cls, String action,
5899 String data) {
5900 synchronized(this) {
5901 if (mStartRunning) {
5902 return;
5903 }
5904 mStartRunning = true;
5905 mTopComponent = pkg != null && cls != null
5906 ? new ComponentName(pkg, cls) : null;
5907 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5908 mTopData = data;
5909 if (!mSystemReady) {
5910 return;
5911 }
5912 }
5913
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005914 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 }
5916
5917 private void retrieveSettings() {
5918 final ContentResolver resolver = mContext.getContentResolver();
5919 String debugApp = Settings.System.getString(
5920 resolver, Settings.System.DEBUG_APP);
5921 boolean waitForDebugger = Settings.System.getInt(
5922 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5923 boolean alwaysFinishActivities = Settings.System.getInt(
5924 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5925
5926 Configuration configuration = new Configuration();
5927 Settings.System.getConfiguration(resolver, configuration);
5928
5929 synchronized (this) {
5930 mDebugApp = mOrigDebugApp = debugApp;
5931 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5932 mAlwaysFinishActivities = alwaysFinishActivities;
5933 // This happens before any activities are started, so we can
5934 // change mConfiguration in-place.
5935 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005936 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005937 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 }
5939 }
5940
5941 public boolean testIsSystemReady() {
5942 // no need to synchronize(this) just to read & return the value
5943 return mSystemReady;
5944 }
5945
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005946 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 // In the simulator, startRunning will never have been called, which
5948 // normally sets a few crucial variables. Do it here instead.
5949 if (!Process.supportsProcesses()) {
5950 mStartRunning = true;
5951 mTopAction = Intent.ACTION_MAIN;
5952 }
5953
5954 synchronized(this) {
5955 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005956 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 return;
5958 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005959
5960 // Check to see if there are any update receivers to run.
5961 if (!mDidUpdate) {
5962 if (mWaitingUpdate) {
5963 return;
5964 }
5965 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5966 List<ResolveInfo> ris = null;
5967 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005968 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005969 intent, null, 0);
5970 } catch (RemoteException e) {
5971 }
5972 if (ris != null) {
5973 for (int i=ris.size()-1; i>=0; i--) {
5974 if ((ris.get(i).activityInfo.applicationInfo.flags
5975 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5976 ris.remove(i);
5977 }
5978 }
5979 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5980 for (int i=0; i<ris.size(); i++) {
5981 ActivityInfo ai = ris.get(i).activityInfo;
5982 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5983 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005984 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005985 finisher = new IIntentReceiver.Stub() {
5986 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005987 String data, Bundle extras, boolean ordered,
5988 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005989 throws RemoteException {
5990 synchronized (ActivityManagerService.this) {
5991 mDidUpdate = true;
5992 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005993 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005994 }
5995 };
5996 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005997 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005998 broadcastIntentLocked(null, null, intent, null, finisher,
5999 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006000 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006001 mWaitingUpdate = true;
6002 }
6003 }
6004 }
6005 if (mWaitingUpdate) {
6006 return;
6007 }
6008 mDidUpdate = true;
6009 }
6010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006011 mSystemReady = true;
6012 if (!mStartRunning) {
6013 return;
6014 }
6015 }
6016
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006017 ArrayList<ProcessRecord> procsToKill = null;
6018 synchronized(mPidsSelfLocked) {
6019 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6020 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6021 if (!isAllowedWhileBooting(proc.info)){
6022 if (procsToKill == null) {
6023 procsToKill = new ArrayList<ProcessRecord>();
6024 }
6025 procsToKill.add(proc);
6026 }
6027 }
6028 }
6029
6030 if (procsToKill != null) {
6031 synchronized(this) {
6032 for (int i=procsToKill.size()-1; i>=0; i--) {
6033 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006034 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006035 removeProcessLocked(proc, true);
6036 }
6037 }
6038 }
6039
Joe Onorato8a9b2202010-02-26 18:56:32 -08006040 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006041 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 SystemClock.uptimeMillis());
6043
6044 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006045 // Make sure we have no pre-ready processes sitting around.
6046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6048 ResolveInfo ri = mContext.getPackageManager()
6049 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006050 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051 CharSequence errorMsg = null;
6052 if (ri != null) {
6053 ActivityInfo ai = ri.activityInfo;
6054 ApplicationInfo app = ai.applicationInfo;
6055 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6056 mTopAction = Intent.ACTION_FACTORY_TEST;
6057 mTopData = null;
6058 mTopComponent = new ComponentName(app.packageName,
6059 ai.name);
6060 } else {
6061 errorMsg = mContext.getResources().getText(
6062 com.android.internal.R.string.factorytest_not_system);
6063 }
6064 } else {
6065 errorMsg = mContext.getResources().getText(
6066 com.android.internal.R.string.factorytest_no_action);
6067 }
6068 if (errorMsg != null) {
6069 mTopAction = null;
6070 mTopData = null;
6071 mTopComponent = null;
6072 Message msg = Message.obtain();
6073 msg.what = SHOW_FACTORY_ERROR_MSG;
6074 msg.getData().putCharSequence("msg", errorMsg);
6075 mHandler.sendMessage(msg);
6076 }
6077 }
6078 }
6079
6080 retrieveSettings();
6081
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006082 if (goingCallback != null) goingCallback.run();
6083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 synchronized (this) {
6085 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6086 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006087 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006088 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006089 if (apps != null) {
6090 int N = apps.size();
6091 int i;
6092 for (i=0; i<N; i++) {
6093 ApplicationInfo info
6094 = (ApplicationInfo)apps.get(i);
6095 if (info != null &&
6096 !info.packageName.equals("android")) {
6097 addAppLocked(info);
6098 }
6099 }
6100 }
6101 } catch (RemoteException ex) {
6102 // pm is in same process, this will never happen.
6103 }
6104 }
6105
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006106 // Start up initial activity.
6107 mBooting = true;
6108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006109 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006110 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006111 Message msg = Message.obtain();
6112 msg.what = SHOW_UID_ERROR_MSG;
6113 mHandler.sendMessage(msg);
6114 }
6115 } catch (RemoteException e) {
6116 }
6117
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006118 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006119 }
6120 }
6121
Dan Egnorb7f03672009-12-09 16:22:32 -08006122 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006123 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006124 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006125 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006126 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006127 startAppProblemLocked(app);
6128 app.stopFreezingAllLocked();
6129 return handleAppCrashLocked(app);
6130 }
6131
Dan Egnorb7f03672009-12-09 16:22:32 -08006132 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006133 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006134 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006135 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006136 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6137 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006138 startAppProblemLocked(app);
6139 app.stopFreezingAllLocked();
6140 }
6141
6142 /**
6143 * Generate a process error record, suitable for attachment to a ProcessRecord.
6144 *
6145 * @param app The ProcessRecord in which the error occurred.
6146 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6147 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006148 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006149 * @param shortMsg Short message describing the crash.
6150 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006151 * @param stackTrace Full crash stack trace, may be null.
6152 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 * @return Returns a fully-formed AppErrorStateInfo record.
6154 */
6155 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006156 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006157 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006159 report.condition = condition;
6160 report.processName = app.processName;
6161 report.pid = app.pid;
6162 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006163 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006164 report.shortMsg = shortMsg;
6165 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006166 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167
6168 return report;
6169 }
6170
Dan Egnor42471dd2010-01-07 17:25:22 -08006171 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006172 synchronized (this) {
6173 app.crashing = false;
6174 app.crashingReport = null;
6175 app.notResponding = false;
6176 app.notRespondingReport = null;
6177 if (app.anrDialog == fromDialog) {
6178 app.anrDialog = null;
6179 }
6180 if (app.waitDialog == fromDialog) {
6181 app.waitDialog = null;
6182 }
6183 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006184 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006185 Slog.i(ActivityManagerService.TAG, "Killing "
6186 + app.processName + " (pid=" + app.pid + "): user's request");
6187 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6188 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006189 Process.killProcess(app.pid);
6190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006191 }
6192 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006193
Dan Egnorb7f03672009-12-09 16:22:32 -08006194 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006195 long now = SystemClock.uptimeMillis();
6196
6197 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6198 app.info.uid);
6199 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6200 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006201 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006202 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006203 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006204 app.info.processName, app.info.uid);
6205 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006206 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6207 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006208 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006209 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006210 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006211 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212 }
6213 }
6214 if (!app.persistent) {
6215 // We don't want to start this process again until the user
6216 // explicitly does so... but for persistent process, we really
6217 // need to keep it running. If a persistent process is actually
6218 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006219 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006220 app.info.processName);
6221 mBadProcesses.put(app.info.processName, app.info.uid, now);
6222 app.bad = true;
6223 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6224 app.removed = true;
6225 removeProcessLocked(app, false);
6226 return false;
6227 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006228 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006229 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006230 if (r.app == app) {
6231 // If the top running activity is from this crashing
6232 // process, then terminate it to avoid getting in a loop.
6233 Slog.w(TAG, " Force finishing activity "
6234 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006235 int index = mMainStack.indexOfTokenLocked(r);
6236 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006237 Activity.RESULT_CANCELED, null, "crashed");
6238 // Also terminate an activities below it that aren't yet
6239 // stopped, to avoid a situation where one will get
6240 // re-start our crashing activity once it gets resumed again.
6241 index--;
6242 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006243 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006244 if (r.state == ActivityState.RESUMED
6245 || r.state == ActivityState.PAUSING
6246 || r.state == ActivityState.PAUSED) {
6247 if (!r.isHomeActivity) {
6248 Slog.w(TAG, " Force finishing activity "
6249 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006250 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006251 Activity.RESULT_CANCELED, null, "crashed");
6252 }
6253 }
6254 }
6255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 }
6257
6258 // Bump up the crash count of any services currently running in the proc.
6259 if (app.services.size() != 0) {
6260 // Any services running in the application need to be placed
6261 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006262 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006263 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006264 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006265 sr.crashCount++;
6266 }
6267 }
6268
6269 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6270 return true;
6271 }
6272
6273 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006274 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6275 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006276 skipCurrentReceiverLocked(app);
6277 }
6278
6279 void skipCurrentReceiverLocked(ProcessRecord app) {
6280 boolean reschedule = false;
6281 BroadcastRecord r = app.curReceiver;
6282 if (r != null) {
6283 // The current broadcast is waiting for this app's receiver
6284 // to be finished. Looks like that's not going to happen, so
6285 // let the broadcast continue.
6286 logBroadcastReceiverDiscard(r);
6287 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6288 r.resultExtras, r.resultAbort, true);
6289 reschedule = true;
6290 }
6291 r = mPendingBroadcast;
6292 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006293 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006294 "skip & discard pending app " + r);
6295 logBroadcastReceiverDiscard(r);
6296 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6297 r.resultExtras, r.resultAbort, true);
6298 reschedule = true;
6299 }
6300 if (reschedule) {
6301 scheduleBroadcastsLocked();
6302 }
6303 }
6304
Dan Egnor60d87622009-12-16 16:32:58 -08006305 /**
6306 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6307 * The application process will exit immediately after this call returns.
6308 * @param app object of the crashing app, null for the system server
6309 * @param crashInfo describing the exception
6310 */
6311 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6312 ProcessRecord r = findAppProcess(app);
6313
6314 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6315 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006316 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006317 crashInfo.exceptionClassName,
6318 crashInfo.exceptionMessage,
6319 crashInfo.throwFileName,
6320 crashInfo.throwLineNumber);
6321
Dan Egnor42471dd2010-01-07 17:25:22 -08006322 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006323
6324 crashApplication(r, crashInfo);
6325 }
6326
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006327 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006328 IBinder app,
6329 int violationMask,
6330 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006331 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006332
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006333 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006334 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006335 boolean logIt = true;
6336 synchronized (mAlreadyLoggedViolatedStacks) {
6337 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6338 logIt = false;
6339 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006340 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006341 // the relative pain numbers, without logging all
6342 // the stack traces repeatedly. We'd want to do
6343 // likewise in the client code, which also does
6344 // dup suppression, before the Binder call.
6345 } else {
6346 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6347 mAlreadyLoggedViolatedStacks.clear();
6348 }
6349 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6350 }
6351 }
6352 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006353 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006354 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006355 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006356
6357 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6358 AppErrorResult result = new AppErrorResult();
6359 synchronized (this) {
6360 final long origId = Binder.clearCallingIdentity();
6361
6362 Message msg = Message.obtain();
6363 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6364 HashMap<String, Object> data = new HashMap<String, Object>();
6365 data.put("result", result);
6366 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006367 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006368 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006369 msg.obj = data;
6370 mHandler.sendMessage(msg);
6371
6372 Binder.restoreCallingIdentity(origId);
6373 }
6374 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006375 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006376 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006377 }
6378
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006379 // Depending on the policy in effect, there could be a bunch of
6380 // these in quick succession so we try to batch these together to
6381 // minimize disk writes, number of dropbox entries, and maximize
6382 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006383 private void logStrictModeViolationToDropBox(
6384 ProcessRecord process,
6385 StrictMode.ViolationInfo info) {
6386 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006387 return;
6388 }
6389 final boolean isSystemApp = process == null ||
6390 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6391 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6392 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6393 final DropBoxManager dbox = (DropBoxManager)
6394 mContext.getSystemService(Context.DROPBOX_SERVICE);
6395
6396 // Exit early if the dropbox isn't configured to accept this report type.
6397 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6398
6399 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006400 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006401 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6402 synchronized (sb) {
6403 bufferWasEmpty = sb.length() == 0;
6404 appendDropBoxProcessHeaders(process, sb);
6405 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6406 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006407 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6408 if (info.violationNumThisLoop != 0) {
6409 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6410 }
6411 if (info != null && info.durationMillis != -1) {
6412 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006413 }
6414 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006415 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6416 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006417 }
6418 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006419
6420 // Only buffer up to ~64k. Various logging bits truncate
6421 // things at 128k.
6422 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006423 }
6424
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006425 // Flush immediately if the buffer's grown too large, or this
6426 // is a non-system app. Non-system apps are isolated with a
6427 // different tag & policy and not batched.
6428 //
6429 // Batching is useful during internal testing with
6430 // StrictMode settings turned up high. Without batching,
6431 // thousands of separate files could be created on boot.
6432 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006433 new Thread("Error dump: " + dropboxTag) {
6434 @Override
6435 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006436 String report;
6437 synchronized (sb) {
6438 report = sb.toString();
6439 sb.delete(0, sb.length());
6440 sb.trimToSize();
6441 }
6442 if (report.length() != 0) {
6443 dbox.addText(dropboxTag, report);
6444 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006445 }
6446 }.start();
6447 return;
6448 }
6449
6450 // System app batching:
6451 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006452 // An existing dropbox-writing thread is outstanding, so
6453 // we don't need to start it up. The existing thread will
6454 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006455 return;
6456 }
6457
6458 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6459 // (After this point, we shouldn't access AMS internal data structures.)
6460 new Thread("Error dump: " + dropboxTag) {
6461 @Override
6462 public void run() {
6463 // 5 second sleep to let stacks arrive and be batched together
6464 try {
6465 Thread.sleep(5000); // 5 seconds
6466 } catch (InterruptedException e) {}
6467
6468 String errorReport;
6469 synchronized (mStrictModeBuffer) {
6470 errorReport = mStrictModeBuffer.toString();
6471 if (errorReport.length() == 0) {
6472 return;
6473 }
6474 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6475 mStrictModeBuffer.trimToSize();
6476 }
6477 dbox.addText(dropboxTag, errorReport);
6478 }
6479 }.start();
6480 }
6481
Dan Egnor60d87622009-12-16 16:32:58 -08006482 /**
6483 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6484 * @param app object of the crashing app, null for the system server
6485 * @param tag reported by the caller
6486 * @param crashInfo describing the context of the error
6487 * @return true if the process should exit immediately (WTF is fatal)
6488 */
6489 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006490 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006491 ProcessRecord r = findAppProcess(app);
6492
6493 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6494 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006495 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006496 tag, crashInfo.exceptionMessage);
6497
Dan Egnor42471dd2010-01-07 17:25:22 -08006498 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006499
Doug Zongker43866e02010-01-07 12:09:54 -08006500 if (Settings.Secure.getInt(mContext.getContentResolver(),
6501 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006502 crashApplication(r, crashInfo);
6503 return true;
6504 } else {
6505 return false;
6506 }
6507 }
6508
6509 /**
6510 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6511 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6512 */
6513 private ProcessRecord findAppProcess(IBinder app) {
6514 if (app == null) {
6515 return null;
6516 }
6517
6518 synchronized (this) {
6519 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6520 final int NA = apps.size();
6521 for (int ia=0; ia<NA; ia++) {
6522 ProcessRecord p = apps.valueAt(ia);
6523 if (p.thread != null && p.thread.asBinder() == app) {
6524 return p;
6525 }
6526 }
6527 }
6528
Joe Onorato8a9b2202010-02-26 18:56:32 -08006529 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006530 return null;
6531 }
6532 }
6533
6534 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006535 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6536 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006537 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006538 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006539 if (process == null || process.pid == MY_PID) {
6540 sb.append("Process: system_server\n");
6541 } else {
6542 sb.append("Process: ").append(process.processName).append("\n");
6543 }
6544 if (process != null) {
6545 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006546 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006547 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6548 for (String pkg : process.pkgList) {
6549 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006550 try {
Dan Egnora455d192010-03-12 08:52:28 -08006551 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6552 if (pi != null) {
6553 sb.append(" v").append(pi.versionCode);
6554 if (pi.versionName != null) {
6555 sb.append(" (").append(pi.versionName).append(")");
6556 }
6557 }
6558 } catch (RemoteException e) {
6559 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006560 }
Dan Egnora455d192010-03-12 08:52:28 -08006561 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006562 }
Dan Egnora455d192010-03-12 08:52:28 -08006563 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006564 }
6565
6566 private static String processClass(ProcessRecord process) {
6567 if (process == null || process.pid == MY_PID) {
6568 return "system_server";
6569 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6570 return "system_app";
6571 } else {
6572 return "data_app";
6573 }
6574 }
6575
6576 /**
6577 * Write a description of an error (crash, WTF, ANR) to the drop box.
6578 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6579 * @param process which caused the error, null means the system server
6580 * @param activity which triggered the error, null if unknown
6581 * @param parent activity related to the error, null if unknown
6582 * @param subject line related to the error, null if absent
6583 * @param report in long form describing the error, null if absent
6584 * @param logFile to include in the report, null if none
6585 * @param crashInfo giving an application stack trace, null if absent
6586 */
6587 public void addErrorToDropBox(String eventType,
6588 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6589 final String report, final File logFile,
6590 final ApplicationErrorReport.CrashInfo crashInfo) {
6591 // NOTE -- this must never acquire the ActivityManagerService lock,
6592 // otherwise the watchdog may be prevented from resetting the system.
6593
6594 final String dropboxTag = processClass(process) + "_" + eventType;
6595 final DropBoxManager dbox = (DropBoxManager)
6596 mContext.getSystemService(Context.DROPBOX_SERVICE);
6597
6598 // Exit early if the dropbox isn't configured to accept this report type.
6599 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6600
6601 final StringBuilder sb = new StringBuilder(1024);
6602 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006603 if (activity != null) {
6604 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6605 }
6606 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6607 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6608 }
6609 if (parent != null && parent != activity) {
6610 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6611 }
6612 if (subject != null) {
6613 sb.append("Subject: ").append(subject).append("\n");
6614 }
6615 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6616 sb.append("\n");
6617
6618 // Do the rest in a worker thread to avoid blocking the caller on I/O
6619 // (After this point, we shouldn't access AMS internal data structures.)
6620 Thread worker = new Thread("Error dump: " + dropboxTag) {
6621 @Override
6622 public void run() {
6623 if (report != null) {
6624 sb.append(report);
6625 }
6626 if (logFile != null) {
6627 try {
6628 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6629 } catch (IOException e) {
6630 Slog.e(TAG, "Error reading " + logFile, e);
6631 }
6632 }
6633 if (crashInfo != null && crashInfo.stackTrace != null) {
6634 sb.append(crashInfo.stackTrace);
6635 }
6636
6637 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6638 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6639 if (lines > 0) {
6640 sb.append("\n");
6641
6642 // Merge several logcat streams, and take the last N lines
6643 InputStreamReader input = null;
6644 try {
6645 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6646 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6647 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6648
6649 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6650 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6651 input = new InputStreamReader(logcat.getInputStream());
6652
6653 int num;
6654 char[] buf = new char[8192];
6655 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6656 } catch (IOException e) {
6657 Slog.e(TAG, "Error running logcat", e);
6658 } finally {
6659 if (input != null) try { input.close(); } catch (IOException e) {}
6660 }
6661 }
6662
6663 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006664 }
Dan Egnora455d192010-03-12 08:52:28 -08006665 };
6666
6667 if (process == null || process.pid == MY_PID) {
6668 worker.run(); // We may be about to die -- need to run this synchronously
6669 } else {
6670 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006671 }
6672 }
6673
6674 /**
6675 * Bring up the "unexpected error" dialog box for a crashing app.
6676 * Deal with edge cases (intercepts from instrumented applications,
6677 * ActivityController, error intent receivers, that sort of thing).
6678 * @param r the application crashing
6679 * @param crashInfo describing the failure
6680 */
6681 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006682 long timeMillis = System.currentTimeMillis();
6683 String shortMsg = crashInfo.exceptionClassName;
6684 String longMsg = crashInfo.exceptionMessage;
6685 String stackTrace = crashInfo.stackTrace;
6686 if (shortMsg != null && longMsg != null) {
6687 longMsg = shortMsg + ": " + longMsg;
6688 } else if (shortMsg != null) {
6689 longMsg = shortMsg;
6690 }
6691
Dan Egnor60d87622009-12-16 16:32:58 -08006692 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006694 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006695 try {
6696 String name = r != null ? r.processName : null;
6697 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006698 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006699 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006700 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006701 + " at watcher's request");
6702 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006703 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006704 }
6705 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006706 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 }
6708 }
6709
6710 final long origId = Binder.clearCallingIdentity();
6711
6712 // If this process is running instrumentation, finish it.
6713 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006714 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006716 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6717 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006718 Bundle info = new Bundle();
6719 info.putString("shortMsg", shortMsg);
6720 info.putString("longMsg", longMsg);
6721 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6722 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006723 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006724 }
6725
Dan Egnor60d87622009-12-16 16:32:58 -08006726 // If we can't identify the process or it's already exceeded its crash quota,
6727 // quit right away without showing a crash dialog.
6728 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006729 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006730 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 }
6732
6733 Message msg = Message.obtain();
6734 msg.what = SHOW_ERROR_MSG;
6735 HashMap data = new HashMap();
6736 data.put("result", result);
6737 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006738 msg.obj = data;
6739 mHandler.sendMessage(msg);
6740
6741 Binder.restoreCallingIdentity(origId);
6742 }
6743
6744 int res = result.get();
6745
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006746 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006747 synchronized (this) {
6748 if (r != null) {
6749 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6750 SystemClock.uptimeMillis());
6751 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006752 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006753 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006754 }
6755 }
6756
6757 if (appErrorIntent != null) {
6758 try {
6759 mContext.startActivity(appErrorIntent);
6760 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006761 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006764 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006765
6766 Intent createAppErrorIntentLocked(ProcessRecord r,
6767 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6768 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006769 if (report == null) {
6770 return null;
6771 }
6772 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6773 result.setComponent(r.errorReportReceiver);
6774 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6775 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6776 return result;
6777 }
6778
Dan Egnorb7f03672009-12-09 16:22:32 -08006779 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6780 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006781 if (r.errorReportReceiver == null) {
6782 return null;
6783 }
6784
6785 if (!r.crashing && !r.notResponding) {
6786 return null;
6787 }
6788
Dan Egnorb7f03672009-12-09 16:22:32 -08006789 ApplicationErrorReport report = new ApplicationErrorReport();
6790 report.packageName = r.info.packageName;
6791 report.installerPackageName = r.errorReportReceiver.getPackageName();
6792 report.processName = r.processName;
6793 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006794 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006795
Dan Egnorb7f03672009-12-09 16:22:32 -08006796 if (r.crashing) {
6797 report.type = ApplicationErrorReport.TYPE_CRASH;
6798 report.crashInfo = crashInfo;
6799 } else if (r.notResponding) {
6800 report.type = ApplicationErrorReport.TYPE_ANR;
6801 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006802
Dan Egnorb7f03672009-12-09 16:22:32 -08006803 report.anrInfo.activity = r.notRespondingReport.tag;
6804 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6805 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006806 }
6807
Dan Egnorb7f03672009-12-09 16:22:32 -08006808 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006809 }
6810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006811 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6812 // assume our apps are happy - lazy create the list
6813 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6814
6815 synchronized (this) {
6816
6817 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006818 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6819 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006820 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6821 // This one's in trouble, so we'll generate a report for it
6822 // crashes are higher priority (in case there's a crash *and* an anr)
6823 ActivityManager.ProcessErrorStateInfo report = null;
6824 if (app.crashing) {
6825 report = app.crashingReport;
6826 } else if (app.notResponding) {
6827 report = app.notRespondingReport;
6828 }
6829
6830 if (report != null) {
6831 if (errList == null) {
6832 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6833 }
6834 errList.add(report);
6835 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006836 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 " crashing = " + app.crashing +
6838 " notResponding = " + app.notResponding);
6839 }
6840 }
6841 }
6842 }
6843
6844 return errList;
6845 }
6846
6847 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6848 // Lazy instantiation of list
6849 List<ActivityManager.RunningAppProcessInfo> runList = null;
6850 synchronized (this) {
6851 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006852 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6853 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6855 // Generate process state info for running application
6856 ActivityManager.RunningAppProcessInfo currApp =
6857 new ActivityManager.RunningAppProcessInfo(app.processName,
6858 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006859 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006860 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07006861 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006863 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006864 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006865 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6866 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6867 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006868 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6869 } else if (adj >= HOME_APP_ADJ) {
6870 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6871 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006872 } else if (adj >= SECONDARY_SERVER_ADJ) {
6873 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006874 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6875 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6876 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6877 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006878 } else if (adj >= VISIBLE_APP_ADJ) {
6879 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6880 } else {
6881 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6882 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006883 currApp.importanceReasonCode = app.adjTypeCode;
6884 if (app.adjSource instanceof ProcessRecord) {
6885 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006886 } else if (app.adjSource instanceof ActivityRecord) {
6887 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006888 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6889 }
6890 if (app.adjTarget instanceof ComponentName) {
6891 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6892 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006893 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006894 // + " lru=" + currApp.lru);
6895 if (runList == null) {
6896 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6897 }
6898 runList.add(currApp);
6899 }
6900 }
6901 }
6902 return runList;
6903 }
6904
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006905 public List<ApplicationInfo> getRunningExternalApplications() {
6906 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6907 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6908 if (runningApps != null && runningApps.size() > 0) {
6909 Set<String> extList = new HashSet<String>();
6910 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6911 if (app.pkgList != null) {
6912 for (String pkg : app.pkgList) {
6913 extList.add(pkg);
6914 }
6915 }
6916 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006917 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006918 for (String pkg : extList) {
6919 try {
6920 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6921 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6922 retList.add(info);
6923 }
6924 } catch (RemoteException e) {
6925 }
6926 }
6927 }
6928 return retList;
6929 }
6930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006931 @Override
6932 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006933 if (checkCallingPermission(android.Manifest.permission.DUMP)
6934 != PackageManager.PERMISSION_GRANTED) {
6935 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6936 + Binder.getCallingPid()
6937 + ", uid=" + Binder.getCallingUid()
6938 + " without permission "
6939 + android.Manifest.permission.DUMP);
6940 return;
6941 }
6942
6943 boolean dumpAll = false;
6944
6945 int opti = 0;
6946 while (opti < args.length) {
6947 String opt = args[opti];
6948 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6949 break;
6950 }
6951 opti++;
6952 if ("-a".equals(opt)) {
6953 dumpAll = true;
6954 } else if ("-h".equals(opt)) {
6955 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006956 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006957 pw.println(" cmd may be one of:");
6958 pw.println(" activities: activity stack state");
6959 pw.println(" broadcasts: broadcast state");
6960 pw.println(" intents: pending intent state");
6961 pw.println(" processes: process state");
6962 pw.println(" providers: content provider state");
6963 pw.println(" services: service state");
6964 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006966 } else {
6967 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006968 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006969 }
6970
6971 // Is the caller requesting to dump a particular piece of data?
6972 if (opti < args.length) {
6973 String cmd = args[opti];
6974 opti++;
6975 if ("activities".equals(cmd) || "a".equals(cmd)) {
6976 synchronized (this) {
6977 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006978 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006979 return;
6980 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6981 synchronized (this) {
6982 dumpBroadcastsLocked(fd, pw, args, opti, true);
6983 }
6984 return;
6985 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6986 synchronized (this) {
6987 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6988 }
6989 return;
6990 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6991 synchronized (this) {
6992 dumpProcessesLocked(fd, pw, args, opti, true);
6993 }
6994 return;
6995 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6996 synchronized (this) {
6997 dumpProvidersLocked(fd, pw, args, opti, true);
6998 }
6999 return;
7000 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007001 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007002 return;
7003 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7004 synchronized (this) {
7005 dumpServicesLocked(fd, pw, args, opti, true);
7006 }
7007 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007008 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007009 }
7010
7011 // No piece of data specified, dump everything.
7012 synchronized (this) {
7013 boolean needSep;
7014 if (dumpAll) {
7015 pw.println("Providers in Current Activity Manager State:");
7016 }
7017 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7018 if (needSep) {
7019 pw.println(" ");
7020 }
7021 if (dumpAll) {
7022 pw.println("-------------------------------------------------------------------------------");
7023 pw.println("Broadcasts in Current Activity Manager State:");
7024 }
7025 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7026 if (needSep) {
7027 pw.println(" ");
7028 }
7029 if (dumpAll) {
7030 pw.println("-------------------------------------------------------------------------------");
7031 pw.println("Services in Current Activity Manager State:");
7032 }
7033 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7034 if (needSep) {
7035 pw.println(" ");
7036 }
7037 if (dumpAll) {
7038 pw.println("-------------------------------------------------------------------------------");
7039 pw.println("PendingIntents in Current Activity Manager State:");
7040 }
7041 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7042 if (needSep) {
7043 pw.println(" ");
7044 }
7045 if (dumpAll) {
7046 pw.println("-------------------------------------------------------------------------------");
7047 pw.println("Activities in Current Activity Manager State:");
7048 }
7049 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7050 if (needSep) {
7051 pw.println(" ");
7052 }
7053 if (dumpAll) {
7054 pw.println("-------------------------------------------------------------------------------");
7055 pw.println("Processes in Current Activity Manager State:");
7056 }
7057 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7058 }
7059 }
7060
7061 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7062 int opti, boolean dumpAll, boolean needHeader) {
7063 if (needHeader) {
7064 pw.println(" Activity stack:");
7065 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007066 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007067 pw.println(" ");
7068 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007069 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7070 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007071 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007072 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007073 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007074 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007075 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007076 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007077 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007078 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007079 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007080 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007081 pw.println(" ");
7082 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007083 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007085
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007086 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007087 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7088 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007089 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007090 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007092 if (dumpAll && mRecentTasks.size() > 0) {
7093 pw.println(" ");
7094 pw.println("Recent tasks in Current Activity Manager State:");
7095
7096 final int N = mRecentTasks.size();
7097 for (int i=0; i<N; i++) {
7098 TaskRecord tr = mRecentTasks.get(i);
7099 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7100 pw.println(tr);
7101 mRecentTasks.get(i).dump(pw, " ");
7102 }
7103 }
7104
7105 pw.println(" ");
7106 pw.println(" mCurTask: " + mCurTask);
7107
7108 return true;
7109 }
7110
7111 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7112 int opti, boolean dumpAll) {
7113 boolean needSep = false;
7114 int numPers = 0;
7115
7116 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7118 final int NA = procs.size();
7119 for (int ia=0; ia<NA; ia++) {
7120 if (!needSep) {
7121 pw.println(" All known processes:");
7122 needSep = true;
7123 }
7124 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007125 pw.print(r.persistent ? " *PERS*" : " *APP*");
7126 pw.print(" UID "); pw.print(procs.keyAt(ia));
7127 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007128 r.dump(pw, " ");
7129 if (r.persistent) {
7130 numPers++;
7131 }
7132 }
7133 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007134 }
7135
7136 if (mLruProcesses.size() > 0) {
7137 if (needSep) pw.println(" ");
7138 needSep = true;
7139 pw.println(" Running processes (most recent first):");
7140 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007141 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007142 needSep = true;
7143 }
7144
7145 synchronized (mPidsSelfLocked) {
7146 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 if (needSep) pw.println(" ");
7148 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007149 pw.println(" PID mappings:");
7150 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7151 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7152 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 }
7154 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007155 }
7156
7157 if (mForegroundProcesses.size() > 0) {
7158 if (needSep) pw.println(" ");
7159 needSep = true;
7160 pw.println(" Foreground Processes:");
7161 for (int i=0; i<mForegroundProcesses.size(); i++) {
7162 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7163 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007164 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007165 }
7166
7167 if (mPersistentStartingProcesses.size() > 0) {
7168 if (needSep) pw.println(" ");
7169 needSep = true;
7170 pw.println(" Persisent processes that are starting:");
7171 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
7172 "Starting Norm", "Restarting PERS", false);
7173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007175 if (mStartingProcesses.size() > 0) {
7176 if (needSep) pw.println(" ");
7177 needSep = true;
7178 pw.println(" Processes that are starting:");
7179 dumpProcessList(pw, this, mStartingProcesses, " ",
7180 "Starting Norm", "Starting PERS", false);
7181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007182
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007183 if (mRemovedProcesses.size() > 0) {
7184 if (needSep) pw.println(" ");
7185 needSep = true;
7186 pw.println(" Processes that are being removed:");
7187 dumpProcessList(pw, this, mRemovedProcesses, " ",
7188 "Removed Norm", "Removed PERS", false);
7189 }
7190
7191 if (mProcessesOnHold.size() > 0) {
7192 if (needSep) pw.println(" ");
7193 needSep = true;
7194 pw.println(" Processes that are on old until the system is ready:");
7195 dumpProcessList(pw, this, mProcessesOnHold, " ",
7196 "OnHold Norm", "OnHold PERS", false);
7197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007198
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007199 if (mProcessesToGc.size() > 0) {
7200 if (needSep) pw.println(" ");
7201 needSep = true;
7202 pw.println(" Processes that are waiting to GC:");
7203 long now = SystemClock.uptimeMillis();
7204 for (int i=0; i<mProcessesToGc.size(); i++) {
7205 ProcessRecord proc = mProcessesToGc.get(i);
7206 pw.print(" Process "); pw.println(proc);
7207 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7208 pw.print(", last gced=");
7209 pw.print(now-proc.lastRequestedGc);
7210 pw.print(" ms ago, last lowMem=");
7211 pw.print(now-proc.lastLowMemory);
7212 pw.println(" ms ago");
7213
7214 }
7215 }
7216
7217 if (mProcessCrashTimes.getMap().size() > 0) {
7218 if (needSep) pw.println(" ");
7219 needSep = true;
7220 pw.println(" Time since processes crashed:");
7221 long now = SystemClock.uptimeMillis();
7222 for (Map.Entry<String, SparseArray<Long>> procs
7223 : mProcessCrashTimes.getMap().entrySet()) {
7224 SparseArray<Long> uids = procs.getValue();
7225 final int N = uids.size();
7226 for (int i=0; i<N; i++) {
7227 pw.print(" Process "); pw.print(procs.getKey());
7228 pw.print(" uid "); pw.print(uids.keyAt(i));
7229 pw.print(": last crashed ");
7230 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007231 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007232 }
7233 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007235
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007236 if (mBadProcesses.getMap().size() > 0) {
7237 if (needSep) pw.println(" ");
7238 needSep = true;
7239 pw.println(" Bad processes:");
7240 for (Map.Entry<String, SparseArray<Long>> procs
7241 : mBadProcesses.getMap().entrySet()) {
7242 SparseArray<Long> uids = procs.getValue();
7243 final int N = uids.size();
7244 for (int i=0; i<N; i++) {
7245 pw.print(" Bad process "); pw.print(procs.getKey());
7246 pw.print(" uid "); pw.print(uids.keyAt(i));
7247 pw.print(": crashed at time ");
7248 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007249 }
7250 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007253 pw.println(" ");
7254 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007255 if (mHeavyWeightProcess != null) {
7256 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7257 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007258 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007259 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007260 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7261 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7262 || mOrigWaitForDebugger) {
7263 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7264 + " mDebugTransient=" + mDebugTransient
7265 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7266 }
7267 if (mAlwaysFinishActivities || mController != null) {
7268 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7269 + " mController=" + mController);
7270 }
7271 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 pw.println(" mStartRunning=" + mStartRunning
7274 + " mSystemReady=" + mSystemReady
7275 + " mBooting=" + mBooting
7276 + " mBooted=" + mBooted
7277 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007278 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7279 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007280 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007281 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007282
7283 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007284 }
7285
7286 /**
7287 * There are three ways to call this:
7288 * - no service specified: dump all the services
7289 * - a flattened component name that matched an existing service was specified as the
7290 * first arg: dump that one service
7291 * - the first arg isn't the flattened component name of an existing service:
7292 * dump all services whose component contains the first arg as a substring
7293 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007294 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7295 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296 String[] newArgs;
7297 String componentNameString;
7298 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007299 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007300 componentNameString = null;
7301 newArgs = EMPTY_STRING_ARRAY;
7302 r = null;
7303 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007304 componentNameString = args[opti];
7305 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007307 synchronized (this) {
7308 r = componentName != null ? mServices.get(componentName) : null;
7309 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007310 newArgs = new String[args.length - opti];
7311 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007312 }
7313
7314 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007315 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007317 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7318 synchronized (this) {
7319 for (ServiceRecord r1 : mServices.values()) {
7320 if (componentNameString == null
7321 || r1.name.flattenToString().contains(componentNameString)) {
7322 services.add(r1);
7323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 }
7325 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007326 for (int i=0; i<services.size(); i++) {
7327 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 }
7330 }
7331
7332 /**
7333 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7334 * there is a thread associated with the service.
7335 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007336 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7337 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007338 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007339 if (dumpAll) {
7340 synchronized (this) {
7341 pw.print(" * "); pw.println(r);
7342 r.dump(pw, " ");
7343 }
7344 pw.println("");
7345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 if (r.app != null && r.app.thread != null) {
7347 try {
7348 // flush anything that is already in the PrintWriter since the thread is going
7349 // to write to the file descriptor directly
7350 pw.flush();
7351 r.app.thread.dumpService(fd, r, args);
7352 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007353 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007354 } catch (RemoteException e) {
7355 pw.println("got a RemoteException while dumping the service");
7356 }
7357 }
7358 }
7359
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007360 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7361 int opti, boolean dumpAll) {
7362 boolean needSep = false;
7363
7364 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 if (mRegisteredReceivers.size() > 0) {
7366 pw.println(" ");
7367 pw.println(" Registered Receivers:");
7368 Iterator it = mRegisteredReceivers.values().iterator();
7369 while (it.hasNext()) {
7370 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007371 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 r.dump(pw, " ");
7373 }
7374 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 pw.println(" ");
7377 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007378 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007379 needSep = true;
7380 }
7381
7382 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7383 || mPendingBroadcast != null) {
7384 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007385 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007386 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007388 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7389 pw.println(" Broadcast #" + i + ":");
7390 mParallelBroadcasts.get(i).dump(pw, " ");
7391 }
7392 if (mOrderedBroadcasts.size() > 0) {
7393 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007394 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007395 }
7396 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7397 pw.println(" Serialized Broadcast #" + i + ":");
7398 mOrderedBroadcasts.get(i).dump(pw, " ");
7399 }
7400 pw.println(" ");
7401 pw.println(" Pending broadcast:");
7402 if (mPendingBroadcast != null) {
7403 mPendingBroadcast.dump(pw, " ");
7404 } else {
7405 pw.println(" (null)");
7406 }
7407 needSep = true;
7408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007410 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007412 pw.println(" Historical broadcasts:");
7413 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7414 BroadcastRecord r = mBroadcastHistory[i];
7415 if (r == null) {
7416 break;
7417 }
7418 pw.println(" Historical Broadcast #" + i + ":");
7419 r.dump(pw, " ");
7420 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007421 needSep = true;
7422 }
7423
7424 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007425 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007426 pw.println(" Sticky broadcasts:");
7427 StringBuilder sb = new StringBuilder(128);
7428 for (Map.Entry<String, ArrayList<Intent>> ent
7429 : mStickyBroadcasts.entrySet()) {
7430 pw.print(" * Sticky action "); pw.print(ent.getKey());
7431 pw.println(":");
7432 ArrayList<Intent> intents = ent.getValue();
7433 final int N = intents.size();
7434 for (int i=0; i<N; i++) {
7435 sb.setLength(0);
7436 sb.append(" Intent: ");
7437 intents.get(i).toShortString(sb, true, false);
7438 pw.println(sb.toString());
7439 Bundle bundle = intents.get(i).getExtras();
7440 if (bundle != null) {
7441 pw.print(" ");
7442 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007443 }
7444 }
7445 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007446 needSep = true;
7447 }
7448
7449 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007450 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007451 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007452 pw.println(" mHandler:");
7453 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007454 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007456
7457 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 }
7459
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007460 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7461 int opti, boolean dumpAll) {
7462 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007464 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 if (mServices.size() > 0) {
7466 pw.println(" Active services:");
7467 Iterator<ServiceRecord> it = mServices.values().iterator();
7468 while (it.hasNext()) {
7469 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007470 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 r.dump(pw, " ");
7472 }
7473 needSep = true;
7474 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007475 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007477 if (mPendingServices.size() > 0) {
7478 if (needSep) pw.println(" ");
7479 pw.println(" Pending services:");
7480 for (int i=0; i<mPendingServices.size(); i++) {
7481 ServiceRecord r = mPendingServices.get(i);
7482 pw.print(" * Pending "); pw.println(r);
7483 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007485 needSep = true;
7486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007488 if (mRestartingServices.size() > 0) {
7489 if (needSep) pw.println(" ");
7490 pw.println(" Restarting services:");
7491 for (int i=0; i<mRestartingServices.size(); i++) {
7492 ServiceRecord r = mRestartingServices.get(i);
7493 pw.print(" * Restarting "); pw.println(r);
7494 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007496 needSep = true;
7497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007498
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007499 if (mStoppingServices.size() > 0) {
7500 if (needSep) pw.println(" ");
7501 pw.println(" Stopping services:");
7502 for (int i=0; i<mStoppingServices.size(); i++) {
7503 ServiceRecord r = mStoppingServices.get(i);
7504 pw.print(" * Stopping "); pw.println(r);
7505 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007507 needSep = true;
7508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007509
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007510 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007511 if (mServiceConnections.size() > 0) {
7512 if (needSep) pw.println(" ");
7513 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007514 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 = mServiceConnections.values().iterator();
7516 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007517 ArrayList<ConnectionRecord> r = it.next();
7518 for (int i=0; i<r.size(); i++) {
7519 pw.print(" * "); pw.println(r.get(i));
7520 r.get(i).dump(pw, " ");
7521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007522 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007523 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007524 }
7525 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007526
7527 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528 }
7529
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007530 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7531 int opti, boolean dumpAll) {
7532 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007533
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007534 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007535 if (mProvidersByClass.size() > 0) {
7536 if (needSep) pw.println(" ");
7537 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007538 Iterator<Map.Entry<String, ContentProviderRecord>> it
7539 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007540 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007541 Map.Entry<String, ContentProviderRecord> e = it.next();
7542 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007543 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007544 r.dump(pw, " ");
7545 }
7546 needSep = true;
7547 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007548
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007549 if (mProvidersByName.size() > 0) {
7550 pw.println(" ");
7551 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007552 Iterator<Map.Entry<String, ContentProviderRecord>> it
7553 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007554 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007555 Map.Entry<String, ContentProviderRecord> e = it.next();
7556 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007557 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7558 pw.println(r);
7559 }
7560 needSep = true;
7561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007562 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007563
7564 if (mLaunchingProviders.size() > 0) {
7565 if (needSep) pw.println(" ");
7566 pw.println(" Launching content providers:");
7567 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7568 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7569 pw.println(mLaunchingProviders.get(i));
7570 }
7571 needSep = true;
7572 }
7573
7574 if (mGrantedUriPermissions.size() > 0) {
7575 pw.println();
7576 pw.println("Granted Uri Permissions:");
7577 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7578 int uid = mGrantedUriPermissions.keyAt(i);
7579 HashMap<Uri, UriPermission> perms
7580 = mGrantedUriPermissions.valueAt(i);
7581 pw.print(" * UID "); pw.print(uid);
7582 pw.println(" holds:");
7583 for (UriPermission perm : perms.values()) {
7584 pw.print(" "); pw.println(perm);
7585 perm.dump(pw, " ");
7586 }
7587 }
7588 needSep = true;
7589 }
7590
7591 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592 }
7593
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007594 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7595 int opti, boolean dumpAll) {
7596 boolean needSep = false;
7597
7598 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 if (this.mIntentSenderRecords.size() > 0) {
7600 Iterator<WeakReference<PendingIntentRecord>> it
7601 = mIntentSenderRecords.values().iterator();
7602 while (it.hasNext()) {
7603 WeakReference<PendingIntentRecord> ref = it.next();
7604 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007605 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007607 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 rec.dump(pw, " ");
7609 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007610 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007611 }
7612 }
7613 }
7614 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007615
7616 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007617 }
7618
7619 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007620 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007621 TaskRecord lastTask = null;
7622 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007623 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007624 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 if (lastTask != r.task) {
7626 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007627 pw.print(prefix);
7628 pw.print(full ? "* " : " ");
7629 pw.println(lastTask);
7630 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007631 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007634 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7635 pw.print(" #"); pw.print(i); pw.print(": ");
7636 pw.println(r);
7637 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007638 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007640 }
7641 }
7642
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007643 private static String buildOomTag(String prefix, String space, int val, int base) {
7644 if (val == base) {
7645 if (space == null) return prefix;
7646 return prefix + " ";
7647 }
7648 return prefix + "+" + Integer.toString(val-base);
7649 }
7650
7651 private static final int dumpProcessList(PrintWriter pw,
7652 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 String prefix, String normalLabel, String persistentLabel,
7654 boolean inclOomAdj) {
7655 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007656 final int N = list.size()-1;
7657 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007658 ProcessRecord r = (ProcessRecord)list.get(i);
7659 if (false) {
7660 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7661 + " #" + i + ":");
7662 r.dump(pw, prefix + " ");
7663 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007664 String oomAdj;
7665 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007666 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007667 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007668 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7669 } else if (r.setAdj >= HOME_APP_ADJ) {
7670 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7671 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7672 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7673 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7674 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007675 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7676 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7677 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7678 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007679 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7680 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7681 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7682 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007683 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007684 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007685 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007686 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007687 } else {
7688 oomAdj = Integer.toString(r.setAdj);
7689 }
7690 String schedGroup;
7691 switch (r.setSchedGroup) {
7692 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7693 schedGroup = "B";
7694 break;
7695 case Process.THREAD_GROUP_DEFAULT:
7696 schedGroup = "F";
7697 break;
7698 default:
7699 schedGroup = Integer.toString(r.setSchedGroup);
7700 break;
7701 }
7702 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007704 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007705 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007706 pw.print(prefix);
7707 pw.print(" ");
7708 if (r.adjTarget instanceof ComponentName) {
7709 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7710 } else if (r.adjTarget != null) {
7711 pw.print(r.adjTarget.toString());
7712 } else {
7713 pw.print("{null}");
7714 }
7715 pw.print("<=");
7716 if (r.adjSource instanceof ProcessRecord) {
7717 pw.print("Proc{");
7718 pw.print(((ProcessRecord)r.adjSource).toShortString());
7719 pw.println("}");
7720 } else if (r.adjSource != null) {
7721 pw.println(r.adjSource.toString());
7722 } else {
7723 pw.println("{null}");
7724 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726 } else {
7727 pw.println(String.format("%s%s #%2d: %s",
7728 prefix, (r.persistent ? persistentLabel : normalLabel),
7729 i, r.toString()));
7730 }
7731 if (r.persistent) {
7732 numPers++;
7733 }
7734 }
7735 return numPers;
7736 }
7737
Dianne Hackborn472ad872010-04-07 17:31:48 -07007738 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007739 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007740 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741 long uptime = SystemClock.uptimeMillis();
7742 long realtime = SystemClock.elapsedRealtime();
7743
7744 if (isCheckinRequest) {
7745 // short checkin version
7746 pw.println(uptime + "," + realtime);
7747 pw.flush();
7748 } else {
7749 pw.println("Applications Memory Usage (kB):");
7750 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7751 }
7752 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7753 ProcessRecord r = (ProcessRecord)list.get(i);
7754 if (r.thread != null) {
7755 if (!isCheckinRequest) {
7756 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7757 pw.flush();
7758 }
7759 try {
7760 r.thread.asBinder().dump(fd, args);
7761 } catch (RemoteException e) {
7762 if (!isCheckinRequest) {
7763 pw.println("Got RemoteException!");
7764 pw.flush();
7765 }
7766 }
7767 }
7768 }
7769 }
7770
7771 /**
7772 * Searches array of arguments for the specified string
7773 * @param args array of argument strings
7774 * @param value value to search for
7775 * @return true if the value is contained in the array
7776 */
7777 private static boolean scanArgs(String[] args, String value) {
7778 if (args != null) {
7779 for (String arg : args) {
7780 if (value.equals(arg)) {
7781 return true;
7782 }
7783 }
7784 }
7785 return false;
7786 }
7787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007788 private final void killServicesLocked(ProcessRecord app,
7789 boolean allowRestart) {
7790 // Report disconnected services.
7791 if (false) {
7792 // XXX we are letting the client link to the service for
7793 // death notifications.
7794 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007795 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007796 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007797 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007798 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007799 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 = r.connections.values().iterator();
7801 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007802 ArrayList<ConnectionRecord> cl = jt.next();
7803 for (int i=0; i<cl.size(); i++) {
7804 ConnectionRecord c = cl.get(i);
7805 if (c.binding.client != app) {
7806 try {
7807 //c.conn.connected(r.className, null);
7808 } catch (Exception e) {
7809 // todo: this should be asynchronous!
7810 Slog.w(TAG, "Exception thrown disconnected servce "
7811 + r.shortName
7812 + " from app " + app.processName, e);
7813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007814 }
7815 }
7816 }
7817 }
7818 }
7819 }
7820 }
7821
7822 // Clean up any connections this application has to other services.
7823 if (app.connections.size() > 0) {
7824 Iterator<ConnectionRecord> it = app.connections.iterator();
7825 while (it.hasNext()) {
7826 ConnectionRecord r = it.next();
7827 removeConnectionLocked(r, app, null);
7828 }
7829 }
7830 app.connections.clear();
7831
7832 if (app.services.size() != 0) {
7833 // Any services running in the application need to be placed
7834 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007835 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007836 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007837 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 synchronized (sr.stats.getBatteryStats()) {
7839 sr.stats.stopLaunchedLocked();
7840 }
7841 sr.app = null;
7842 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007843 if (mStoppingServices.remove(sr)) {
7844 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
7845 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007846
7847 boolean hasClients = sr.bindings.size() > 0;
7848 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007849 Iterator<IntentBindRecord> bindings
7850 = sr.bindings.values().iterator();
7851 while (bindings.hasNext()) {
7852 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007853 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007854 + ": shouldUnbind=" + b.hasBound);
7855 b.binder = null;
7856 b.requested = b.received = b.hasBound = false;
7857 }
7858 }
7859
7860 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007861 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007863 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007864 sr.crashCount, sr.shortName, app.pid);
7865 bringDownServiceLocked(sr, true);
7866 } else if (!allowRestart) {
7867 bringDownServiceLocked(sr, true);
7868 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007869 boolean canceled = scheduleServiceRestartLocked(sr, true);
7870
7871 // Should the service remain running? Note that in the
7872 // extreme case of so many attempts to deliver a command
7873 // that it failed, that we also will stop it here.
7874 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7875 if (sr.pendingStarts.size() == 0) {
7876 sr.startRequested = false;
7877 if (!hasClients) {
7878 // Whoops, no reason to restart!
7879 bringDownServiceLocked(sr, true);
7880 }
7881 }
7882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007883 }
7884 }
7885
7886 if (!allowRestart) {
7887 app.services.clear();
7888 }
7889 }
7890
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007891 // Make sure we have no more records on the stopping list.
7892 int i = mStoppingServices.size();
7893 while (i > 0) {
7894 i--;
7895 ServiceRecord sr = mStoppingServices.get(i);
7896 if (sr.app == app) {
7897 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007898 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007899 }
7900 }
7901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007902 app.executingServices.clear();
7903 }
7904
7905 private final void removeDyingProviderLocked(ProcessRecord proc,
7906 ContentProviderRecord cpr) {
7907 synchronized (cpr) {
7908 cpr.launchingApp = null;
7909 cpr.notifyAll();
7910 }
7911
7912 mProvidersByClass.remove(cpr.info.name);
7913 String names[] = cpr.info.authority.split(";");
7914 for (int j = 0; j < names.length; j++) {
7915 mProvidersByName.remove(names[j]);
7916 }
7917
7918 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7919 while (cit.hasNext()) {
7920 ProcessRecord capp = cit.next();
7921 if (!capp.persistent && capp.thread != null
7922 && capp.pid != 0
7923 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007924 Slog.i(TAG, "Kill " + capp.processName
7925 + " (pid " + capp.pid + "): provider " + cpr.info.name
7926 + " in dying process " + proc.processName);
7927 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7928 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007929 Process.killProcess(capp.pid);
7930 }
7931 }
7932
7933 mLaunchingProviders.remove(cpr);
7934 }
7935
7936 /**
7937 * Main code for cleaning up a process when it has gone away. This is
7938 * called both as a result of the process dying, or directly when stopping
7939 * a process when running in single process mode.
7940 */
7941 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7942 boolean restarting, int index) {
7943 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007944 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007945 }
7946
Dianne Hackborn36124872009-10-08 16:22:03 -07007947 mProcessesToGc.remove(app);
7948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007949 // Dismiss any open dialogs.
7950 if (app.crashDialog != null) {
7951 app.crashDialog.dismiss();
7952 app.crashDialog = null;
7953 }
7954 if (app.anrDialog != null) {
7955 app.anrDialog.dismiss();
7956 app.anrDialog = null;
7957 }
7958 if (app.waitDialog != null) {
7959 app.waitDialog.dismiss();
7960 app.waitDialog = null;
7961 }
7962
7963 app.crashing = false;
7964 app.notResponding = false;
7965
7966 app.resetPackageList();
7967 app.thread = null;
7968 app.forcingToForeground = null;
7969 app.foregroundServices = false;
7970
7971 killServicesLocked(app, true);
7972
7973 boolean restart = false;
7974
7975 int NL = mLaunchingProviders.size();
7976
7977 // Remove published content providers.
7978 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007979 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007981 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007982 cpr.provider = null;
7983 cpr.app = null;
7984
7985 // See if someone is waiting for this provider... in which
7986 // case we don't remove it, but just let it restart.
7987 int i = 0;
7988 if (!app.bad) {
7989 for (; i<NL; i++) {
7990 if (mLaunchingProviders.get(i) == cpr) {
7991 restart = true;
7992 break;
7993 }
7994 }
7995 } else {
7996 i = NL;
7997 }
7998
7999 if (i >= NL) {
8000 removeDyingProviderLocked(app, cpr);
8001 NL = mLaunchingProviders.size();
8002 }
8003 }
8004 app.pubProviders.clear();
8005 }
8006
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008007 // Take care of any launching providers waiting for this process.
8008 if (checkAppInLaunchingProvidersLocked(app, false)) {
8009 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008010 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008012 // Unregister from connected content providers.
8013 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008014 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008015 while (it.hasNext()) {
8016 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8017 cpr.clients.remove(app);
8018 }
8019 app.conProviders.clear();
8020 }
8021
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008022 // At this point there may be remaining entries in mLaunchingProviders
8023 // where we were the only one waiting, so they are no longer of use.
8024 // Look for these and clean up if found.
8025 // XXX Commented out for now. Trying to figure out a way to reproduce
8026 // the actual situation to identify what is actually going on.
8027 if (false) {
8028 for (int i=0; i<NL; i++) {
8029 ContentProviderRecord cpr = (ContentProviderRecord)
8030 mLaunchingProviders.get(i);
8031 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8032 synchronized (cpr) {
8033 cpr.launchingApp = null;
8034 cpr.notifyAll();
8035 }
8036 }
8037 }
8038 }
8039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008040 skipCurrentReceiverLocked(app);
8041
8042 // Unregister any receivers.
8043 if (app.receivers.size() > 0) {
8044 Iterator<ReceiverList> it = app.receivers.iterator();
8045 while (it.hasNext()) {
8046 removeReceiverLocked(it.next());
8047 }
8048 app.receivers.clear();
8049 }
8050
Christopher Tate181fafa2009-05-14 11:12:14 -07008051 // If the app is undergoing backup, tell the backup manager about it
8052 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008053 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008054 try {
8055 IBackupManager bm = IBackupManager.Stub.asInterface(
8056 ServiceManager.getService(Context.BACKUP_SERVICE));
8057 bm.agentDisconnected(app.info.packageName);
8058 } catch (RemoteException e) {
8059 // can't happen; backup manager is local
8060 }
8061 }
8062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 // If the caller is restarting this app, then leave it in its
8064 // current lists and let the caller take care of it.
8065 if (restarting) {
8066 return;
8067 }
8068
8069 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008070 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008071 "Removing non-persistent process during cleanup: " + app);
8072 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008073 if (mHeavyWeightProcess == app) {
8074 mHeavyWeightProcess = null;
8075 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 } else if (!app.removed) {
8078 // This app is persistent, so we need to keep its record around.
8079 // If it is not already on the pending app list, add it there
8080 // and start a new process for it.
8081 app.thread = null;
8082 app.forcingToForeground = null;
8083 app.foregroundServices = false;
8084 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8085 mPersistentStartingProcesses.add(app);
8086 restart = true;
8087 }
8088 }
8089 mProcessesOnHold.remove(app);
8090
The Android Open Source Project4df24232009-03-05 14:34:35 -08008091 if (app == mHomeProcess) {
8092 mHomeProcess = null;
8093 }
8094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008095 if (restart) {
8096 // We have components that still need to be running in the
8097 // process, so re-launch it.
8098 mProcessNames.put(app.processName, app.info.uid, app);
8099 startProcessLocked(app, "restart", app.processName);
8100 } else if (app.pid > 0 && app.pid != MY_PID) {
8101 // Goodbye!
8102 synchronized (mPidsSelfLocked) {
8103 mPidsSelfLocked.remove(app.pid);
8104 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8105 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008106 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008107 }
8108 }
8109
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008110 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8111 // Look through the content providers we are waiting to have launched,
8112 // and if any run in this process then either schedule a restart of
8113 // the process or kill the client waiting for it if this process has
8114 // gone bad.
8115 int NL = mLaunchingProviders.size();
8116 boolean restart = false;
8117 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008118 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008119 if (cpr.launchingApp == app) {
8120 if (!alwaysBad && !app.bad) {
8121 restart = true;
8122 } else {
8123 removeDyingProviderLocked(app, cpr);
8124 NL = mLaunchingProviders.size();
8125 }
8126 }
8127 }
8128 return restart;
8129 }
8130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008131 // =========================================================
8132 // SERVICES
8133 // =========================================================
8134
8135 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8136 ActivityManager.RunningServiceInfo info =
8137 new ActivityManager.RunningServiceInfo();
8138 info.service = r.name;
8139 if (r.app != null) {
8140 info.pid = r.app.pid;
8141 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008142 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 info.process = r.processName;
8144 info.foreground = r.isForeground;
8145 info.activeSince = r.createTime;
8146 info.started = r.startRequested;
8147 info.clientCount = r.connections.size();
8148 info.crashCount = r.crashCount;
8149 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008150 if (r.isForeground) {
8151 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8152 }
8153 if (r.startRequested) {
8154 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8155 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008156 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008157 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8158 }
8159 if (r.app != null && r.app.persistent) {
8160 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8161 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008162
8163 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8164 for (int i=0; i<connl.size(); i++) {
8165 ConnectionRecord conn = connl.get(i);
8166 if (conn.clientLabel != 0) {
8167 info.clientPackage = conn.binding.client.info.packageName;
8168 info.clientLabel = conn.clientLabel;
8169 return info;
8170 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008171 }
8172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 return info;
8174 }
8175
8176 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8177 int flags) {
8178 synchronized (this) {
8179 ArrayList<ActivityManager.RunningServiceInfo> res
8180 = new ArrayList<ActivityManager.RunningServiceInfo>();
8181
8182 if (mServices.size() > 0) {
8183 Iterator<ServiceRecord> it = mServices.values().iterator();
8184 while (it.hasNext() && res.size() < maxNum) {
8185 res.add(makeRunningServiceInfoLocked(it.next()));
8186 }
8187 }
8188
8189 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8190 ServiceRecord r = mRestartingServices.get(i);
8191 ActivityManager.RunningServiceInfo info =
8192 makeRunningServiceInfoLocked(r);
8193 info.restarting = r.nextRestartTime;
8194 res.add(info);
8195 }
8196
8197 return res;
8198 }
8199 }
8200
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008201 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8202 synchronized (this) {
8203 ServiceRecord r = mServices.get(name);
8204 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008205 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8206 for (int i=0; i<conn.size(); i++) {
8207 if (conn.get(i).clientIntent != null) {
8208 return conn.get(i).clientIntent;
8209 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008210 }
8211 }
8212 }
8213 }
8214 return null;
8215 }
8216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 private final ServiceRecord findServiceLocked(ComponentName name,
8218 IBinder token) {
8219 ServiceRecord r = mServices.get(name);
8220 return r == token ? r : null;
8221 }
8222
8223 private final class ServiceLookupResult {
8224 final ServiceRecord record;
8225 final String permission;
8226
8227 ServiceLookupResult(ServiceRecord _record, String _permission) {
8228 record = _record;
8229 permission = _permission;
8230 }
8231 };
8232
8233 private ServiceLookupResult findServiceLocked(Intent service,
8234 String resolvedType) {
8235 ServiceRecord r = null;
8236 if (service.getComponent() != null) {
8237 r = mServices.get(service.getComponent());
8238 }
8239 if (r == null) {
8240 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8241 r = mServicesByIntent.get(filter);
8242 }
8243
8244 if (r == null) {
8245 try {
8246 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008247 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008248 service, resolvedType, 0);
8249 ServiceInfo sInfo =
8250 rInfo != null ? rInfo.serviceInfo : null;
8251 if (sInfo == null) {
8252 return null;
8253 }
8254
8255 ComponentName name = new ComponentName(
8256 sInfo.applicationInfo.packageName, sInfo.name);
8257 r = mServices.get(name);
8258 } catch (RemoteException ex) {
8259 // pm is in same process, this will never happen.
8260 }
8261 }
8262 if (r != null) {
8263 int callingPid = Binder.getCallingPid();
8264 int callingUid = Binder.getCallingUid();
8265 if (checkComponentPermission(r.permission,
8266 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8267 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008268 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008269 + " from pid=" + callingPid
8270 + ", uid=" + callingUid
8271 + " requires " + r.permission);
8272 return new ServiceLookupResult(null, r.permission);
8273 }
8274 return new ServiceLookupResult(r, null);
8275 }
8276 return null;
8277 }
8278
8279 private class ServiceRestarter implements Runnable {
8280 private ServiceRecord mService;
8281
8282 void setService(ServiceRecord service) {
8283 mService = service;
8284 }
8285
8286 public void run() {
8287 synchronized(ActivityManagerService.this) {
8288 performServiceRestartLocked(mService);
8289 }
8290 }
8291 }
8292
8293 private ServiceLookupResult retrieveServiceLocked(Intent service,
8294 String resolvedType, int callingPid, int callingUid) {
8295 ServiceRecord r = null;
8296 if (service.getComponent() != null) {
8297 r = mServices.get(service.getComponent());
8298 }
8299 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8300 r = mServicesByIntent.get(filter);
8301 if (r == null) {
8302 try {
8303 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008304 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008305 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008306 ServiceInfo sInfo =
8307 rInfo != null ? rInfo.serviceInfo : null;
8308 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008309 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008310 ": not found");
8311 return null;
8312 }
8313
8314 ComponentName name = new ComponentName(
8315 sInfo.applicationInfo.packageName, sInfo.name);
8316 r = mServices.get(name);
8317 if (r == null) {
8318 filter = new Intent.FilterComparison(service.cloneFilter());
8319 ServiceRestarter res = new ServiceRestarter();
8320 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8321 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8322 synchronized (stats) {
8323 ss = stats.getServiceStatsLocked(
8324 sInfo.applicationInfo.uid, sInfo.packageName,
8325 sInfo.name);
8326 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008327 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 res.setService(r);
8329 mServices.put(name, r);
8330 mServicesByIntent.put(filter, r);
8331
8332 // Make sure this component isn't in the pending list.
8333 int N = mPendingServices.size();
8334 for (int i=0; i<N; i++) {
8335 ServiceRecord pr = mPendingServices.get(i);
8336 if (pr.name.equals(name)) {
8337 mPendingServices.remove(i);
8338 i--;
8339 N--;
8340 }
8341 }
8342 }
8343 } catch (RemoteException ex) {
8344 // pm is in same process, this will never happen.
8345 }
8346 }
8347 if (r != null) {
8348 if (checkComponentPermission(r.permission,
8349 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8350 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008351 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008352 + " from pid=" + Binder.getCallingPid()
8353 + ", uid=" + Binder.getCallingUid()
8354 + " requires " + r.permission);
8355 return new ServiceLookupResult(null, r.permission);
8356 }
8357 return new ServiceLookupResult(r, null);
8358 }
8359 return null;
8360 }
8361
8362 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8363 long now = SystemClock.uptimeMillis();
8364 if (r.executeNesting == 0 && r.app != null) {
8365 if (r.app.executingServices.size() == 0) {
8366 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8367 msg.obj = r.app;
8368 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8369 }
8370 r.app.executingServices.add(r);
8371 }
8372 r.executeNesting++;
8373 r.executingStart = now;
8374 }
8375
8376 private final void sendServiceArgsLocked(ServiceRecord r,
8377 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008378 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008379 if (N == 0) {
8380 return;
8381 }
8382
Dianne Hackborn39792d22010-08-19 18:01:52 -07008383 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008385 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008386 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8387 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008388 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008389 // If somehow we got a dummy start at the front, then
8390 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008391 continue;
8392 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008393 si.deliveredTime = SystemClock.uptimeMillis();
8394 r.deliveredStarts.add(si);
8395 si.deliveryCount++;
8396 if (si.targetPermissionUid >= 0) {
8397 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008398 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008399 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008400 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008401 bumpServiceExecutingLocked(r);
8402 if (!oomAdjusted) {
8403 oomAdjusted = true;
8404 updateOomAdjLocked(r.app);
8405 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008406 int flags = 0;
8407 if (si.deliveryCount > 0) {
8408 flags |= Service.START_FLAG_RETRY;
8409 }
8410 if (si.doneExecutingCount > 0) {
8411 flags |= Service.START_FLAG_REDELIVERY;
8412 }
8413 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008414 } catch (RemoteException e) {
8415 // Remote process gone... we'll let the normal cleanup take
8416 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008417 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008418 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008419 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008420 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008421 break;
8422 }
8423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008424 }
8425
8426 private final boolean requestServiceBindingLocked(ServiceRecord r,
8427 IntentBindRecord i, boolean rebind) {
8428 if (r.app == null || r.app.thread == null) {
8429 // If service is not currently running, can't yet bind.
8430 return false;
8431 }
8432 if ((!i.requested || rebind) && i.apps.size() > 0) {
8433 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008434 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
8435 + " in " + i + ": shouldUnbind=" + i.hasBound);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 bumpServiceExecutingLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008437 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8438 if (!rebind) {
8439 i.requested = true;
8440 }
8441 i.hasBound = true;
8442 i.doRebind = false;
8443 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008444 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 return false;
8446 }
8447 }
8448 return true;
8449 }
8450
8451 private final void requestServiceBindingsLocked(ServiceRecord r) {
8452 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8453 while (bindings.hasNext()) {
8454 IntentBindRecord i = bindings.next();
8455 if (!requestServiceBindingLocked(r, i, false)) {
8456 break;
8457 }
8458 }
8459 }
8460
8461 private final void realStartServiceLocked(ServiceRecord r,
8462 ProcessRecord app) throws RemoteException {
8463 if (app.thread == null) {
8464 throw new RemoteException();
8465 }
8466
8467 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008468 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008469
8470 app.services.add(r);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008471 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008472 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008473 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008474
8475 boolean created = false;
8476 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008477 mStringBuilder.setLength(0);
8478 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008479 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008480 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008481 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008482 synchronized (r.stats.getBatteryStats()) {
8483 r.stats.startLaunchedLocked();
8484 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008485 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008487 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008488 created = true;
8489 } finally {
8490 if (!created) {
8491 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008492 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 }
8494 }
8495
8496 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008497
8498 // If the service is in the started state, and there are no
8499 // pending arguments, then fake up one so its onStartCommand() will
8500 // be called.
8501 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8502 r.lastStartId++;
8503 if (r.lastStartId < 1) {
8504 r.lastStartId = 1;
8505 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008506 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008507 }
8508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 sendServiceArgsLocked(r, true);
8510 }
8511
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008512 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8513 boolean allowCancel) {
8514 boolean canceled = false;
8515
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008516 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008517 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008518 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008519
8520 // Any delivered but not yet finished starts should be put back
8521 // on the pending list.
8522 final int N = r.deliveredStarts.size();
8523 if (N > 0) {
8524 for (int i=N-1; i>=0; i--) {
8525 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008526 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008527 if (si.intent == null) {
8528 // We'll generate this again if needed.
8529 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8530 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8531 r.pendingStarts.add(0, si);
8532 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8533 dur *= 2;
8534 if (minDuration < dur) minDuration = dur;
8535 if (resetTime < dur) resetTime = dur;
8536 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008537 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008538 + r.name);
8539 canceled = true;
8540 }
8541 }
8542 r.deliveredStarts.clear();
8543 }
8544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008545 r.totalRestartCount++;
8546 if (r.restartDelay == 0) {
8547 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008548 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008549 } else {
8550 // If it has been a "reasonably long time" since the service
8551 // was started, then reset our restart duration back to
8552 // the beginning, so we don't infinitely increase the duration
8553 // on a service that just occasionally gets killed (which is
8554 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008555 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008556 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008557 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008558 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008559 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008560 if (r.restartDelay < minDuration) {
8561 r.restartDelay = minDuration;
8562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008563 }
8564 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008565
8566 r.nextRestartTime = now + r.restartDelay;
8567
8568 // Make sure that we don't end up restarting a bunch of services
8569 // all at the same time.
8570 boolean repeat;
8571 do {
8572 repeat = false;
8573 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8574 ServiceRecord r2 = mRestartingServices.get(i);
8575 if (r2 != r && r.nextRestartTime
8576 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8577 && r.nextRestartTime
8578 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8579 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8580 r.restartDelay = r.nextRestartTime - now;
8581 repeat = true;
8582 break;
8583 }
8584 }
8585 } while (repeat);
8586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008587 if (!mRestartingServices.contains(r)) {
8588 mRestartingServices.add(r);
8589 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008590
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008591 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008593 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008594 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008595 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008596 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008597 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008598 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 r.shortName, r.restartDelay);
8600
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008601 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008602 }
8603
8604 final void performServiceRestartLocked(ServiceRecord r) {
8605 if (!mRestartingServices.contains(r)) {
8606 return;
8607 }
8608 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8609 }
8610
8611 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8612 if (r.restartDelay == 0) {
8613 return false;
8614 }
8615 r.resetRestartCounter();
8616 mRestartingServices.remove(r);
8617 mHandler.removeCallbacks(r.restarter);
8618 return true;
8619 }
8620
8621 private final boolean bringUpServiceLocked(ServiceRecord r,
8622 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008623 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008624 //r.dump(" ");
8625
Dianne Hackborn36124872009-10-08 16:22:03 -07008626 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 sendServiceArgsLocked(r, false);
8628 return true;
8629 }
8630
8631 if (!whileRestarting && r.restartDelay > 0) {
8632 // If waiting for a restart, then do nothing.
8633 return true;
8634 }
8635
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008636 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008638 // We are now bringing the service up, so no longer in the
8639 // restarting state.
8640 mRestartingServices.remove(r);
8641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 final String appName = r.processName;
8643 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8644 if (app != null && app.thread != null) {
8645 try {
8646 realStartServiceLocked(r, app);
8647 return true;
8648 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008649 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 }
8651
8652 // If a dead object exception was thrown -- fall through to
8653 // restart the application.
8654 }
8655
Dianne Hackborn36124872009-10-08 16:22:03 -07008656 // Not running -- get it started, and enqueue this service record
8657 // to be executed when the app comes up.
8658 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8659 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008660 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008661 + r.appInfo.packageName + "/"
8662 + r.appInfo.uid + " for service "
8663 + r.intent.getIntent() + ": process is bad");
8664 bringDownServiceLocked(r, true);
8665 return false;
8666 }
8667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008668 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 mPendingServices.add(r);
8670 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 return true;
8673 }
8674
8675 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008676 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008677 //r.dump(" ");
8678
8679 // Does it still need to run?
8680 if (!force && r.startRequested) {
8681 return;
8682 }
8683 if (r.connections.size() > 0) {
8684 if (!force) {
8685 // XXX should probably keep a count of the number of auto-create
8686 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008687 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008688 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008689 ArrayList<ConnectionRecord> cr = it.next();
8690 for (int i=0; i<cr.size(); i++) {
8691 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8692 return;
8693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 }
8695 }
8696 }
8697
8698 // Report to all of the connections that the service is no longer
8699 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008700 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008701 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008702 ArrayList<ConnectionRecord> c = it.next();
8703 for (int i=0; i<c.size(); i++) {
8704 try {
8705 c.get(i).conn.connected(r.name, null);
8706 } catch (Exception e) {
8707 Slog.w(TAG, "Failure disconnecting service " + r.name +
8708 " to connection " + c.get(i).conn.asBinder() +
8709 " (in " + c.get(i).binding.client.processName + ")", e);
8710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008711 }
8712 }
8713 }
8714
8715 // Tell the service that it has been unbound.
8716 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8717 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8718 while (it.hasNext()) {
8719 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008720 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008721 + ": hasBound=" + ibr.hasBound);
8722 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8723 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008724 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
8725 + " for " + ibr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008726 bumpServiceExecutingLocked(r);
8727 updateOomAdjLocked(r.app);
8728 ibr.hasBound = false;
8729 r.app.thread.scheduleUnbindService(r,
8730 ibr.intent.getIntent());
8731 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008732 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008733 + r.shortName, e);
8734 serviceDoneExecutingLocked(r, true);
8735 }
8736 }
8737 }
8738 }
8739
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008740 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008741 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008742 System.identityHashCode(r), r.shortName,
8743 (r.app != null) ? r.app.pid : -1);
8744
8745 mServices.remove(r.name);
8746 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 r.totalRestartCount = 0;
8748 unscheduleServiceRestartLocked(r);
8749
8750 // Also make sure it is not on the pending list.
8751 int N = mPendingServices.size();
8752 for (int i=0; i<N; i++) {
8753 if (mPendingServices.get(i) == r) {
8754 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008755 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008756 i--;
8757 N--;
8758 }
8759 }
8760
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008761 r.cancelNotification();
8762 r.isForeground = false;
8763 r.foregroundId = 0;
8764 r.foregroundNoti = null;
8765
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008766 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008767 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008768 r.pendingStarts.clear();
8769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008770 if (r.app != null) {
8771 synchronized (r.stats.getBatteryStats()) {
8772 r.stats.stopLaunchedLocked();
8773 }
8774 r.app.services.remove(r);
8775 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008776 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008777 if (DEBUG_SERVICE) {
8778 RuntimeException here = new RuntimeException();
8779 here.fillInStackTrace();
8780 Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
8781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 bumpServiceExecutingLocked(r);
8783 mStoppingServices.add(r);
8784 updateOomAdjLocked(r.app);
8785 r.app.thread.scheduleStopService(r);
8786 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008787 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 + r.shortName, e);
8789 serviceDoneExecutingLocked(r, true);
8790 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008791 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008792 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008793 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008794 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008795 }
8796 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008797 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008798 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008799 }
8800 }
8801
8802 ComponentName startServiceLocked(IApplicationThread caller,
8803 Intent service, String resolvedType,
8804 int callingPid, int callingUid) {
8805 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008806 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 + " type=" + resolvedType + " args=" + service.getExtras());
8808
8809 if (caller != null) {
8810 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8811 if (callerApp == null) {
8812 throw new SecurityException(
8813 "Unable to find app for caller " + caller
8814 + " (pid=" + Binder.getCallingPid()
8815 + ") when starting service " + service);
8816 }
8817 }
8818
8819 ServiceLookupResult res =
8820 retrieveServiceLocked(service, resolvedType,
8821 callingPid, callingUid);
8822 if (res == null) {
8823 return null;
8824 }
8825 if (res.record == null) {
8826 return new ComponentName("!", res.permission != null
8827 ? res.permission : "private to package");
8828 }
8829 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07008830 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
8831 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008832 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008833 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 }
8835 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008836 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008837 r.lastStartId++;
8838 if (r.lastStartId < 1) {
8839 r.lastStartId = 1;
8840 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008841 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
8842 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008843 r.lastActivity = SystemClock.uptimeMillis();
8844 synchronized (r.stats.getBatteryStats()) {
8845 r.stats.startRunningLocked();
8846 }
8847 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8848 return new ComponentName("!", "Service process is bad");
8849 }
8850 return r.name;
8851 }
8852 }
8853
8854 public ComponentName startService(IApplicationThread caller, Intent service,
8855 String resolvedType) {
8856 // Refuse possible leaked file descriptors
8857 if (service != null && service.hasFileDescriptors() == true) {
8858 throw new IllegalArgumentException("File descriptors passed in Intent");
8859 }
8860
8861 synchronized(this) {
8862 final int callingPid = Binder.getCallingPid();
8863 final int callingUid = Binder.getCallingUid();
8864 final long origId = Binder.clearCallingIdentity();
8865 ComponentName res = startServiceLocked(caller, service,
8866 resolvedType, callingPid, callingUid);
8867 Binder.restoreCallingIdentity(origId);
8868 return res;
8869 }
8870 }
8871
8872 ComponentName startServiceInPackage(int uid,
8873 Intent service, String resolvedType) {
8874 synchronized(this) {
8875 final long origId = Binder.clearCallingIdentity();
8876 ComponentName res = startServiceLocked(null, service,
8877 resolvedType, -1, uid);
8878 Binder.restoreCallingIdentity(origId);
8879 return res;
8880 }
8881 }
8882
8883 public int stopService(IApplicationThread caller, Intent service,
8884 String resolvedType) {
8885 // Refuse possible leaked file descriptors
8886 if (service != null && service.hasFileDescriptors() == true) {
8887 throw new IllegalArgumentException("File descriptors passed in Intent");
8888 }
8889
8890 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008891 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008892 + " type=" + resolvedType);
8893
8894 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8895 if (caller != null && callerApp == null) {
8896 throw new SecurityException(
8897 "Unable to find app for caller " + caller
8898 + " (pid=" + Binder.getCallingPid()
8899 + ") when stopping service " + service);
8900 }
8901
8902 // If this service is active, make sure it is stopped.
8903 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8904 if (r != null) {
8905 if (r.record != null) {
8906 synchronized (r.record.stats.getBatteryStats()) {
8907 r.record.stats.stopRunningLocked();
8908 }
8909 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008910 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008911 final long origId = Binder.clearCallingIdentity();
8912 bringDownServiceLocked(r.record, false);
8913 Binder.restoreCallingIdentity(origId);
8914 return 1;
8915 }
8916 return -1;
8917 }
8918 }
8919
8920 return 0;
8921 }
8922
8923 public IBinder peekService(Intent service, String resolvedType) {
8924 // Refuse possible leaked file descriptors
8925 if (service != null && service.hasFileDescriptors() == true) {
8926 throw new IllegalArgumentException("File descriptors passed in Intent");
8927 }
8928
8929 IBinder ret = null;
8930
8931 synchronized(this) {
8932 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8933
8934 if (r != null) {
8935 // r.record is null if findServiceLocked() failed the caller permission check
8936 if (r.record == null) {
8937 throw new SecurityException(
8938 "Permission Denial: Accessing service " + r.record.name
8939 + " from pid=" + Binder.getCallingPid()
8940 + ", uid=" + Binder.getCallingUid()
8941 + " requires " + r.permission);
8942 }
8943 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8944 if (ib != null) {
8945 ret = ib.binder;
8946 }
8947 }
8948 }
8949
8950 return ret;
8951 }
8952
8953 public boolean stopServiceToken(ComponentName className, IBinder token,
8954 int startId) {
8955 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008956 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008957 + " " + token + " startId=" + startId);
8958 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008959 if (r != null) {
8960 if (startId >= 0) {
8961 // Asked to only stop if done with all work. Note that
8962 // to avoid leaks, we will take this as dropping all
8963 // start items up to and including this one.
8964 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8965 if (si != null) {
8966 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008967 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
8968 cur.removeUriPermissionsLocked();
8969 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008970 break;
8971 }
8972 }
8973 }
8974
8975 if (r.lastStartId != startId) {
8976 return false;
8977 }
8978
8979 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008980 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008981 + " is last, but have " + r.deliveredStarts.size()
8982 + " remaining args");
8983 }
8984 }
8985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008986 synchronized (r.stats.getBatteryStats()) {
8987 r.stats.stopRunningLocked();
8988 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008989 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008990 }
8991 final long origId = Binder.clearCallingIdentity();
8992 bringDownServiceLocked(r, false);
8993 Binder.restoreCallingIdentity(origId);
8994 return true;
8995 }
8996 }
8997 return false;
8998 }
8999
9000 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009001 int id, Notification notification, boolean removeNotification) {
9002 final long origId = Binder.clearCallingIdentity();
9003 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009004 synchronized(this) {
9005 ServiceRecord r = findServiceLocked(className, token);
9006 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009007 if (id != 0) {
9008 if (notification == null) {
9009 throw new IllegalArgumentException("null notification");
9010 }
9011 if (r.foregroundId != id) {
9012 r.cancelNotification();
9013 r.foregroundId = id;
9014 }
9015 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9016 r.foregroundNoti = notification;
9017 r.isForeground = true;
9018 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009019 if (r.app != null) {
9020 updateServiceForegroundLocked(r.app, true);
9021 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009022 } else {
9023 if (r.isForeground) {
9024 r.isForeground = false;
9025 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009026 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009027 updateServiceForegroundLocked(r.app, true);
9028 }
9029 }
9030 if (removeNotification) {
9031 r.cancelNotification();
9032 r.foregroundId = 0;
9033 r.foregroundNoti = null;
9034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009035 }
9036 }
9037 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009038 } finally {
9039 Binder.restoreCallingIdentity(origId);
9040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 }
9042
9043 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9044 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009045 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046 if (sr.isForeground) {
9047 anyForeground = true;
9048 break;
9049 }
9050 }
9051 if (anyForeground != proc.foregroundServices) {
9052 proc.foregroundServices = anyForeground;
9053 if (oomAdj) {
9054 updateOomAdjLocked();
9055 }
9056 }
9057 }
9058
9059 public int bindService(IApplicationThread caller, IBinder token,
9060 Intent service, String resolvedType,
9061 IServiceConnection connection, int flags) {
9062 // Refuse possible leaked file descriptors
9063 if (service != null && service.hasFileDescriptors() == true) {
9064 throw new IllegalArgumentException("File descriptors passed in Intent");
9065 }
9066
9067 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009068 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009069 + " type=" + resolvedType + " conn=" + connection.asBinder()
9070 + " flags=0x" + Integer.toHexString(flags));
9071 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9072 if (callerApp == null) {
9073 throw new SecurityException(
9074 "Unable to find app for caller " + caller
9075 + " (pid=" + Binder.getCallingPid()
9076 + ") when binding service " + service);
9077 }
9078
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009079 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009081 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009082 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009083 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009084 return 0;
9085 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009086 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009087 }
9088
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009089 int clientLabel = 0;
9090 PendingIntent clientIntent = null;
9091
9092 if (callerApp.info.uid == Process.SYSTEM_UID) {
9093 // Hacky kind of thing -- allow system stuff to tell us
9094 // what they are, so we can report this elsewhere for
9095 // others to know why certain services are running.
9096 try {
9097 clientIntent = (PendingIntent)service.getParcelableExtra(
9098 Intent.EXTRA_CLIENT_INTENT);
9099 } catch (RuntimeException e) {
9100 }
9101 if (clientIntent != null) {
9102 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9103 if (clientLabel != 0) {
9104 // There are no useful extras in the intent, trash them.
9105 // System code calling with this stuff just needs to know
9106 // this will happen.
9107 service = service.cloneFilter();
9108 }
9109 }
9110 }
9111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 ServiceLookupResult res =
9113 retrieveServiceLocked(service, resolvedType,
9114 Binder.getCallingPid(), Binder.getCallingUid());
9115 if (res == null) {
9116 return 0;
9117 }
9118 if (res.record == null) {
9119 return -1;
9120 }
9121 ServiceRecord s = res.record;
9122
9123 final long origId = Binder.clearCallingIdentity();
9124
9125 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009126 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009127 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009128 }
9129
9130 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9131 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009132 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009133
9134 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009135 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9136 if (clist == null) {
9137 clist = new ArrayList<ConnectionRecord>();
9138 s.connections.put(binder, clist);
9139 }
9140 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009141 b.connections.add(c);
9142 if (activity != null) {
9143 if (activity.connections == null) {
9144 activity.connections = new HashSet<ConnectionRecord>();
9145 }
9146 activity.connections.add(c);
9147 }
9148 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009149 clist = mServiceConnections.get(binder);
9150 if (clist == null) {
9151 clist = new ArrayList<ConnectionRecord>();
9152 mServiceConnections.put(binder, clist);
9153 }
9154 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155
9156 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9157 s.lastActivity = SystemClock.uptimeMillis();
9158 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9159 return 0;
9160 }
9161 }
9162
9163 if (s.app != null) {
9164 // This could have made the service more important.
9165 updateOomAdjLocked(s.app);
9166 }
9167
Joe Onorato8a9b2202010-02-26 18:56:32 -08009168 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009169 + ": received=" + b.intent.received
9170 + " apps=" + b.intent.apps.size()
9171 + " doRebind=" + b.intent.doRebind);
9172
9173 if (s.app != null && b.intent.received) {
9174 // Service is already running, so we can immediately
9175 // publish the connection.
9176 try {
9177 c.conn.connected(s.name, b.intent.binder);
9178 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009179 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009180 + " to connection " + c.conn.asBinder()
9181 + " (in " + c.binding.client.processName + ")", e);
9182 }
9183
9184 // If this is the first app connected back to this binding,
9185 // and the service had previously asked to be told when
9186 // rebound, then do so.
9187 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9188 requestServiceBindingLocked(s, b.intent, true);
9189 }
9190 } else if (!b.intent.requested) {
9191 requestServiceBindingLocked(s, b.intent, false);
9192 }
9193
9194 Binder.restoreCallingIdentity(origId);
9195 }
9196
9197 return 1;
9198 }
9199
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009200 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009201 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009202 IBinder binder = c.conn.asBinder();
9203 AppBindRecord b = c.binding;
9204 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009205 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9206 if (clist != null) {
9207 clist.remove(c);
9208 if (clist.size() == 0) {
9209 s.connections.remove(binder);
9210 }
9211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009212 b.connections.remove(c);
9213 if (c.activity != null && c.activity != skipAct) {
9214 if (c.activity.connections != null) {
9215 c.activity.connections.remove(c);
9216 }
9217 }
9218 if (b.client != skipApp) {
9219 b.client.connections.remove(c);
9220 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009221 clist = mServiceConnections.get(binder);
9222 if (clist != null) {
9223 clist.remove(c);
9224 if (clist.size() == 0) {
9225 mServiceConnections.remove(binder);
9226 }
9227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009228
9229 if (b.connections.size() == 0) {
9230 b.intent.apps.remove(b.client);
9231 }
9232
Joe Onorato8a9b2202010-02-26 18:56:32 -08009233 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009234 + ": shouldUnbind=" + b.intent.hasBound);
9235 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9236 && b.intent.hasBound) {
9237 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009238 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
9239 + " from " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 bumpServiceExecutingLocked(s);
9241 updateOomAdjLocked(s.app);
9242 b.intent.hasBound = false;
9243 // Assume the client doesn't want to know about a rebind;
9244 // we will deal with that later if it asks for one.
9245 b.intent.doRebind = false;
9246 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9247 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009248 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009249 serviceDoneExecutingLocked(s, true);
9250 }
9251 }
9252
9253 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9254 bringDownServiceLocked(s, false);
9255 }
9256 }
9257
9258 public boolean unbindService(IServiceConnection connection) {
9259 synchronized (this) {
9260 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009261 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009262 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9263 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009264 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009265 + connection.asBinder());
9266 return false;
9267 }
9268
9269 final long origId = Binder.clearCallingIdentity();
9270
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009271 while (clist.size() > 0) {
9272 ConnectionRecord r = clist.get(0);
9273 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009274
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009275 if (r.binding.service.app != null) {
9276 // This could have made the service less important.
9277 updateOomAdjLocked(r.binding.service.app);
9278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 }
9280
9281 Binder.restoreCallingIdentity(origId);
9282 }
9283
9284 return true;
9285 }
9286
9287 public void publishService(IBinder token, Intent intent, IBinder service) {
9288 // Refuse possible leaked file descriptors
9289 if (intent != null && intent.hasFileDescriptors() == true) {
9290 throw new IllegalArgumentException("File descriptors passed in Intent");
9291 }
9292
9293 synchronized(this) {
9294 if (!(token instanceof ServiceRecord)) {
9295 throw new IllegalArgumentException("Invalid service token");
9296 }
9297 ServiceRecord r = (ServiceRecord)token;
9298
9299 final long origId = Binder.clearCallingIdentity();
9300
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009301 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302 + " " + intent + ": " + service);
9303 if (r != null) {
9304 Intent.FilterComparison filter
9305 = new Intent.FilterComparison(intent);
9306 IntentBindRecord b = r.bindings.get(filter);
9307 if (b != null && !b.received) {
9308 b.binder = service;
9309 b.requested = true;
9310 b.received = true;
9311 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009312 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009313 = r.connections.values().iterator();
9314 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009315 ArrayList<ConnectionRecord> clist = it.next();
9316 for (int i=0; i<clist.size(); i++) {
9317 ConnectionRecord c = clist.get(i);
9318 if (!filter.equals(c.binding.intent.intent)) {
9319 if (DEBUG_SERVICE) Slog.v(
9320 TAG, "Not publishing to: " + c);
9321 if (DEBUG_SERVICE) Slog.v(
9322 TAG, "Bound intent: " + c.binding.intent.intent);
9323 if (DEBUG_SERVICE) Slog.v(
9324 TAG, "Published intent: " + intent);
9325 continue;
9326 }
9327 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9328 try {
9329 c.conn.connected(r.name, service);
9330 } catch (Exception e) {
9331 Slog.w(TAG, "Failure sending service " + r.name +
9332 " to connection " + c.conn.asBinder() +
9333 " (in " + c.binding.client.processName + ")", e);
9334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009335 }
9336 }
9337 }
9338 }
9339
9340 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9341
9342 Binder.restoreCallingIdentity(origId);
9343 }
9344 }
9345 }
9346
9347 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9348 // Refuse possible leaked file descriptors
9349 if (intent != null && intent.hasFileDescriptors() == true) {
9350 throw new IllegalArgumentException("File descriptors passed in Intent");
9351 }
9352
9353 synchronized(this) {
9354 if (!(token instanceof ServiceRecord)) {
9355 throw new IllegalArgumentException("Invalid service token");
9356 }
9357 ServiceRecord r = (ServiceRecord)token;
9358
9359 final long origId = Binder.clearCallingIdentity();
9360
9361 if (r != null) {
9362 Intent.FilterComparison filter
9363 = new Intent.FilterComparison(intent);
9364 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009365 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 + " at " + b + ": apps="
9367 + (b != null ? b.apps.size() : 0));
9368 if (b != null) {
9369 if (b.apps.size() > 0) {
9370 // Applications have already bound since the last
9371 // unbind, so just rebind right here.
9372 requestServiceBindingLocked(r, b, true);
9373 } else {
9374 // Note to tell the service the next time there is
9375 // a new client.
9376 b.doRebind = true;
9377 }
9378 }
9379
9380 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9381
9382 Binder.restoreCallingIdentity(origId);
9383 }
9384 }
9385 }
9386
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009387 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009388 synchronized(this) {
9389 if (!(token instanceof ServiceRecord)) {
9390 throw new IllegalArgumentException("Invalid service token");
9391 }
9392 ServiceRecord r = (ServiceRecord)token;
9393 boolean inStopping = mStoppingServices.contains(token);
9394 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009396 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009397 + " with incorrect token: given " + token
9398 + ", expected " + r);
9399 return;
9400 }
9401
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009402 if (type == 1) {
9403 // This is a call from a service start... take care of
9404 // book-keeping.
9405 r.callStart = true;
9406 switch (res) {
9407 case Service.START_STICKY_COMPATIBILITY:
9408 case Service.START_STICKY: {
9409 // We are done with the associated start arguments.
9410 r.findDeliveredStart(startId, true);
9411 // Don't stop if killed.
9412 r.stopIfKilled = false;
9413 break;
9414 }
9415 case Service.START_NOT_STICKY: {
9416 // We are done with the associated start arguments.
9417 r.findDeliveredStart(startId, true);
9418 if (r.lastStartId == startId) {
9419 // There is no more work, and this service
9420 // doesn't want to hang around if killed.
9421 r.stopIfKilled = true;
9422 }
9423 break;
9424 }
9425 case Service.START_REDELIVER_INTENT: {
9426 // We'll keep this item until they explicitly
9427 // call stop for it, but keep track of the fact
9428 // that it was delivered.
9429 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9430 if (si != null) {
9431 si.deliveryCount = 0;
9432 si.doneExecutingCount++;
9433 // Don't stop if killed.
9434 r.stopIfKilled = true;
9435 }
9436 break;
9437 }
9438 default:
9439 throw new IllegalArgumentException(
9440 "Unknown service start result: " + res);
9441 }
9442 if (res == Service.START_STICKY_COMPATIBILITY) {
9443 r.callStart = false;
9444 }
9445 }
9446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009447 final long origId = Binder.clearCallingIdentity();
9448 serviceDoneExecutingLocked(r, inStopping);
9449 Binder.restoreCallingIdentity(origId);
9450 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009451 Slog.w(TAG, "Done executing unknown service from pid "
9452 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009453 }
9454 }
9455 }
9456
9457 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009458 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9459 + ": nesting=" + r.executeNesting
9460 + ", inStopping=" + inStopping + ", app=" + r.app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461 r.executeNesting--;
9462 if (r.executeNesting <= 0 && r.app != null) {
9463 r.app.executingServices.remove(r);
9464 if (r.app.executingServices.size() == 0) {
9465 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9466 }
9467 if (inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009468 if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009469 mStoppingServices.remove(r);
9470 }
9471 updateOomAdjLocked(r.app);
9472 }
9473 }
9474
9475 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009476 String anrMessage = null;
9477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009478 synchronized(this) {
9479 if (proc.executingServices.size() == 0 || proc.thread == null) {
9480 return;
9481 }
9482 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9483 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9484 ServiceRecord timeout = null;
9485 long nextTime = 0;
9486 while (it.hasNext()) {
9487 ServiceRecord sr = it.next();
9488 if (sr.executingStart < maxTime) {
9489 timeout = sr;
9490 break;
9491 }
9492 if (sr.executingStart > nextTime) {
9493 nextTime = sr.executingStart;
9494 }
9495 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009496 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009497 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009498 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009499 } else {
9500 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9501 msg.obj = proc;
9502 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9503 }
9504 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009505
9506 if (anrMessage != null) {
9507 appNotResponding(proc, null, null, anrMessage);
9508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009509 }
9510
9511 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009512 // BACKUP AND RESTORE
9513 // =========================================================
9514
9515 // Cause the target app to be launched if necessary and its backup agent
9516 // instantiated. The backup agent will invoke backupAgentCreated() on the
9517 // activity manager to announce its creation.
9518 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009519 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009520 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9521
9522 synchronized(this) {
9523 // !!! TODO: currently no check here that we're already bound
9524 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9525 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9526 synchronized (stats) {
9527 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9528 }
9529
9530 BackupRecord r = new BackupRecord(ss, app, backupMode);
9531 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9532 // startProcessLocked() returns existing proc's record if it's already running
9533 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009534 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009535 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009536 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009537 return false;
9538 }
9539
9540 r.app = proc;
9541 mBackupTarget = r;
9542 mBackupAppName = app.packageName;
9543
Christopher Tate6fa95972009-06-05 18:43:55 -07009544 // Try not to kill the process during backup
9545 updateOomAdjLocked(proc);
9546
Christopher Tate181fafa2009-05-14 11:12:14 -07009547 // If the process is already attached, schedule the creation of the backup agent now.
9548 // If it is not yet live, this will be done when it attaches to the framework.
9549 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009550 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009551 try {
9552 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9553 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009554 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009555 }
9556 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009557 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009558 }
9559 // Invariants: at this point, the target app process exists and the application
9560 // is either already running or in the process of coming up. mBackupTarget and
9561 // mBackupAppName describe the app, so that when it binds back to the AM we
9562 // know that it's scheduled for a backup-agent operation.
9563 }
9564
9565 return true;
9566 }
9567
9568 // A backup agent has just come up
9569 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009570 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009571 + " = " + agent);
9572
9573 synchronized(this) {
9574 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009575 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009576 return;
9577 }
9578
Christopher Tate043dadc2009-06-02 16:11:00 -07009579 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009580 try {
9581 IBackupManager bm = IBackupManager.Stub.asInterface(
9582 ServiceManager.getService(Context.BACKUP_SERVICE));
9583 bm.agentConnected(agentPackageName, agent);
9584 } catch (RemoteException e) {
9585 // can't happen; the backup manager service is local
9586 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009587 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009588 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009589 } finally {
9590 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009591 }
9592 }
9593 }
9594
9595 // done with this agent
9596 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009597 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009598 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009599 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009600 return;
9601 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009602
9603 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009604 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009605 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009606 return;
9607 }
9608
Christopher Tate181fafa2009-05-14 11:12:14 -07009609 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009610 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009611 return;
9612 }
9613
Christopher Tate6fa95972009-06-05 18:43:55 -07009614 ProcessRecord proc = mBackupTarget.app;
9615 mBackupTarget = null;
9616 mBackupAppName = null;
9617
9618 // Not backing this app up any more; reset its OOM adjustment
9619 updateOomAdjLocked(proc);
9620
Christopher Tatec7b31e32009-06-10 15:49:30 -07009621 // If the app crashed during backup, 'thread' will be null here
9622 if (proc.thread != null) {
9623 try {
9624 proc.thread.scheduleDestroyBackupAgent(appInfo);
9625 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009626 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009627 e.printStackTrace();
9628 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009629 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009630 }
9631 }
9632 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009633 // BROADCASTS
9634 // =========================================================
9635
Josh Bartel7f208742010-02-25 11:01:44 -06009636 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009637 List cur) {
9638 final ContentResolver resolver = mContext.getContentResolver();
9639 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9640 if (list == null) {
9641 return cur;
9642 }
9643 int N = list.size();
9644 for (int i=0; i<N; i++) {
9645 Intent intent = list.get(i);
9646 if (filter.match(resolver, intent, true, TAG) >= 0) {
9647 if (cur == null) {
9648 cur = new ArrayList<Intent>();
9649 }
9650 cur.add(intent);
9651 }
9652 }
9653 return cur;
9654 }
9655
9656 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009657 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009658 + mBroadcastsScheduled);
9659
9660 if (mBroadcastsScheduled) {
9661 return;
9662 }
9663 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9664 mBroadcastsScheduled = true;
9665 }
9666
9667 public Intent registerReceiver(IApplicationThread caller,
9668 IIntentReceiver receiver, IntentFilter filter, String permission) {
9669 synchronized(this) {
9670 ProcessRecord callerApp = null;
9671 if (caller != null) {
9672 callerApp = getRecordForAppLocked(caller);
9673 if (callerApp == null) {
9674 throw new SecurityException(
9675 "Unable to find app for caller " + caller
9676 + " (pid=" + Binder.getCallingPid()
9677 + ") when registering receiver " + receiver);
9678 }
9679 }
9680
9681 List allSticky = null;
9682
9683 // Look for any matching sticky broadcasts...
9684 Iterator actions = filter.actionsIterator();
9685 if (actions != null) {
9686 while (actions.hasNext()) {
9687 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009688 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 }
9690 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009691 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 }
9693
9694 // The first sticky in the list is returned directly back to
9695 // the client.
9696 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9697
Joe Onorato8a9b2202010-02-26 18:56:32 -08009698 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009699 + ": " + sticky);
9700
9701 if (receiver == null) {
9702 return sticky;
9703 }
9704
9705 ReceiverList rl
9706 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9707 if (rl == null) {
9708 rl = new ReceiverList(this, callerApp,
9709 Binder.getCallingPid(),
9710 Binder.getCallingUid(), receiver);
9711 if (rl.app != null) {
9712 rl.app.receivers.add(rl);
9713 } else {
9714 try {
9715 receiver.asBinder().linkToDeath(rl, 0);
9716 } catch (RemoteException e) {
9717 return sticky;
9718 }
9719 rl.linkedToDeath = true;
9720 }
9721 mRegisteredReceivers.put(receiver.asBinder(), rl);
9722 }
9723 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9724 rl.add(bf);
9725 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009726 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009727 }
9728 mReceiverResolver.addFilter(bf);
9729
9730 // Enqueue broadcasts for all existing stickies that match
9731 // this filter.
9732 if (allSticky != null) {
9733 ArrayList receivers = new ArrayList();
9734 receivers.add(bf);
9735
9736 int N = allSticky.size();
9737 for (int i=0; i<N; i++) {
9738 Intent intent = (Intent)allSticky.get(i);
9739 BroadcastRecord r = new BroadcastRecord(intent, null,
9740 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009741 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009742 if (mParallelBroadcasts.size() == 0) {
9743 scheduleBroadcastsLocked();
9744 }
9745 mParallelBroadcasts.add(r);
9746 }
9747 }
9748
9749 return sticky;
9750 }
9751 }
9752
9753 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009754 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009755
9756 boolean doNext = false;
9757
9758 synchronized(this) {
9759 ReceiverList rl
9760 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9761 if (rl != null) {
9762 if (rl.curBroadcast != null) {
9763 BroadcastRecord r = rl.curBroadcast;
9764 doNext = finishReceiverLocked(
9765 receiver.asBinder(), r.resultCode, r.resultData,
9766 r.resultExtras, r.resultAbort, true);
9767 }
9768
9769 if (rl.app != null) {
9770 rl.app.receivers.remove(rl);
9771 }
9772 removeReceiverLocked(rl);
9773 if (rl.linkedToDeath) {
9774 rl.linkedToDeath = false;
9775 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9776 }
9777 }
9778 }
9779
9780 if (!doNext) {
9781 return;
9782 }
9783
9784 final long origId = Binder.clearCallingIdentity();
9785 processNextBroadcast(false);
9786 trimApplications();
9787 Binder.restoreCallingIdentity(origId);
9788 }
9789
9790 void removeReceiverLocked(ReceiverList rl) {
9791 mRegisteredReceivers.remove(rl.receiver.asBinder());
9792 int N = rl.size();
9793 for (int i=0; i<N; i++) {
9794 mReceiverResolver.removeFilter(rl.get(i));
9795 }
9796 }
9797
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009798 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9799 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9800 ProcessRecord r = mLruProcesses.get(i);
9801 if (r.thread != null) {
9802 try {
9803 r.thread.dispatchPackageBroadcast(cmd, packages);
9804 } catch (RemoteException ex) {
9805 }
9806 }
9807 }
9808 }
9809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009810 private final int broadcastIntentLocked(ProcessRecord callerApp,
9811 String callerPackage, Intent intent, String resolvedType,
9812 IIntentReceiver resultTo, int resultCode, String resultData,
9813 Bundle map, String requiredPermission,
9814 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9815 intent = new Intent(intent);
9816
Joe Onorato8a9b2202010-02-26 18:56:32 -08009817 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009818 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9819 + " ordered=" + ordered);
9820 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009821 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009822 }
9823
9824 // Handle special intents: if this broadcast is from the package
9825 // manager about a package being removed, we need to remove all of
9826 // its activities from the history stack.
9827 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9828 intent.getAction());
9829 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9830 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009831 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 || uidRemoved) {
9833 if (checkComponentPermission(
9834 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9835 callingPid, callingUid, -1)
9836 == PackageManager.PERMISSION_GRANTED) {
9837 if (uidRemoved) {
9838 final Bundle intentExtras = intent.getExtras();
9839 final int uid = intentExtras != null
9840 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9841 if (uid >= 0) {
9842 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9843 synchronized (bs) {
9844 bs.removeUidStatsLocked(uid);
9845 }
9846 }
9847 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009848 // If resources are unvailble just force stop all
9849 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009850 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009851 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9852 if (list != null && (list.length > 0)) {
9853 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009854 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009855 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009856 sendPackageBroadcastLocked(
9857 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009858 }
9859 } else {
9860 Uri data = intent.getData();
9861 String ssp;
9862 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9863 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9864 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009865 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009866 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009867 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9868 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9869 new String[] {ssp});
9870 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009871 }
9872 }
9873 }
9874 } else {
9875 String msg = "Permission Denial: " + intent.getAction()
9876 + " broadcast from " + callerPackage + " (pid=" + callingPid
9877 + ", uid=" + callingUid + ")"
9878 + " requires "
9879 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009880 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009881 throw new SecurityException(msg);
9882 }
9883 }
9884
9885 /*
9886 * If this is the time zone changed action, queue up a message that will reset the timezone
9887 * of all currently running processes. This message will get queued up before the broadcast
9888 * happens.
9889 */
9890 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9891 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9892 }
9893
Dianne Hackborn854060af2009-07-09 18:14:31 -07009894 /*
9895 * Prevent non-system code (defined here to be non-persistent
9896 * processes) from sending protected broadcasts.
9897 */
9898 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9899 || callingUid == Process.SHELL_UID || callingUid == 0) {
9900 // Always okay.
9901 } else if (callerApp == null || !callerApp.persistent) {
9902 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009903 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009904 intent.getAction())) {
9905 String msg = "Permission Denial: not allowed to send broadcast "
9906 + intent.getAction() + " from pid="
9907 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009908 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009909 throw new SecurityException(msg);
9910 }
9911 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009912 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009913 return BROADCAST_SUCCESS;
9914 }
9915 }
9916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009917 // Add to the sticky list if requested.
9918 if (sticky) {
9919 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9920 callingPid, callingUid)
9921 != PackageManager.PERMISSION_GRANTED) {
9922 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9923 + callingPid + ", uid=" + callingUid
9924 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009925 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009926 throw new SecurityException(msg);
9927 }
9928 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009929 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009930 + " and enforce permission " + requiredPermission);
9931 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9932 }
9933 if (intent.getComponent() != null) {
9934 throw new SecurityException(
9935 "Sticky broadcasts can't target a specific component");
9936 }
9937 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9938 if (list == null) {
9939 list = new ArrayList<Intent>();
9940 mStickyBroadcasts.put(intent.getAction(), list);
9941 }
9942 int N = list.size();
9943 int i;
9944 for (i=0; i<N; i++) {
9945 if (intent.filterEquals(list.get(i))) {
9946 // This sticky already exists, replace it.
9947 list.set(i, new Intent(intent));
9948 break;
9949 }
9950 }
9951 if (i >= N) {
9952 list.add(new Intent(intent));
9953 }
9954 }
9955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009956 // Figure out who all will receive this broadcast.
9957 List receivers = null;
9958 List<BroadcastFilter> registeredReceivers = null;
9959 try {
9960 if (intent.getComponent() != null) {
9961 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009962 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009963 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009964 if (ai != null) {
9965 receivers = new ArrayList();
9966 ResolveInfo ri = new ResolveInfo();
9967 ri.activityInfo = ai;
9968 receivers.add(ri);
9969 }
9970 } else {
9971 // Need to resolve the intent to interested receivers...
9972 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9973 == 0) {
9974 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009975 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009976 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977 }
Mihai Preda074edef2009-05-18 17:13:31 +02009978 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009979 }
9980 } catch (RemoteException ex) {
9981 // pm is in same process, this will never happen.
9982 }
9983
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009984 final boolean replacePending =
9985 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9986
Joe Onorato8a9b2202010-02-26 18:56:32 -08009987 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009988 + " replacePending=" + replacePending);
9989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009990 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9991 if (!ordered && NR > 0) {
9992 // If we are not serializing this broadcast, then send the
9993 // registered receivers separately so they don't wait for the
9994 // components to be launched.
9995 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9996 callerPackage, callingPid, callingUid, requiredPermission,
9997 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009998 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009999 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 TAG, "Enqueueing parallel broadcast " + r
10001 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010002 boolean replaced = false;
10003 if (replacePending) {
10004 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10005 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010006 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010007 "***** DROPPING PARALLEL: " + intent);
10008 mParallelBroadcasts.set(i, r);
10009 replaced = true;
10010 break;
10011 }
10012 }
10013 }
10014 if (!replaced) {
10015 mParallelBroadcasts.add(r);
10016 scheduleBroadcastsLocked();
10017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010018 registeredReceivers = null;
10019 NR = 0;
10020 }
10021
10022 // Merge into one list.
10023 int ir = 0;
10024 if (receivers != null) {
10025 // A special case for PACKAGE_ADDED: do not allow the package
10026 // being added to see this broadcast. This prevents them from
10027 // using this as a back door to get run as soon as they are
10028 // installed. Maybe in the future we want to have a special install
10029 // broadcast or such for apps, but we'd like to deliberately make
10030 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010031 String skipPackages[] = null;
10032 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10033 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10034 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10035 Uri data = intent.getData();
10036 if (data != null) {
10037 String pkgName = data.getSchemeSpecificPart();
10038 if (pkgName != null) {
10039 skipPackages = new String[] { pkgName };
10040 }
10041 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010042 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010043 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010044 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010045 if (skipPackages != null && (skipPackages.length > 0)) {
10046 for (String skipPackage : skipPackages) {
10047 if (skipPackage != null) {
10048 int NT = receivers.size();
10049 for (int it=0; it<NT; it++) {
10050 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10051 if (curt.activityInfo.packageName.equals(skipPackage)) {
10052 receivers.remove(it);
10053 it--;
10054 NT--;
10055 }
10056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010057 }
10058 }
10059 }
10060
10061 int NT = receivers != null ? receivers.size() : 0;
10062 int it = 0;
10063 ResolveInfo curt = null;
10064 BroadcastFilter curr = null;
10065 while (it < NT && ir < NR) {
10066 if (curt == null) {
10067 curt = (ResolveInfo)receivers.get(it);
10068 }
10069 if (curr == null) {
10070 curr = registeredReceivers.get(ir);
10071 }
10072 if (curr.getPriority() >= curt.priority) {
10073 // Insert this broadcast record into the final list.
10074 receivers.add(it, curr);
10075 ir++;
10076 curr = null;
10077 it++;
10078 NT++;
10079 } else {
10080 // Skip to the next ResolveInfo in the final list.
10081 it++;
10082 curt = null;
10083 }
10084 }
10085 }
10086 while (ir < NR) {
10087 if (receivers == null) {
10088 receivers = new ArrayList();
10089 }
10090 receivers.add(registeredReceivers.get(ir));
10091 ir++;
10092 }
10093
10094 if ((receivers != null && receivers.size() > 0)
10095 || resultTo != null) {
10096 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10097 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010098 receivers, resultTo, resultCode, resultData, map, ordered,
10099 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010100 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010101 TAG, "Enqueueing ordered broadcast " + r
10102 + ": prev had " + mOrderedBroadcasts.size());
10103 if (DEBUG_BROADCAST) {
10104 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010105 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010106 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010107 boolean replaced = false;
10108 if (replacePending) {
10109 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10110 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010111 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010112 "***** DROPPING ORDERED: " + intent);
10113 mOrderedBroadcasts.set(i, r);
10114 replaced = true;
10115 break;
10116 }
10117 }
10118 }
10119 if (!replaced) {
10120 mOrderedBroadcasts.add(r);
10121 scheduleBroadcastsLocked();
10122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010123 }
10124
10125 return BROADCAST_SUCCESS;
10126 }
10127
10128 public final int broadcastIntent(IApplicationThread caller,
10129 Intent intent, String resolvedType, IIntentReceiver resultTo,
10130 int resultCode, String resultData, Bundle map,
10131 String requiredPermission, boolean serialized, boolean sticky) {
10132 // Refuse possible leaked file descriptors
10133 if (intent != null && intent.hasFileDescriptors() == true) {
10134 throw new IllegalArgumentException("File descriptors passed in Intent");
10135 }
10136
10137 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010138 int flags = intent.getFlags();
10139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 if (!mSystemReady) {
10141 // if the caller really truly claims to know what they're doing, go
10142 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010143 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10144 intent = new Intent(intent);
10145 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10146 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080010147 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 + " before boot completion");
10149 throw new IllegalStateException("Cannot broadcast before boot completed");
10150 }
10151 }
10152
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010153 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10154 throw new IllegalArgumentException(
10155 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10156 }
10157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010158 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10159 final int callingPid = Binder.getCallingPid();
10160 final int callingUid = Binder.getCallingUid();
10161 final long origId = Binder.clearCallingIdentity();
10162 int res = broadcastIntentLocked(callerApp,
10163 callerApp != null ? callerApp.info.packageName : null,
10164 intent, resolvedType, resultTo,
10165 resultCode, resultData, map, requiredPermission, serialized,
10166 sticky, callingPid, callingUid);
10167 Binder.restoreCallingIdentity(origId);
10168 return res;
10169 }
10170 }
10171
10172 int broadcastIntentInPackage(String packageName, int uid,
10173 Intent intent, String resolvedType, IIntentReceiver resultTo,
10174 int resultCode, String resultData, Bundle map,
10175 String requiredPermission, boolean serialized, boolean sticky) {
10176 synchronized(this) {
10177 final long origId = Binder.clearCallingIdentity();
10178 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10179 resultTo, resultCode, resultData, map, requiredPermission,
10180 serialized, sticky, -1, uid);
10181 Binder.restoreCallingIdentity(origId);
10182 return res;
10183 }
10184 }
10185
10186 public final void unbroadcastIntent(IApplicationThread caller,
10187 Intent intent) {
10188 // Refuse possible leaked file descriptors
10189 if (intent != null && intent.hasFileDescriptors() == true) {
10190 throw new IllegalArgumentException("File descriptors passed in Intent");
10191 }
10192
10193 synchronized(this) {
10194 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10195 != PackageManager.PERMISSION_GRANTED) {
10196 String msg = "Permission Denial: unbroadcastIntent() from pid="
10197 + Binder.getCallingPid()
10198 + ", uid=" + Binder.getCallingUid()
10199 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010200 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010201 throw new SecurityException(msg);
10202 }
10203 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10204 if (list != null) {
10205 int N = list.size();
10206 int i;
10207 for (i=0; i<N; i++) {
10208 if (intent.filterEquals(list.get(i))) {
10209 list.remove(i);
10210 break;
10211 }
10212 }
10213 }
10214 }
10215 }
10216
10217 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10218 String resultData, Bundle resultExtras, boolean resultAbort,
10219 boolean explicit) {
10220 if (mOrderedBroadcasts.size() == 0) {
10221 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010222 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010223 }
10224 return false;
10225 }
10226 BroadcastRecord r = mOrderedBroadcasts.get(0);
10227 if (r.receiver == null) {
10228 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010229 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 }
10231 return false;
10232 }
10233 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010234 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010235 return false;
10236 }
10237 int state = r.state;
10238 r.state = r.IDLE;
10239 if (state == r.IDLE) {
10240 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010241 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 }
10243 }
10244 r.receiver = null;
10245 r.intent.setComponent(null);
10246 if (r.curApp != null) {
10247 r.curApp.curReceiver = null;
10248 }
10249 if (r.curFilter != null) {
10250 r.curFilter.receiverList.curBroadcast = null;
10251 }
10252 r.curFilter = null;
10253 r.curApp = null;
10254 r.curComponent = null;
10255 r.curReceiver = null;
10256 mPendingBroadcast = null;
10257
10258 r.resultCode = resultCode;
10259 r.resultData = resultData;
10260 r.resultExtras = resultExtras;
10261 r.resultAbort = resultAbort;
10262
10263 // We will process the next receiver right now if this is finishing
10264 // an app receiver (which is always asynchronous) or after we have
10265 // come back from calling a receiver.
10266 return state == BroadcastRecord.APP_RECEIVE
10267 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10268 }
10269
10270 public void finishReceiver(IBinder who, int resultCode, String resultData,
10271 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010272 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010273
10274 // Refuse possible leaked file descriptors
10275 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10276 throw new IllegalArgumentException("File descriptors passed in Bundle");
10277 }
10278
10279 boolean doNext;
10280
10281 final long origId = Binder.clearCallingIdentity();
10282
10283 synchronized(this) {
10284 doNext = finishReceiverLocked(
10285 who, resultCode, resultData, resultExtras, resultAbort, true);
10286 }
10287
10288 if (doNext) {
10289 processNextBroadcast(false);
10290 }
10291 trimApplications();
10292
10293 Binder.restoreCallingIdentity(origId);
10294 }
10295
10296 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10297 if (r.nextReceiver > 0) {
10298 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10299 if (curReceiver instanceof BroadcastFilter) {
10300 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010301 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 System.identityHashCode(r),
10303 r.intent.getAction(),
10304 r.nextReceiver - 1,
10305 System.identityHashCode(bf));
10306 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010307 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010308 System.identityHashCode(r),
10309 r.intent.getAction(),
10310 r.nextReceiver - 1,
10311 ((ResolveInfo)curReceiver).toString());
10312 }
10313 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010314 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010316 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010317 System.identityHashCode(r),
10318 r.intent.getAction(),
10319 r.nextReceiver,
10320 "NONE");
10321 }
10322 }
10323
10324 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010325 ProcessRecord app = null;
10326 String anrMessage = null;
10327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 synchronized (this) {
10329 if (mOrderedBroadcasts.size() == 0) {
10330 return;
10331 }
10332 long now = SystemClock.uptimeMillis();
10333 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010334 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010335 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010336 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010337 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010339 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340 return;
10341 }
10342
Joe Onorato8a9b2202010-02-26 18:56:32 -080010343 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010344 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010345 r.anrCount++;
10346
10347 // Current receiver has passed its expiration date.
10348 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010349 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010350 return;
10351 }
10352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010353 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010354 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010355 logBroadcastReceiverDiscard(r);
10356 if (curReceiver instanceof BroadcastFilter) {
10357 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10358 if (bf.receiverList.pid != 0
10359 && bf.receiverList.pid != MY_PID) {
10360 synchronized (this.mPidsSelfLocked) {
10361 app = this.mPidsSelfLocked.get(
10362 bf.receiverList.pid);
10363 }
10364 }
10365 } else {
10366 app = r.curApp;
10367 }
10368
10369 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010370 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 }
10372
10373 if (mPendingBroadcast == r) {
10374 mPendingBroadcast = null;
10375 }
10376
10377 // Move on to the next receiver.
10378 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10379 r.resultExtras, r.resultAbort, true);
10380 scheduleBroadcastsLocked();
10381 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010382
10383 if (anrMessage != null) {
10384 appNotResponding(app, null, null, anrMessage);
10385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010386 }
10387
10388 private final void processCurBroadcastLocked(BroadcastRecord r,
10389 ProcessRecord app) throws RemoteException {
10390 if (app.thread == null) {
10391 throw new RemoteException();
10392 }
10393 r.receiver = app.thread.asBinder();
10394 r.curApp = app;
10395 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010396 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010397
10398 // Tell the application to launch this receiver.
10399 r.intent.setComponent(r.curComponent);
10400
10401 boolean started = false;
10402 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010403 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010404 "Delivering to component " + r.curComponent
10405 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010406 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010407 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10408 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10409 started = true;
10410 } finally {
10411 if (!started) {
10412 r.receiver = null;
10413 r.curApp = null;
10414 app.curReceiver = null;
10415 }
10416 }
10417
10418 }
10419
10420 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010421 Intent intent, int resultCode, String data, Bundle extras,
10422 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 if (app != null && app.thread != null) {
10424 // If we have an app thread, do the call through that so it is
10425 // correctly ordered with other one-way calls.
10426 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010427 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010428 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010429 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 }
10431 }
10432
10433 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10434 BroadcastFilter filter, boolean ordered) {
10435 boolean skip = false;
10436 if (filter.requiredPermission != null) {
10437 int perm = checkComponentPermission(filter.requiredPermission,
10438 r.callingPid, r.callingUid, -1);
10439 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010440 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010441 + r.intent.toString()
10442 + " from " + r.callerPackage + " (pid="
10443 + r.callingPid + ", uid=" + r.callingUid + ")"
10444 + " requires " + filter.requiredPermission
10445 + " due to registered receiver " + filter);
10446 skip = true;
10447 }
10448 }
10449 if (r.requiredPermission != null) {
10450 int perm = checkComponentPermission(r.requiredPermission,
10451 filter.receiverList.pid, filter.receiverList.uid, -1);
10452 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010453 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010454 + r.intent.toString()
10455 + " to " + filter.receiverList.app
10456 + " (pid=" + filter.receiverList.pid
10457 + ", uid=" + filter.receiverList.uid + ")"
10458 + " requires " + r.requiredPermission
10459 + " due to sender " + r.callerPackage
10460 + " (uid " + r.callingUid + ")");
10461 skip = true;
10462 }
10463 }
10464
10465 if (!skip) {
10466 // If this is not being sent as an ordered broadcast, then we
10467 // don't want to touch the fields that keep track of the current
10468 // state of ordered broadcasts.
10469 if (ordered) {
10470 r.receiver = filter.receiverList.receiver.asBinder();
10471 r.curFilter = filter;
10472 filter.receiverList.curBroadcast = r;
10473 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010474 if (filter.receiverList.app != null) {
10475 // Bump hosting application to no longer be in background
10476 // scheduling class. Note that we can't do that if there
10477 // isn't an app... but we can only be in that case for
10478 // things that directly call the IActivityManager API, which
10479 // are already core system stuff so don't matter for this.
10480 r.curApp = filter.receiverList.app;
10481 filter.receiverList.app.curReceiver = r;
10482 updateOomAdjLocked();
10483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010484 }
10485 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010486 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010487 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010488 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010489 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 }
10491 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10492 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010493 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010494 if (ordered) {
10495 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10496 }
10497 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010498 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010499 if (ordered) {
10500 r.receiver = null;
10501 r.curFilter = null;
10502 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010503 if (filter.receiverList.app != null) {
10504 filter.receiverList.app.curReceiver = null;
10505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010506 }
10507 }
10508 }
10509 }
10510
Dianne Hackborn12527f92009-11-11 17:39:50 -080010511 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10512 if (r.callingUid < 0) {
10513 // This was from a registerReceiver() call; ignore it.
10514 return;
10515 }
10516 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10517 MAX_BROADCAST_HISTORY-1);
10518 r.finishTime = SystemClock.uptimeMillis();
10519 mBroadcastHistory[0] = r;
10520 }
10521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010522 private final void processNextBroadcast(boolean fromMsg) {
10523 synchronized(this) {
10524 BroadcastRecord r;
10525
Joe Onorato8a9b2202010-02-26 18:56:32 -080010526 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010527 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010528 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010529
10530 updateCpuStats();
10531
10532 if (fromMsg) {
10533 mBroadcastsScheduled = false;
10534 }
10535
10536 // First, deliver any non-serialized broadcasts right away.
10537 while (mParallelBroadcasts.size() > 0) {
10538 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010539 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010540 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010541 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010542 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010543 for (int i=0; i<N; i++) {
10544 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010545 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010546 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010547 + target + ": " + r);
10548 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10549 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010550 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010551 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010552 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010553 }
10554
10555 // Now take care of the next serialized one...
10556
10557 // If we are waiting for a process to come up to handle the next
10558 // broadcast, then do nothing at this point. Just in case, we
10559 // check that the process we're waiting for still exists.
10560 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010561 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010562 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010563 + mPendingBroadcast.curApp);
10564 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010565
10566 boolean isDead;
10567 synchronized (mPidsSelfLocked) {
10568 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10569 }
10570 if (!isDead) {
10571 // It's still alive, so keep waiting
10572 return;
10573 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010574 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010575 + " died before responding to broadcast");
10576 mPendingBroadcast = null;
10577 }
10578 }
10579
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010580 boolean looped = false;
10581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010582 do {
10583 if (mOrderedBroadcasts.size() == 0) {
10584 // No more broadcasts pending, so all done!
10585 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010586 if (looped) {
10587 // If we had finished the last ordered broadcast, then
10588 // make sure all processes have correct oom and sched
10589 // adjustments.
10590 updateOomAdjLocked();
10591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 return;
10593 }
10594 r = mOrderedBroadcasts.get(0);
10595 boolean forceReceive = false;
10596
10597 // Ensure that even if something goes awry with the timeout
10598 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010599 // and continue to make progress.
10600 //
10601 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10602 // receivers don't get executed with with timeouts. They're intended for
10603 // one time heavy lifting after system upgrades and can take
10604 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010605 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010606 if (mSystemReady && r.dispatchTime > 0) {
10607 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010608 if ((numReceivers > 0) &&
10609 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010610 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 + " now=" + now
10612 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010613 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 + " intent=" + r.intent
10615 + " numReceivers=" + numReceivers
10616 + " nextReceiver=" + r.nextReceiver
10617 + " state=" + r.state);
10618 broadcastTimeout(); // forcibly finish this broadcast
10619 forceReceive = true;
10620 r.state = BroadcastRecord.IDLE;
10621 }
10622 }
10623
10624 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010625 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010626 "processNextBroadcast() called when not idle (state="
10627 + r.state + ")");
10628 return;
10629 }
10630
10631 if (r.receivers == null || r.nextReceiver >= numReceivers
10632 || r.resultAbort || forceReceive) {
10633 // No more receivers for this broadcast! Send the final
10634 // result if requested...
10635 if (r.resultTo != null) {
10636 try {
10637 if (DEBUG_BROADCAST) {
10638 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010639 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 + " seq=" + seq + " app=" + r.callerApp);
10641 }
10642 performReceive(r.callerApp, r.resultTo,
10643 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010644 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010645 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010646 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010647 }
10648 }
10649
Joe Onorato8a9b2202010-02-26 18:56:32 -080010650 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010651 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10652
Joe Onorato8a9b2202010-02-26 18:56:32 -080010653 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010654 + r);
10655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010656 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010657 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010658 mOrderedBroadcasts.remove(0);
10659 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010660 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010661 continue;
10662 }
10663 } while (r == null);
10664
10665 // Get the next receiver...
10666 int recIdx = r.nextReceiver++;
10667
10668 // Keep track of when this receiver started, and make sure there
10669 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010670 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010671 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010672 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673
Joe Onorato8a9b2202010-02-26 18:56:32 -080010674 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010675 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010676 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010677 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010678 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010679 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010680 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010681 }
10682
10683 Object nextReceiver = r.receivers.get(recIdx);
10684 if (nextReceiver instanceof BroadcastFilter) {
10685 // Simple case: this is a registered receiver who gets
10686 // a direct call.
10687 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010688 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010689 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010690 + filter + ": " + r);
10691 deliverToRegisteredReceiver(r, filter, r.ordered);
10692 if (r.receiver == null || !r.ordered) {
10693 // The receiver has already finished, so schedule to
10694 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010695 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10696 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010697 r.state = BroadcastRecord.IDLE;
10698 scheduleBroadcastsLocked();
10699 }
10700 return;
10701 }
10702
10703 // Hard case: need to instantiate the receiver, possibly
10704 // starting its application process to host it.
10705
10706 ResolveInfo info =
10707 (ResolveInfo)nextReceiver;
10708
10709 boolean skip = false;
10710 int perm = checkComponentPermission(info.activityInfo.permission,
10711 r.callingPid, r.callingUid,
10712 info.activityInfo.exported
10713 ? -1 : info.activityInfo.applicationInfo.uid);
10714 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010715 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 + r.intent.toString()
10717 + " from " + r.callerPackage + " (pid=" + r.callingPid
10718 + ", uid=" + r.callingUid + ")"
10719 + " requires " + info.activityInfo.permission
10720 + " due to receiver " + info.activityInfo.packageName
10721 + "/" + info.activityInfo.name);
10722 skip = true;
10723 }
10724 if (r.callingUid != Process.SYSTEM_UID &&
10725 r.requiredPermission != null) {
10726 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010727 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010728 checkPermission(r.requiredPermission,
10729 info.activityInfo.applicationInfo.packageName);
10730 } catch (RemoteException e) {
10731 perm = PackageManager.PERMISSION_DENIED;
10732 }
10733 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010734 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735 + r.intent + " to "
10736 + info.activityInfo.applicationInfo.packageName
10737 + " requires " + r.requiredPermission
10738 + " due to sender " + r.callerPackage
10739 + " (uid " + r.callingUid + ")");
10740 skip = true;
10741 }
10742 }
10743 if (r.curApp != null && r.curApp.crashing) {
10744 // If the target process is crashing, just skip it.
10745 skip = true;
10746 }
10747
10748 if (skip) {
10749 r.receiver = null;
10750 r.curFilter = null;
10751 r.state = BroadcastRecord.IDLE;
10752 scheduleBroadcastsLocked();
10753 return;
10754 }
10755
10756 r.state = BroadcastRecord.APP_RECEIVE;
10757 String targetProcess = info.activityInfo.processName;
10758 r.curComponent = new ComponentName(
10759 info.activityInfo.applicationInfo.packageName,
10760 info.activityInfo.name);
10761 r.curReceiver = info.activityInfo;
10762
10763 // Is this receiver's application already running?
10764 ProcessRecord app = getProcessRecordLocked(targetProcess,
10765 info.activityInfo.applicationInfo.uid);
10766 if (app != null && app.thread != null) {
10767 try {
10768 processCurBroadcastLocked(r, app);
10769 return;
10770 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010771 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 + r.curComponent, e);
10773 }
10774
10775 // If a dead object exception was thrown -- fall through to
10776 // restart the application.
10777 }
10778
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010779 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010780 if ((r.curApp=startProcessLocked(targetProcess,
10781 info.activityInfo.applicationInfo, true,
10782 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010783 "broadcast", r.curComponent,
10784 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10785 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786 // Ah, this recipient is unavailable. Finish it if necessary,
10787 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010788 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 + info.activityInfo.applicationInfo.packageName + "/"
10790 + info.activityInfo.applicationInfo.uid + " for broadcast "
10791 + r.intent + ": process is bad");
10792 logBroadcastReceiverDiscard(r);
10793 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10794 r.resultExtras, r.resultAbort, true);
10795 scheduleBroadcastsLocked();
10796 r.state = BroadcastRecord.IDLE;
10797 return;
10798 }
10799
10800 mPendingBroadcast = r;
10801 }
10802 }
10803
10804 // =========================================================
10805 // INSTRUMENTATION
10806 // =========================================================
10807
10808 public boolean startInstrumentation(ComponentName className,
10809 String profileFile, int flags, Bundle arguments,
10810 IInstrumentationWatcher watcher) {
10811 // Refuse possible leaked file descriptors
10812 if (arguments != null && arguments.hasFileDescriptors()) {
10813 throw new IllegalArgumentException("File descriptors passed in Bundle");
10814 }
10815
10816 synchronized(this) {
10817 InstrumentationInfo ii = null;
10818 ApplicationInfo ai = null;
10819 try {
10820 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010821 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010823 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010824 } catch (PackageManager.NameNotFoundException e) {
10825 }
10826 if (ii == null) {
10827 reportStartInstrumentationFailure(watcher, className,
10828 "Unable to find instrumentation info for: " + className);
10829 return false;
10830 }
10831 if (ai == null) {
10832 reportStartInstrumentationFailure(watcher, className,
10833 "Unable to find instrumentation target package: " + ii.targetPackage);
10834 return false;
10835 }
10836
10837 int match = mContext.getPackageManager().checkSignatures(
10838 ii.targetPackage, ii.packageName);
10839 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10840 String msg = "Permission Denial: starting instrumentation "
10841 + className + " from pid="
10842 + Binder.getCallingPid()
10843 + ", uid=" + Binder.getCallingPid()
10844 + " not allowed because package " + ii.packageName
10845 + " does not have a signature matching the target "
10846 + ii.targetPackage;
10847 reportStartInstrumentationFailure(watcher, className, msg);
10848 throw new SecurityException(msg);
10849 }
10850
10851 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010852 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010853 ProcessRecord app = addAppLocked(ai);
10854 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010855 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010856 app.instrumentationProfileFile = profileFile;
10857 app.instrumentationArguments = arguments;
10858 app.instrumentationWatcher = watcher;
10859 app.instrumentationResultClass = className;
10860 Binder.restoreCallingIdentity(origId);
10861 }
10862
10863 return true;
10864 }
10865
10866 /**
10867 * Report errors that occur while attempting to start Instrumentation. Always writes the
10868 * error to the logs, but if somebody is watching, send the report there too. This enables
10869 * the "am" command to report errors with more information.
10870 *
10871 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10872 * @param cn The component name of the instrumentation.
10873 * @param report The error report.
10874 */
10875 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10876 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010877 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010878 try {
10879 if (watcher != null) {
10880 Bundle results = new Bundle();
10881 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10882 results.putString("Error", report);
10883 watcher.instrumentationStatus(cn, -1, results);
10884 }
10885 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010886 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010887 }
10888 }
10889
10890 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10891 if (app.instrumentationWatcher != null) {
10892 try {
10893 // NOTE: IInstrumentationWatcher *must* be oneway here
10894 app.instrumentationWatcher.instrumentationFinished(
10895 app.instrumentationClass,
10896 resultCode,
10897 results);
10898 } catch (RemoteException e) {
10899 }
10900 }
10901 app.instrumentationWatcher = null;
10902 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010903 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010904 app.instrumentationProfileFile = null;
10905 app.instrumentationArguments = null;
10906
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010907 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 }
10909
10910 public void finishInstrumentation(IApplicationThread target,
10911 int resultCode, Bundle results) {
10912 // Refuse possible leaked file descriptors
10913 if (results != null && results.hasFileDescriptors()) {
10914 throw new IllegalArgumentException("File descriptors passed in Intent");
10915 }
10916
10917 synchronized(this) {
10918 ProcessRecord app = getRecordForAppLocked(target);
10919 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010920 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 return;
10922 }
10923 final long origId = Binder.clearCallingIdentity();
10924 finishInstrumentationLocked(app, resultCode, results);
10925 Binder.restoreCallingIdentity(origId);
10926 }
10927 }
10928
10929 // =========================================================
10930 // CONFIGURATION
10931 // =========================================================
10932
10933 public ConfigurationInfo getDeviceConfigurationInfo() {
10934 ConfigurationInfo config = new ConfigurationInfo();
10935 synchronized (this) {
10936 config.reqTouchScreen = mConfiguration.touchscreen;
10937 config.reqKeyboardType = mConfiguration.keyboard;
10938 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010939 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10940 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10942 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010943 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10944 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010945 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10946 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010947 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 }
10949 return config;
10950 }
10951
10952 public Configuration getConfiguration() {
10953 Configuration ci;
10954 synchronized(this) {
10955 ci = new Configuration(mConfiguration);
10956 }
10957 return ci;
10958 }
10959
10960 public void updateConfiguration(Configuration values) {
10961 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10962 "updateConfiguration()");
10963
10964 synchronized(this) {
10965 if (values == null && mWindowManager != null) {
10966 // sentinel: fetch the current configuration from the window manager
10967 values = mWindowManager.computeNewConfiguration();
10968 }
10969
10970 final long origId = Binder.clearCallingIdentity();
10971 updateConfigurationLocked(values, null);
10972 Binder.restoreCallingIdentity(origId);
10973 }
10974 }
10975
10976 /**
10977 * Do either or both things: (1) change the current configuration, and (2)
10978 * make sure the given activity is running with the (now) current
10979 * configuration. Returns true if the activity has been left running, or
10980 * false if <var>starting</var> is being destroyed to match the new
10981 * configuration.
10982 */
10983 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010984 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 int changes = 0;
10986
10987 boolean kept = true;
10988
10989 if (values != null) {
10990 Configuration newConfig = new Configuration(mConfiguration);
10991 changes = newConfig.updateFrom(values);
10992 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010993 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010994 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010995 }
10996
Doug Zongker2bec3d42009-12-04 12:52:44 -080010997 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998
10999 if (values.locale != null) {
11000 saveLocaleLocked(values.locale,
11001 !values.locale.equals(mConfiguration.locale),
11002 values.userSetLocale);
11003 }
11004
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011005 mConfigurationSeq++;
11006 if (mConfigurationSeq <= 0) {
11007 mConfigurationSeq = 1;
11008 }
11009 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011010 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011011 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011012
11013 AttributeCache ac = AttributeCache.instance();
11014 if (ac != null) {
11015 ac.updateConfiguration(mConfiguration);
11016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011018 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11019 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11020 msg.obj = new Configuration(mConfiguration);
11021 mHandler.sendMessage(msg);
11022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011024 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11025 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 try {
11027 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011028 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011029 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030 app.thread.scheduleConfigurationChanged(mConfiguration);
11031 }
11032 } catch (Exception e) {
11033 }
11034 }
11035 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011036 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11037 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011038 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11039 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011040 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11041 broadcastIntentLocked(null, null,
11042 new Intent(Intent.ACTION_LOCALE_CHANGED),
11043 null, null, 0, null, null,
11044 null, false, false, MY_PID, Process.SYSTEM_UID);
11045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 }
11047 }
11048
11049 if (changes != 0 && starting == null) {
11050 // If the configuration changed, and the caller is not already
11051 // in the process of starting an activity, then find the top
11052 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011053 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 }
11055
11056 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011057 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058 if (kept) {
11059 // If this didn't result in the starting activity being
11060 // destroyed, then we need to make sure at this point that all
11061 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011062 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011064 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 }
11066 }
11067
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011068 if (values != null && mWindowManager != null) {
11069 mWindowManager.setNewConfiguration(mConfiguration);
11070 }
11071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072 return kept;
11073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011074
11075 /**
11076 * Save the locale. You must be inside a synchronized (this) block.
11077 */
11078 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11079 if(isDiff) {
11080 SystemProperties.set("user.language", l.getLanguage());
11081 SystemProperties.set("user.region", l.getCountry());
11082 }
11083
11084 if(isPersist) {
11085 SystemProperties.set("persist.sys.language", l.getLanguage());
11086 SystemProperties.set("persist.sys.country", l.getCountry());
11087 SystemProperties.set("persist.sys.localevar", l.getVariant());
11088 }
11089 }
11090
11091 // =========================================================
11092 // LIFETIME MANAGEMENT
11093 // =========================================================
11094
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011095 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11096 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011097 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011098 // This adjustment has already been computed. If we are calling
11099 // from the top, we may have already computed our adjustment with
11100 // an earlier hidden adjustment that isn't really for us... if
11101 // so, use the new hidden adjustment.
11102 if (!recursed && app.hidden) {
11103 app.curAdj = hiddenAdj;
11104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011105 return app.curAdj;
11106 }
11107
11108 if (app.thread == null) {
11109 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011110 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011111 return (app.curAdj=EMPTY_APP_ADJ);
11112 }
11113
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011114 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11115 // The max adjustment doesn't allow this app to be anything
11116 // below foreground, so it is not worth doing work for it.
11117 app.adjType = "fixed";
11118 app.adjSeq = mAdjSeq;
11119 app.curRawAdj = app.maxAdj;
11120 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11121 return (app.curAdj=app.maxAdj);
11122 }
11123
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011124 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011125 app.adjSource = null;
11126 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011127 app.empty = false;
11128 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129
The Android Open Source Project4df24232009-03-05 14:34:35 -080011130 // Determine the importance of the process, starting with most
11131 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011132 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011133 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011135 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011136 // The last app on the list is the foreground app.
11137 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011138 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011139 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011140 } else if (app.instrumentationClass != null) {
11141 // Don't want to kill running instrumentation.
11142 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011143 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011144 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011145 } else if (app.persistentActivities > 0) {
11146 // Special persistent activities... shouldn't be used these days.
11147 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011148 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011149 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 } else if (app.curReceiver != null ||
11151 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11152 // An app that is currently receiving a broadcast also
11153 // counts as being in the foreground.
11154 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011155 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011156 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011157 } else if (app.executingServices.size() > 0) {
11158 // An app that is currently executing a service callback also
11159 // counts as being in the foreground.
11160 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011161 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011162 app.adjType = "exec-service";
11163 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011165 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011166 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011167 app.adjType = "foreground-service";
11168 } else if (app.forcingToForeground != null) {
11169 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011170 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011171 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011172 app.adjType = "force-foreground";
11173 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011174 } else if (app == mHeavyWeightProcess) {
11175 // We don't want to kill the current heavy-weight process.
11176 adj = HEAVY_WEIGHT_APP_ADJ;
11177 schedGroup = Process.THREAD_GROUP_DEFAULT;
11178 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011179 } else if (app == mHomeProcess) {
11180 // This process is hosting what we currently consider to be the
11181 // home app, so we don't want to let it go into the background.
11182 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011183 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011184 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011185 } else if ((N=app.activities.size()) != 0) {
11186 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011187 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011189 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011190 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011191 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011193 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011195 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011196 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011197 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011198 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 break;
11200 }
11201 }
11202 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011203 // A very not-needed process. If this is lower in the lru list,
11204 // we will push it in to the empty bucket.
11205 app.hidden = true;
11206 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011207 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011208 adj = hiddenAdj;
11209 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 }
11211
Joe Onorato8a9b2202010-02-26 18:56:32 -080011212 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011213
The Android Open Source Project4df24232009-03-05 14:34:35 -080011214 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011215 // there are applications dependent on our services or providers, but
11216 // this gives us a baseline and makes sure we don't get into an
11217 // infinite recursion.
11218 app.adjSeq = mAdjSeq;
11219 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220
Christopher Tate6fa95972009-06-05 18:43:55 -070011221 if (mBackupTarget != null && app == mBackupTarget.app) {
11222 // If possible we want to avoid killing apps while they're being backed up
11223 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011224 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011225 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011226 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011227 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011228 }
11229 }
11230
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011231 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11232 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 final long now = SystemClock.uptimeMillis();
11234 // This process is more important if the top activity is
11235 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011236 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011238 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011239 if (s.startRequested) {
11240 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11241 // This service has seen some activity within
11242 // recent memory, so we will keep its process ahead
11243 // of the background processes.
11244 if (adj > SECONDARY_SERVER_ADJ) {
11245 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011246 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011247 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011248 }
11249 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011250 // If we have let the service slide into the background
11251 // state, still have some text describing what it is doing
11252 // even though the service no longer has an impact.
11253 if (adj > SECONDARY_SERVER_ADJ) {
11254 app.adjType = "started-bg-services";
11255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011256 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011257 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11258 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011259 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 = s.connections.values().iterator();
11261 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011262 ArrayList<ConnectionRecord> clist = kt.next();
11263 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11264 // XXX should compute this based on the max of
11265 // all connected clients.
11266 ConnectionRecord cr = clist.get(i);
11267 if (cr.binding.client == app) {
11268 // Binding to ourself is not interesting.
11269 continue;
11270 }
11271 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11272 ProcessRecord client = cr.binding.client;
11273 int myHiddenAdj = hiddenAdj;
11274 if (myHiddenAdj > client.hiddenAdj) {
11275 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11276 myHiddenAdj = client.hiddenAdj;
11277 } else {
11278 myHiddenAdj = VISIBLE_APP_ADJ;
11279 }
11280 }
11281 int clientAdj = computeOomAdjLocked(
11282 client, myHiddenAdj, TOP_APP, true);
11283 if (adj > clientAdj) {
11284 adj = clientAdj >= VISIBLE_APP_ADJ
11285 ? clientAdj : VISIBLE_APP_ADJ;
11286 if (!client.hidden) {
11287 app.hidden = false;
11288 }
11289 app.adjType = "service";
11290 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11291 .REASON_SERVICE_IN_USE;
11292 app.adjSource = cr.binding.client;
11293 app.adjTarget = s.name;
11294 }
11295 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11296 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11297 schedGroup = Process.THREAD_GROUP_DEFAULT;
11298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011299 }
11300 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011301 ActivityRecord a = cr.activity;
11302 //if (a != null) {
11303 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11304 //}
11305 if (a != null && adj > FOREGROUND_APP_ADJ &&
11306 (a.state == ActivityState.RESUMED
11307 || a.state == ActivityState.PAUSING)) {
11308 adj = FOREGROUND_APP_ADJ;
11309 schedGroup = Process.THREAD_GROUP_DEFAULT;
11310 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011311 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011312 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11313 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011314 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011315 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011317 }
11318 }
11319 }
11320 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011321
11322 // Finally, f this process has active services running in it, we
11323 // would like to avoid killing it unless it would prevent the current
11324 // application from running. By default we put the process in
11325 // with the rest of the background processes; as we scan through
11326 // its services we may bump it up from there.
11327 if (adj > hiddenAdj) {
11328 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011329 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011330 app.adjType = "bg-services";
11331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011332 }
11333
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011334 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11335 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011336 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011337 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11338 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011339 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011340 if (cpr.clients.size() != 0) {
11341 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11342 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11343 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011344 if (client == app) {
11345 // Being our own client is not interesting.
11346 continue;
11347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011348 int myHiddenAdj = hiddenAdj;
11349 if (myHiddenAdj > client.hiddenAdj) {
11350 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11351 myHiddenAdj = client.hiddenAdj;
11352 } else {
11353 myHiddenAdj = FOREGROUND_APP_ADJ;
11354 }
11355 }
11356 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011357 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011358 if (adj > clientAdj) {
11359 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011360 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011361 if (!client.hidden) {
11362 app.hidden = false;
11363 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011364 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011365 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11366 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011367 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011368 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011370 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11371 schedGroup = Process.THREAD_GROUP_DEFAULT;
11372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011373 }
11374 }
11375 // If the provider has external (non-framework) process
11376 // dependencies, ensure that its adjustment is at least
11377 // FOREGROUND_APP_ADJ.
11378 if (cpr.externals != 0) {
11379 if (adj > FOREGROUND_APP_ADJ) {
11380 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011381 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011382 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011383 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011384 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011385 }
11386 }
11387 }
11388 }
11389
11390 app.curRawAdj = adj;
11391
Joe Onorato8a9b2202010-02-26 18:56:32 -080011392 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11394 if (adj > app.maxAdj) {
11395 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011396 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011397 schedGroup = Process.THREAD_GROUP_DEFAULT;
11398 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 }
11400
11401 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011402 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404 return adj;
11405 }
11406
11407 /**
11408 * Ask a given process to GC right now.
11409 */
11410 final void performAppGcLocked(ProcessRecord app) {
11411 try {
11412 app.lastRequestedGc = SystemClock.uptimeMillis();
11413 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011414 if (app.reportLowMemory) {
11415 app.reportLowMemory = false;
11416 app.thread.scheduleLowMemory();
11417 } else {
11418 app.thread.processInBackground();
11419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420 }
11421 } catch (Exception e) {
11422 // whatever.
11423 }
11424 }
11425
11426 /**
11427 * Returns true if things are idle enough to perform GCs.
11428 */
Josh Bartel7f208742010-02-25 11:01:44 -060011429 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011430 return mParallelBroadcasts.size() == 0
11431 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011432 && (mSleeping || (mMainStack.mResumedActivity != null &&
11433 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 }
11435
11436 /**
11437 * Perform GCs on all processes that are waiting for it, but only
11438 * if things are idle.
11439 */
11440 final void performAppGcsLocked() {
11441 final int N = mProcessesToGc.size();
11442 if (N <= 0) {
11443 return;
11444 }
Josh Bartel7f208742010-02-25 11:01:44 -060011445 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 while (mProcessesToGc.size() > 0) {
11447 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011448 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011449 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11450 <= SystemClock.uptimeMillis()) {
11451 // To avoid spamming the system, we will GC processes one
11452 // at a time, waiting a few seconds between each.
11453 performAppGcLocked(proc);
11454 scheduleAppGcsLocked();
11455 return;
11456 } else {
11457 // It hasn't been long enough since we last GCed this
11458 // process... put it in the list to wait for its time.
11459 addProcessToGcListLocked(proc);
11460 break;
11461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011462 }
11463 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011464
11465 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011466 }
11467 }
11468
11469 /**
11470 * If all looks good, perform GCs on all processes waiting for them.
11471 */
11472 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011473 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 performAppGcsLocked();
11475 return;
11476 }
11477 // Still not idle, wait some more.
11478 scheduleAppGcsLocked();
11479 }
11480
11481 /**
11482 * Schedule the execution of all pending app GCs.
11483 */
11484 final void scheduleAppGcsLocked() {
11485 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011486
11487 if (mProcessesToGc.size() > 0) {
11488 // Schedule a GC for the time to the next process.
11489 ProcessRecord proc = mProcessesToGc.get(0);
11490 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11491
11492 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11493 long now = SystemClock.uptimeMillis();
11494 if (when < (now+GC_TIMEOUT)) {
11495 when = now + GC_TIMEOUT;
11496 }
11497 mHandler.sendMessageAtTime(msg, when);
11498 }
11499 }
11500
11501 /**
11502 * Add a process to the array of processes waiting to be GCed. Keeps the
11503 * list in sorted order by the last GC time. The process can't already be
11504 * on the list.
11505 */
11506 final void addProcessToGcListLocked(ProcessRecord proc) {
11507 boolean added = false;
11508 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11509 if (mProcessesToGc.get(i).lastRequestedGc <
11510 proc.lastRequestedGc) {
11511 added = true;
11512 mProcessesToGc.add(i+1, proc);
11513 break;
11514 }
11515 }
11516 if (!added) {
11517 mProcessesToGc.add(0, proc);
11518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011519 }
11520
11521 /**
11522 * Set up to ask a process to GC itself. This will either do it
11523 * immediately, or put it on the list of processes to gc the next
11524 * time things are idle.
11525 */
11526 final void scheduleAppGcLocked(ProcessRecord app) {
11527 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011528 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011529 return;
11530 }
11531 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011532 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011533 scheduleAppGcsLocked();
11534 }
11535 }
11536
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011537 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11538 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11539 if (mLastWakeLockCheckTime == 0) {
11540 doKills = false;
11541 }
11542 if (stats.isScreenOn()) {
11543 doKills = false;
11544 }
11545 final long curRealtime = SystemClock.elapsedRealtime();
11546 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11547 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011548 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011549 doKills = false;
11550 }
11551 int i = mLruProcesses.size();
11552 while (i > 0) {
11553 i--;
11554 ProcessRecord app = mLruProcesses.get(i);
11555 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11556 long wtime;
11557 synchronized (stats) {
11558 wtime = stats.getProcessWakeTime(app.info.uid,
11559 app.pid, curRealtime);
11560 }
11561 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011562 if (false) {
11563 StringBuilder sb = new StringBuilder(128);
11564 sb.append("Wake for ");
11565 app.toShortString(sb);
11566 sb.append(": over ");
11567 TimeUtils.formatDuration(timeSince, sb);
11568 sb.append(" used ");
11569 TimeUtils.formatDuration(timeUsed, sb);
11570 sb.append(" (");
11571 sb.append((timeUsed*100)/timeSince);
11572 sb.append("%)");
11573 Slog.i(TAG, sb.toString());
11574 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011575 // If a process has held a wake lock for more
11576 // than 50% of the time during this period,
11577 // that sounds pad. Kill!
11578 if (doKills && timeSince > 0
11579 && ((timeUsed*100)/timeSince) >= 50) {
11580 Slog.i(TAG, "Excessive wake lock in " + app.processName
11581 + " (pid " + app.pid + "): held " + timeUsed
11582 + " during " + timeSince);
11583 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11584 app.processName, app.setAdj, "excessive wake lock");
11585 Process.killProcessQuiet(app.pid);
11586 } else {
11587 app.lastWakeTime = wtime;
11588 }
11589 }
11590 }
11591 }
11592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011593 private final boolean updateOomAdjLocked(
11594 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11595 app.hiddenAdj = hiddenAdj;
11596
11597 if (app.thread == null) {
11598 return true;
11599 }
11600
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011601 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011603 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 if (app.curRawAdj != app.setRawAdj) {
11605 if (app.curRawAdj > FOREGROUND_APP_ADJ
11606 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11607 // If this app is transitioning from foreground to
11608 // non-foreground, have it do a gc.
11609 scheduleAppGcLocked(app);
11610 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11611 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11612 // Likewise do a gc when an app is moving in to the
11613 // background (such as a service stopping).
11614 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011615 // And note its current wake lock time.
11616 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11617 synchronized (stats) {
11618 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11619 app.pid, SystemClock.elapsedRealtime());
11620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 }
11622 app.setRawAdj = app.curRawAdj;
11623 }
11624 if (adj != app.setAdj) {
11625 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011626 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011627 TAG, "Set app " + app.processName +
11628 " oom adj to " + adj);
11629 app.setAdj = adj;
11630 } else {
11631 return false;
11632 }
11633 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011634 if (app.setSchedGroup != app.curSchedGroup) {
11635 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011636 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011637 "Setting process group of " + app.processName
11638 + " to " + app.curSchedGroup);
11639 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011640 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011641 try {
11642 Process.setProcessGroup(app.pid, app.curSchedGroup);
11643 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011644 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011645 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011646 e.printStackTrace();
11647 } finally {
11648 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011649 }
11650 }
11651 if (false) {
11652 if (app.thread != null) {
11653 try {
11654 app.thread.setSchedulingGroup(app.curSchedGroup);
11655 } catch (RemoteException e) {
11656 }
11657 }
11658 }
11659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011660 }
11661
11662 return true;
11663 }
11664
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011665 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011666 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011667 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011668 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011669 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011670 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011671 }
11672 }
11673 return resumedActivity;
11674 }
11675
11676 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011677 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011678 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11679 int curAdj = app.curAdj;
11680 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11681 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11682
11683 mAdjSeq++;
11684
11685 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11686 if (res) {
11687 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11688 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11689 if (nowHidden != wasHidden) {
11690 // Changed to/from hidden state, so apps after it in the LRU
11691 // list may also be changed.
11692 updateOomAdjLocked();
11693 }
11694 }
11695 return res;
11696 }
11697
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011698 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011699 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011700 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011701 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11702
11703 if (false) {
11704 RuntimeException e = new RuntimeException();
11705 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011706 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 }
11708
11709 mAdjSeq++;
11710
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011711 // Let's determine how many processes we have running vs.
11712 // how many slots we have for background processes; we may want
11713 // to put multiple processes in a slot of there are enough of
11714 // them.
11715 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11716 int factor = (mLruProcesses.size()-4)/numSlots;
11717 if (factor < 1) factor = 1;
11718 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011719 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011721 // First try updating the OOM adjustment for each of the
11722 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011723 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011724 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11725 while (i > 0) {
11726 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011727 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011728 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011729 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011730 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011732 step++;
11733 if (step >= factor) {
11734 step = 0;
11735 curHiddenAdj++;
11736 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011738 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011739 if (!app.killedBackground) {
11740 numHidden++;
11741 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011742 Slog.i(TAG, "No longer want " + app.processName
11743 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011744 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11745 app.processName, app.setAdj, "too many background");
11746 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011747 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011748 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011749 }
11750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011751 } else {
11752 didOomAdj = false;
11753 }
11754 }
11755
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011756 // If we return false, we will fall back on killing processes to
11757 // have a fixed limit. Do this if a limit has been requested; else
11758 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011759 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11760 }
11761
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011762 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011763 synchronized (this) {
11764 int i;
11765
11766 // First remove any unused application processes whose package
11767 // has been removed.
11768 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11769 final ProcessRecord app = mRemovedProcesses.get(i);
11770 if (app.activities.size() == 0
11771 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011772 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011773 TAG, "Exiting empty application process "
11774 + app.processName + " ("
11775 + (app.thread != null ? app.thread.asBinder() : null)
11776 + ")\n");
11777 if (app.pid > 0 && app.pid != MY_PID) {
11778 Process.killProcess(app.pid);
11779 } else {
11780 try {
11781 app.thread.scheduleExit();
11782 } catch (Exception e) {
11783 // Ignore exceptions.
11784 }
11785 }
11786 cleanUpApplicationRecordLocked(app, false, -1);
11787 mRemovedProcesses.remove(i);
11788
11789 if (app.persistent) {
11790 if (app.persistent) {
11791 addAppLocked(app.info);
11792 }
11793 }
11794 }
11795 }
11796
11797 // Now try updating the OOM adjustment for each of the
11798 // application processes based on their current state.
11799 // If the setOomAdj() API is not supported, then go with our
11800 // back-up plan...
11801 if (!updateOomAdjLocked()) {
11802
11803 // Count how many processes are running services.
11804 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011805 for (i=mLruProcesses.size()-1; i>=0; i--) {
11806 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807
11808 if (app.persistent || app.services.size() != 0
11809 || app.curReceiver != null
11810 || app.persistentActivities > 0) {
11811 // Don't count processes holding services against our
11812 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011813 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011814 TAG, "Not trimming app " + app + " with services: "
11815 + app.services);
11816 numServiceProcs++;
11817 }
11818 }
11819
11820 int curMaxProcs = mProcessLimit;
11821 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11822 if (mAlwaysFinishActivities) {
11823 curMaxProcs = 1;
11824 }
11825 curMaxProcs += numServiceProcs;
11826
11827 // Quit as many processes as we can to get down to the desired
11828 // process count. First remove any processes that no longer
11829 // have activites running in them.
11830 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011831 i<mLruProcesses.size()
11832 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011833 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011834 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011835 // Quit an application only if it is not currently
11836 // running any activities.
11837 if (!app.persistent && app.activities.size() == 0
11838 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011839 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011840 TAG, "Exiting empty application process "
11841 + app.processName + " ("
11842 + (app.thread != null ? app.thread.asBinder() : null)
11843 + ")\n");
11844 if (app.pid > 0 && app.pid != MY_PID) {
11845 Process.killProcess(app.pid);
11846 } else {
11847 try {
11848 app.thread.scheduleExit();
11849 } catch (Exception e) {
11850 // Ignore exceptions.
11851 }
11852 }
11853 // todo: For now we assume the application is not buggy
11854 // or evil, and will quit as a result of our request.
11855 // Eventually we need to drive this off of the death
11856 // notification, and kill the process if it takes too long.
11857 cleanUpApplicationRecordLocked(app, false, i);
11858 i--;
11859 }
11860 }
11861
11862 // If we still have too many processes, now from the least
11863 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011864 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011865 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011866 " of " + curMaxProcs + " processes");
11867 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011868 i<mLruProcesses.size()
11869 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011870 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011871 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011872 // Quit the application only if we have a state saved for
11873 // all of its activities.
11874 boolean canQuit = !app.persistent && app.curReceiver == null
11875 && app.services.size() == 0
11876 && app.persistentActivities == 0;
11877 int NUMA = app.activities.size();
11878 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011879 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011880 TAG, "Looking to quit " + app.processName);
11881 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011882 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011883 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011884 TAG, " " + r.intent.getComponent().flattenToShortString()
11885 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11886 canQuit = (r.haveState || !r.stateNotNeeded)
11887 && !r.visible && r.stopped;
11888 }
11889 if (canQuit) {
11890 // Finish all of the activities, and then the app itself.
11891 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011892 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011893 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011894 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011895 }
11896 r.resultTo = null;
11897 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011898 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011899 + app.processName + " ("
11900 + (app.thread != null ? app.thread.asBinder() : null)
11901 + ")\n");
11902 if (app.pid > 0 && app.pid != MY_PID) {
11903 Process.killProcess(app.pid);
11904 } else {
11905 try {
11906 app.thread.scheduleExit();
11907 } catch (Exception e) {
11908 // Ignore exceptions.
11909 }
11910 }
11911 // todo: For now we assume the application is not buggy
11912 // or evil, and will quit as a result of our request.
11913 // Eventually we need to drive this off of the death
11914 // notification, and kill the process if it takes too long.
11915 cleanUpApplicationRecordLocked(app, false, i);
11916 i--;
11917 //dump();
11918 }
11919 }
11920
11921 }
11922
11923 int curMaxActivities = MAX_ACTIVITIES;
11924 if (mAlwaysFinishActivities) {
11925 curMaxActivities = 1;
11926 }
11927
11928 // Finally, if there are too many activities now running, try to
11929 // finish as many as we can to get back down to the limit.
11930 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011931 i<mMainStack.mLRUActivities.size()
11932 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011933 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011934 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011935 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011936
11937 // We can finish this one if we have its icicle saved and
11938 // it is not persistent.
11939 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11940 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011941 final int origSize = mMainStack.mLRUActivities.size();
11942 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011943
11944 // This will remove it from the LRU list, so keep
11945 // our index at the same value. Note that this check to
11946 // see if the size changes is just paranoia -- if
11947 // something unexpected happens, we don't want to end up
11948 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011949 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011950 i--;
11951 }
11952 }
11953 }
11954 }
11955 }
11956
11957 /** This method sends the specified signal to each of the persistent apps */
11958 public void signalPersistentProcesses(int sig) throws RemoteException {
11959 if (sig != Process.SIGNAL_USR1) {
11960 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11961 }
11962
11963 synchronized (this) {
11964 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11965 != PackageManager.PERMISSION_GRANTED) {
11966 throw new SecurityException("Requires permission "
11967 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11968 }
11969
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011970 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11971 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011972 if (r.thread != null && r.persistent) {
11973 Process.sendSignal(r.pid, sig);
11974 }
11975 }
11976 }
11977 }
11978
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011979 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011980 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011981
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011982 try {
11983 synchronized (this) {
11984 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11985 // its own permission.
11986 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11987 != PackageManager.PERMISSION_GRANTED) {
11988 throw new SecurityException("Requires permission "
11989 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011990 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011991
11992 if (start && fd == null) {
11993 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011994 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011995
11996 ProcessRecord proc = null;
11997 try {
11998 int pid = Integer.parseInt(process);
11999 synchronized (mPidsSelfLocked) {
12000 proc = mPidsSelfLocked.get(pid);
12001 }
12002 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012003 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012004
12005 if (proc == null) {
12006 HashMap<String, SparseArray<ProcessRecord>> all
12007 = mProcessNames.getMap();
12008 SparseArray<ProcessRecord> procs = all.get(process);
12009 if (procs != null && procs.size() > 0) {
12010 proc = procs.valueAt(0);
12011 }
12012 }
12013
12014 if (proc == null || proc.thread == null) {
12015 throw new IllegalArgumentException("Unknown process: " + process);
12016 }
12017
12018 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12019 if (isSecure) {
12020 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12021 throw new SecurityException("Process not debuggable: " + proc);
12022 }
12023 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012024
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012025 proc.thread.profilerControl(start, path, fd);
12026 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012027 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012028 }
12029 } catch (RemoteException e) {
12030 throw new IllegalStateException("Process disappeared");
12031 } finally {
12032 if (fd != null) {
12033 try {
12034 fd.close();
12035 } catch (IOException e) {
12036 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012037 }
12038 }
12039 }
12040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012041 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12042 public void monitor() {
12043 synchronized (this) { }
12044 }
12045}