blob: 2cdf31e9579107cf571ab57182e04b994fe724e7 [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 Fitzpatrick1e02d362010-09-10 09:19:50 -07006538 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6539 // Note: ProcessRecord 'process' is guarded by the service
6540 // instance. (notably process.pkgList, which could otherwise change
6541 // concurrently during execution of this method)
6542 synchronized (this) {
6543 if (process == null || process.pid == MY_PID) {
6544 sb.append("Process: system_server\n");
6545 } else {
6546 sb.append("Process: ").append(process.processName).append("\n");
6547 }
6548 if (process == null) {
6549 return;
6550 }
Dan Egnora455d192010-03-12 08:52:28 -08006551 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006552 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006553 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6554 for (String pkg : process.pkgList) {
6555 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006556 try {
Dan Egnora455d192010-03-12 08:52:28 -08006557 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6558 if (pi != null) {
6559 sb.append(" v").append(pi.versionCode);
6560 if (pi.versionName != null) {
6561 sb.append(" (").append(pi.versionName).append(")");
6562 }
6563 }
6564 } catch (RemoteException e) {
6565 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006566 }
Dan Egnora455d192010-03-12 08:52:28 -08006567 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006568 }
Dan Egnora455d192010-03-12 08:52:28 -08006569 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006570 }
6571
6572 private static String processClass(ProcessRecord process) {
6573 if (process == null || process.pid == MY_PID) {
6574 return "system_server";
6575 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6576 return "system_app";
6577 } else {
6578 return "data_app";
6579 }
6580 }
6581
6582 /**
6583 * Write a description of an error (crash, WTF, ANR) to the drop box.
6584 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6585 * @param process which caused the error, null means the system server
6586 * @param activity which triggered the error, null if unknown
6587 * @param parent activity related to the error, null if unknown
6588 * @param subject line related to the error, null if absent
6589 * @param report in long form describing the error, null if absent
6590 * @param logFile to include in the report, null if none
6591 * @param crashInfo giving an application stack trace, null if absent
6592 */
6593 public void addErrorToDropBox(String eventType,
6594 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6595 final String report, final File logFile,
6596 final ApplicationErrorReport.CrashInfo crashInfo) {
6597 // NOTE -- this must never acquire the ActivityManagerService lock,
6598 // otherwise the watchdog may be prevented from resetting the system.
6599
6600 final String dropboxTag = processClass(process) + "_" + eventType;
6601 final DropBoxManager dbox = (DropBoxManager)
6602 mContext.getSystemService(Context.DROPBOX_SERVICE);
6603
6604 // Exit early if the dropbox isn't configured to accept this report type.
6605 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6606
6607 final StringBuilder sb = new StringBuilder(1024);
6608 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006609 if (activity != null) {
6610 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6611 }
6612 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6613 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6614 }
6615 if (parent != null && parent != activity) {
6616 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6617 }
6618 if (subject != null) {
6619 sb.append("Subject: ").append(subject).append("\n");
6620 }
6621 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6622 sb.append("\n");
6623
6624 // Do the rest in a worker thread to avoid blocking the caller on I/O
6625 // (After this point, we shouldn't access AMS internal data structures.)
6626 Thread worker = new Thread("Error dump: " + dropboxTag) {
6627 @Override
6628 public void run() {
6629 if (report != null) {
6630 sb.append(report);
6631 }
6632 if (logFile != null) {
6633 try {
6634 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6635 } catch (IOException e) {
6636 Slog.e(TAG, "Error reading " + logFile, e);
6637 }
6638 }
6639 if (crashInfo != null && crashInfo.stackTrace != null) {
6640 sb.append(crashInfo.stackTrace);
6641 }
6642
6643 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6644 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6645 if (lines > 0) {
6646 sb.append("\n");
6647
6648 // Merge several logcat streams, and take the last N lines
6649 InputStreamReader input = null;
6650 try {
6651 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6652 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6653 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6654
6655 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6656 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6657 input = new InputStreamReader(logcat.getInputStream());
6658
6659 int num;
6660 char[] buf = new char[8192];
6661 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6662 } catch (IOException e) {
6663 Slog.e(TAG, "Error running logcat", e);
6664 } finally {
6665 if (input != null) try { input.close(); } catch (IOException e) {}
6666 }
6667 }
6668
6669 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006670 }
Dan Egnora455d192010-03-12 08:52:28 -08006671 };
6672
6673 if (process == null || process.pid == MY_PID) {
6674 worker.run(); // We may be about to die -- need to run this synchronously
6675 } else {
6676 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006677 }
6678 }
6679
6680 /**
6681 * Bring up the "unexpected error" dialog box for a crashing app.
6682 * Deal with edge cases (intercepts from instrumented applications,
6683 * ActivityController, error intent receivers, that sort of thing).
6684 * @param r the application crashing
6685 * @param crashInfo describing the failure
6686 */
6687 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006688 long timeMillis = System.currentTimeMillis();
6689 String shortMsg = crashInfo.exceptionClassName;
6690 String longMsg = crashInfo.exceptionMessage;
6691 String stackTrace = crashInfo.stackTrace;
6692 if (shortMsg != null && longMsg != null) {
6693 longMsg = shortMsg + ": " + longMsg;
6694 } else if (shortMsg != null) {
6695 longMsg = shortMsg;
6696 }
6697
Dan Egnor60d87622009-12-16 16:32:58 -08006698 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006700 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006701 try {
6702 String name = r != null ? r.processName : null;
6703 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006704 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006705 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006706 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 + " at watcher's request");
6708 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006709 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006710 }
6711 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006712 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006713 }
6714 }
6715
6716 final long origId = Binder.clearCallingIdentity();
6717
6718 // If this process is running instrumentation, finish it.
6719 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006720 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006721 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006722 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6723 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006724 Bundle info = new Bundle();
6725 info.putString("shortMsg", shortMsg);
6726 info.putString("longMsg", longMsg);
6727 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6728 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006729 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 }
6731
Dan Egnor60d87622009-12-16 16:32:58 -08006732 // If we can't identify the process or it's already exceeded its crash quota,
6733 // quit right away without showing a crash dialog.
6734 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006735 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006736 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006737 }
6738
6739 Message msg = Message.obtain();
6740 msg.what = SHOW_ERROR_MSG;
6741 HashMap data = new HashMap();
6742 data.put("result", result);
6743 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006744 msg.obj = data;
6745 mHandler.sendMessage(msg);
6746
6747 Binder.restoreCallingIdentity(origId);
6748 }
6749
6750 int res = result.get();
6751
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006752 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006753 synchronized (this) {
6754 if (r != null) {
6755 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6756 SystemClock.uptimeMillis());
6757 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006758 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006759 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006760 }
6761 }
6762
6763 if (appErrorIntent != null) {
6764 try {
6765 mContext.startActivity(appErrorIntent);
6766 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006767 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006770 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006771
6772 Intent createAppErrorIntentLocked(ProcessRecord r,
6773 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6774 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006775 if (report == null) {
6776 return null;
6777 }
6778 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6779 result.setComponent(r.errorReportReceiver);
6780 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6781 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6782 return result;
6783 }
6784
Dan Egnorb7f03672009-12-09 16:22:32 -08006785 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6786 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006787 if (r.errorReportReceiver == null) {
6788 return null;
6789 }
6790
6791 if (!r.crashing && !r.notResponding) {
6792 return null;
6793 }
6794
Dan Egnorb7f03672009-12-09 16:22:32 -08006795 ApplicationErrorReport report = new ApplicationErrorReport();
6796 report.packageName = r.info.packageName;
6797 report.installerPackageName = r.errorReportReceiver.getPackageName();
6798 report.processName = r.processName;
6799 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006800 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006801
Dan Egnorb7f03672009-12-09 16:22:32 -08006802 if (r.crashing) {
6803 report.type = ApplicationErrorReport.TYPE_CRASH;
6804 report.crashInfo = crashInfo;
6805 } else if (r.notResponding) {
6806 report.type = ApplicationErrorReport.TYPE_ANR;
6807 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006808
Dan Egnorb7f03672009-12-09 16:22:32 -08006809 report.anrInfo.activity = r.notRespondingReport.tag;
6810 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6811 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006812 }
6813
Dan Egnorb7f03672009-12-09 16:22:32 -08006814 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006815 }
6816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006817 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6818 // assume our apps are happy - lazy create the list
6819 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6820
6821 synchronized (this) {
6822
6823 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006824 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6825 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006826 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6827 // This one's in trouble, so we'll generate a report for it
6828 // crashes are higher priority (in case there's a crash *and* an anr)
6829 ActivityManager.ProcessErrorStateInfo report = null;
6830 if (app.crashing) {
6831 report = app.crashingReport;
6832 } else if (app.notResponding) {
6833 report = app.notRespondingReport;
6834 }
6835
6836 if (report != null) {
6837 if (errList == null) {
6838 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6839 }
6840 errList.add(report);
6841 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006842 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006843 " crashing = " + app.crashing +
6844 " notResponding = " + app.notResponding);
6845 }
6846 }
6847 }
6848 }
6849
6850 return errList;
6851 }
6852
6853 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6854 // Lazy instantiation of list
6855 List<ActivityManager.RunningAppProcessInfo> runList = null;
6856 synchronized (this) {
6857 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006858 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6859 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006860 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6861 // Generate process state info for running application
6862 ActivityManager.RunningAppProcessInfo currApp =
6863 new ActivityManager.RunningAppProcessInfo(app.processName,
6864 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006865 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006866 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07006867 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006869 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006870 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006871 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6872 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6873 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006874 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6875 } else if (adj >= HOME_APP_ADJ) {
6876 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6877 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006878 } else if (adj >= SECONDARY_SERVER_ADJ) {
6879 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006880 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6881 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6882 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6883 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006884 } else if (adj >= VISIBLE_APP_ADJ) {
6885 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6886 } else {
6887 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6888 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006889 currApp.importanceReasonCode = app.adjTypeCode;
6890 if (app.adjSource instanceof ProcessRecord) {
6891 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006892 } else if (app.adjSource instanceof ActivityRecord) {
6893 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006894 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6895 }
6896 if (app.adjTarget instanceof ComponentName) {
6897 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6898 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006899 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 // + " lru=" + currApp.lru);
6901 if (runList == null) {
6902 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6903 }
6904 runList.add(currApp);
6905 }
6906 }
6907 }
6908 return runList;
6909 }
6910
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006911 public List<ApplicationInfo> getRunningExternalApplications() {
6912 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6913 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6914 if (runningApps != null && runningApps.size() > 0) {
6915 Set<String> extList = new HashSet<String>();
6916 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6917 if (app.pkgList != null) {
6918 for (String pkg : app.pkgList) {
6919 extList.add(pkg);
6920 }
6921 }
6922 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006923 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006924 for (String pkg : extList) {
6925 try {
6926 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6927 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6928 retList.add(info);
6929 }
6930 } catch (RemoteException e) {
6931 }
6932 }
6933 }
6934 return retList;
6935 }
6936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 @Override
6938 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006939 if (checkCallingPermission(android.Manifest.permission.DUMP)
6940 != PackageManager.PERMISSION_GRANTED) {
6941 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6942 + Binder.getCallingPid()
6943 + ", uid=" + Binder.getCallingUid()
6944 + " without permission "
6945 + android.Manifest.permission.DUMP);
6946 return;
6947 }
6948
6949 boolean dumpAll = false;
6950
6951 int opti = 0;
6952 while (opti < args.length) {
6953 String opt = args[opti];
6954 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6955 break;
6956 }
6957 opti++;
6958 if ("-a".equals(opt)) {
6959 dumpAll = true;
6960 } else if ("-h".equals(opt)) {
6961 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006962 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006963 pw.println(" cmd may be one of:");
6964 pw.println(" activities: activity stack state");
6965 pw.println(" broadcasts: broadcast state");
6966 pw.println(" intents: pending intent state");
6967 pw.println(" processes: process state");
6968 pw.println(" providers: content provider state");
6969 pw.println(" services: service state");
6970 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006971 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006972 } else {
6973 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006975 }
6976
6977 // Is the caller requesting to dump a particular piece of data?
6978 if (opti < args.length) {
6979 String cmd = args[opti];
6980 opti++;
6981 if ("activities".equals(cmd) || "a".equals(cmd)) {
6982 synchronized (this) {
6983 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006984 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006985 return;
6986 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6987 synchronized (this) {
6988 dumpBroadcastsLocked(fd, pw, args, opti, true);
6989 }
6990 return;
6991 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6992 synchronized (this) {
6993 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6994 }
6995 return;
6996 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6997 synchronized (this) {
6998 dumpProcessesLocked(fd, pw, args, opti, true);
6999 }
7000 return;
7001 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7002 synchronized (this) {
7003 dumpProvidersLocked(fd, pw, args, opti, true);
7004 }
7005 return;
7006 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007007 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007008 return;
7009 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7010 synchronized (this) {
7011 dumpServicesLocked(fd, pw, args, opti, true);
7012 }
7013 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007015 }
7016
7017 // No piece of data specified, dump everything.
7018 synchronized (this) {
7019 boolean needSep;
7020 if (dumpAll) {
7021 pw.println("Providers in Current Activity Manager State:");
7022 }
7023 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7024 if (needSep) {
7025 pw.println(" ");
7026 }
7027 if (dumpAll) {
7028 pw.println("-------------------------------------------------------------------------------");
7029 pw.println("Broadcasts in Current Activity Manager State:");
7030 }
7031 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7032 if (needSep) {
7033 pw.println(" ");
7034 }
7035 if (dumpAll) {
7036 pw.println("-------------------------------------------------------------------------------");
7037 pw.println("Services in Current Activity Manager State:");
7038 }
7039 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7040 if (needSep) {
7041 pw.println(" ");
7042 }
7043 if (dumpAll) {
7044 pw.println("-------------------------------------------------------------------------------");
7045 pw.println("PendingIntents in Current Activity Manager State:");
7046 }
7047 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7048 if (needSep) {
7049 pw.println(" ");
7050 }
7051 if (dumpAll) {
7052 pw.println("-------------------------------------------------------------------------------");
7053 pw.println("Activities in Current Activity Manager State:");
7054 }
7055 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7056 if (needSep) {
7057 pw.println(" ");
7058 }
7059 if (dumpAll) {
7060 pw.println("-------------------------------------------------------------------------------");
7061 pw.println("Processes in Current Activity Manager State:");
7062 }
7063 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7064 }
7065 }
7066
7067 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7068 int opti, boolean dumpAll, boolean needHeader) {
7069 if (needHeader) {
7070 pw.println(" Activity stack:");
7071 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007072 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007073 pw.println(" ");
7074 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007075 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7076 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007077 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007078 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007079 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007080 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007081 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007082 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007083 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007084 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007085 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007086 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007087 pw.println(" ");
7088 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007089 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007092 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007093 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7094 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007095 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007096 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007097
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007098 if (dumpAll && mRecentTasks.size() > 0) {
7099 pw.println(" ");
7100 pw.println("Recent tasks in Current Activity Manager State:");
7101
7102 final int N = mRecentTasks.size();
7103 for (int i=0; i<N; i++) {
7104 TaskRecord tr = mRecentTasks.get(i);
7105 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7106 pw.println(tr);
7107 mRecentTasks.get(i).dump(pw, " ");
7108 }
7109 }
7110
7111 pw.println(" ");
7112 pw.println(" mCurTask: " + mCurTask);
7113
7114 return true;
7115 }
7116
7117 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7118 int opti, boolean dumpAll) {
7119 boolean needSep = false;
7120 int numPers = 0;
7121
7122 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007123 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7124 final int NA = procs.size();
7125 for (int ia=0; ia<NA; ia++) {
7126 if (!needSep) {
7127 pw.println(" All known processes:");
7128 needSep = true;
7129 }
7130 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007131 pw.print(r.persistent ? " *PERS*" : " *APP*");
7132 pw.print(" UID "); pw.print(procs.keyAt(ia));
7133 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007134 r.dump(pw, " ");
7135 if (r.persistent) {
7136 numPers++;
7137 }
7138 }
7139 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007140 }
7141
7142 if (mLruProcesses.size() > 0) {
7143 if (needSep) pw.println(" ");
7144 needSep = true;
7145 pw.println(" Running processes (most recent first):");
7146 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007147 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007148 needSep = true;
7149 }
7150
7151 synchronized (mPidsSelfLocked) {
7152 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 if (needSep) pw.println(" ");
7154 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007155 pw.println(" PID mappings:");
7156 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7157 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7158 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007159 }
7160 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007161 }
7162
7163 if (mForegroundProcesses.size() > 0) {
7164 if (needSep) pw.println(" ");
7165 needSep = true;
7166 pw.println(" Foreground Processes:");
7167 for (int i=0; i<mForegroundProcesses.size(); i++) {
7168 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7169 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007170 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007171 }
7172
7173 if (mPersistentStartingProcesses.size() > 0) {
7174 if (needSep) pw.println(" ");
7175 needSep = true;
7176 pw.println(" Persisent processes that are starting:");
7177 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
7178 "Starting Norm", "Restarting PERS", false);
7179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007181 if (mStartingProcesses.size() > 0) {
7182 if (needSep) pw.println(" ");
7183 needSep = true;
7184 pw.println(" Processes that are starting:");
7185 dumpProcessList(pw, this, mStartingProcesses, " ",
7186 "Starting Norm", "Starting PERS", false);
7187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007188
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007189 if (mRemovedProcesses.size() > 0) {
7190 if (needSep) pw.println(" ");
7191 needSep = true;
7192 pw.println(" Processes that are being removed:");
7193 dumpProcessList(pw, this, mRemovedProcesses, " ",
7194 "Removed Norm", "Removed PERS", false);
7195 }
7196
7197 if (mProcessesOnHold.size() > 0) {
7198 if (needSep) pw.println(" ");
7199 needSep = true;
7200 pw.println(" Processes that are on old until the system is ready:");
7201 dumpProcessList(pw, this, mProcessesOnHold, " ",
7202 "OnHold Norm", "OnHold PERS", false);
7203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007204
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007205 if (mProcessesToGc.size() > 0) {
7206 if (needSep) pw.println(" ");
7207 needSep = true;
7208 pw.println(" Processes that are waiting to GC:");
7209 long now = SystemClock.uptimeMillis();
7210 for (int i=0; i<mProcessesToGc.size(); i++) {
7211 ProcessRecord proc = mProcessesToGc.get(i);
7212 pw.print(" Process "); pw.println(proc);
7213 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7214 pw.print(", last gced=");
7215 pw.print(now-proc.lastRequestedGc);
7216 pw.print(" ms ago, last lowMem=");
7217 pw.print(now-proc.lastLowMemory);
7218 pw.println(" ms ago");
7219
7220 }
7221 }
7222
7223 if (mProcessCrashTimes.getMap().size() > 0) {
7224 if (needSep) pw.println(" ");
7225 needSep = true;
7226 pw.println(" Time since processes crashed:");
7227 long now = SystemClock.uptimeMillis();
7228 for (Map.Entry<String, SparseArray<Long>> procs
7229 : mProcessCrashTimes.getMap().entrySet()) {
7230 SparseArray<Long> uids = procs.getValue();
7231 final int N = uids.size();
7232 for (int i=0; i<N; i++) {
7233 pw.print(" Process "); pw.print(procs.getKey());
7234 pw.print(" uid "); pw.print(uids.keyAt(i));
7235 pw.print(": last crashed ");
7236 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007237 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007238 }
7239 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007240 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007242 if (mBadProcesses.getMap().size() > 0) {
7243 if (needSep) pw.println(" ");
7244 needSep = true;
7245 pw.println(" Bad processes:");
7246 for (Map.Entry<String, SparseArray<Long>> procs
7247 : mBadProcesses.getMap().entrySet()) {
7248 SparseArray<Long> uids = procs.getValue();
7249 final int N = uids.size();
7250 for (int i=0; i<N; i++) {
7251 pw.print(" Bad process "); pw.print(procs.getKey());
7252 pw.print(" uid "); pw.print(uids.keyAt(i));
7253 pw.print(": crashed at time ");
7254 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007255 }
7256 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007258
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007259 pw.println(" ");
7260 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007261 if (mHeavyWeightProcess != null) {
7262 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7263 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007264 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007265 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007266 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7267 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7268 || mOrigWaitForDebugger) {
7269 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7270 + " mDebugTransient=" + mDebugTransient
7271 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7272 }
7273 if (mAlwaysFinishActivities || mController != null) {
7274 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7275 + " mController=" + mController);
7276 }
7277 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007278 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007279 pw.println(" mStartRunning=" + mStartRunning
7280 + " mSystemReady=" + mSystemReady
7281 + " mBooting=" + mBooting
7282 + " mBooted=" + mBooted
7283 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007284 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7285 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007286 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007287 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007288
7289 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007290 }
7291
7292 /**
7293 * There are three ways to call this:
7294 * - no service specified: dump all the services
7295 * - a flattened component name that matched an existing service was specified as the
7296 * first arg: dump that one service
7297 * - the first arg isn't the flattened component name of an existing service:
7298 * dump all services whose component contains the first arg as a substring
7299 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007300 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7301 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302 String[] newArgs;
7303 String componentNameString;
7304 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007305 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 componentNameString = null;
7307 newArgs = EMPTY_STRING_ARRAY;
7308 r = null;
7309 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007310 componentNameString = args[opti];
7311 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007312 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007313 synchronized (this) {
7314 r = componentName != null ? mServices.get(componentName) : null;
7315 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007316 newArgs = new String[args.length - opti];
7317 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007318 }
7319
7320 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007321 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007322 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007323 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7324 synchronized (this) {
7325 for (ServiceRecord r1 : mServices.values()) {
7326 if (componentNameString == null
7327 || r1.name.flattenToString().contains(componentNameString)) {
7328 services.add(r1);
7329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007330 }
7331 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007332 for (int i=0; i<services.size(); i++) {
7333 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007335 }
7336 }
7337
7338 /**
7339 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7340 * there is a thread associated with the service.
7341 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007342 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7343 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007344 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007345 if (dumpAll) {
7346 synchronized (this) {
7347 pw.print(" * "); pw.println(r);
7348 r.dump(pw, " ");
7349 }
7350 pw.println("");
7351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352 if (r.app != null && r.app.thread != null) {
7353 try {
7354 // flush anything that is already in the PrintWriter since the thread is going
7355 // to write to the file descriptor directly
7356 pw.flush();
7357 r.app.thread.dumpService(fd, r, args);
7358 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007359 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 } catch (RemoteException e) {
7361 pw.println("got a RemoteException while dumping the service");
7362 }
7363 }
7364 }
7365
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007366 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7367 int opti, boolean dumpAll) {
7368 boolean needSep = false;
7369
7370 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 if (mRegisteredReceivers.size() > 0) {
7372 pw.println(" ");
7373 pw.println(" Registered Receivers:");
7374 Iterator it = mRegisteredReceivers.values().iterator();
7375 while (it.hasNext()) {
7376 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007377 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 r.dump(pw, " ");
7379 }
7380 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 pw.println(" ");
7383 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007384 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007385 needSep = true;
7386 }
7387
7388 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7389 || mPendingBroadcast != null) {
7390 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007392 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007393 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007394 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7395 pw.println(" Broadcast #" + i + ":");
7396 mParallelBroadcasts.get(i).dump(pw, " ");
7397 }
7398 if (mOrderedBroadcasts.size() > 0) {
7399 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007400 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007401 }
7402 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7403 pw.println(" Serialized Broadcast #" + i + ":");
7404 mOrderedBroadcasts.get(i).dump(pw, " ");
7405 }
7406 pw.println(" ");
7407 pw.println(" Pending broadcast:");
7408 if (mPendingBroadcast != null) {
7409 mPendingBroadcast.dump(pw, " ");
7410 } else {
7411 pw.println(" (null)");
7412 }
7413 needSep = true;
7414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007416 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007418 pw.println(" Historical broadcasts:");
7419 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7420 BroadcastRecord r = mBroadcastHistory[i];
7421 if (r == null) {
7422 break;
7423 }
7424 pw.println(" Historical Broadcast #" + i + ":");
7425 r.dump(pw, " ");
7426 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007427 needSep = true;
7428 }
7429
7430 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007431 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007432 pw.println(" Sticky broadcasts:");
7433 StringBuilder sb = new StringBuilder(128);
7434 for (Map.Entry<String, ArrayList<Intent>> ent
7435 : mStickyBroadcasts.entrySet()) {
7436 pw.print(" * Sticky action "); pw.print(ent.getKey());
7437 pw.println(":");
7438 ArrayList<Intent> intents = ent.getValue();
7439 final int N = intents.size();
7440 for (int i=0; i<N; i++) {
7441 sb.setLength(0);
7442 sb.append(" Intent: ");
7443 intents.get(i).toShortString(sb, true, false);
7444 pw.println(sb.toString());
7445 Bundle bundle = intents.get(i).getExtras();
7446 if (bundle != null) {
7447 pw.print(" ");
7448 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007449 }
7450 }
7451 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007452 needSep = true;
7453 }
7454
7455 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007456 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007457 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 pw.println(" mHandler:");
7459 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007460 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007462
7463 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007464 }
7465
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007466 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7467 int opti, boolean dumpAll) {
7468 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007469
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007470 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 if (mServices.size() > 0) {
7472 pw.println(" Active services:");
7473 Iterator<ServiceRecord> it = mServices.values().iterator();
7474 while (it.hasNext()) {
7475 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007476 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007477 r.dump(pw, " ");
7478 }
7479 needSep = true;
7480 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007482
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007483 if (mPendingServices.size() > 0) {
7484 if (needSep) pw.println(" ");
7485 pw.println(" Pending services:");
7486 for (int i=0; i<mPendingServices.size(); i++) {
7487 ServiceRecord r = mPendingServices.get(i);
7488 pw.print(" * Pending "); pw.println(r);
7489 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007490 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007491 needSep = true;
7492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007493
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007494 if (mRestartingServices.size() > 0) {
7495 if (needSep) pw.println(" ");
7496 pw.println(" Restarting services:");
7497 for (int i=0; i<mRestartingServices.size(); i++) {
7498 ServiceRecord r = mRestartingServices.get(i);
7499 pw.print(" * Restarting "); pw.println(r);
7500 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007501 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007502 needSep = true;
7503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007504
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007505 if (mStoppingServices.size() > 0) {
7506 if (needSep) pw.println(" ");
7507 pw.println(" Stopping services:");
7508 for (int i=0; i<mStoppingServices.size(); i++) {
7509 ServiceRecord r = mStoppingServices.get(i);
7510 pw.print(" * Stopping "); pw.println(r);
7511 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007512 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007513 needSep = true;
7514 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007516 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517 if (mServiceConnections.size() > 0) {
7518 if (needSep) pw.println(" ");
7519 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007520 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007521 = mServiceConnections.values().iterator();
7522 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007523 ArrayList<ConnectionRecord> r = it.next();
7524 for (int i=0; i<r.size(); i++) {
7525 pw.print(" * "); pw.println(r.get(i));
7526 r.get(i).dump(pw, " ");
7527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007529 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007530 }
7531 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007532
7533 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534 }
7535
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007536 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7537 int opti, boolean dumpAll) {
7538 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007539
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007540 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007541 if (mProvidersByClass.size() > 0) {
7542 if (needSep) pw.println(" ");
7543 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007544 Iterator<Map.Entry<String, ContentProviderRecord>> it
7545 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007546 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007547 Map.Entry<String, ContentProviderRecord> e = it.next();
7548 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007549 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007550 r.dump(pw, " ");
7551 }
7552 needSep = true;
7553 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007554
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007555 if (mProvidersByName.size() > 0) {
7556 pw.println(" ");
7557 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007558 Iterator<Map.Entry<String, ContentProviderRecord>> it
7559 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007560 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007561 Map.Entry<String, ContentProviderRecord> e = it.next();
7562 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007563 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7564 pw.println(r);
7565 }
7566 needSep = true;
7567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007569
7570 if (mLaunchingProviders.size() > 0) {
7571 if (needSep) pw.println(" ");
7572 pw.println(" Launching content providers:");
7573 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7574 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7575 pw.println(mLaunchingProviders.get(i));
7576 }
7577 needSep = true;
7578 }
7579
7580 if (mGrantedUriPermissions.size() > 0) {
7581 pw.println();
7582 pw.println("Granted Uri Permissions:");
7583 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7584 int uid = mGrantedUriPermissions.keyAt(i);
7585 HashMap<Uri, UriPermission> perms
7586 = mGrantedUriPermissions.valueAt(i);
7587 pw.print(" * UID "); pw.print(uid);
7588 pw.println(" holds:");
7589 for (UriPermission perm : perms.values()) {
7590 pw.print(" "); pw.println(perm);
7591 perm.dump(pw, " ");
7592 }
7593 }
7594 needSep = true;
7595 }
7596
7597 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007598 }
7599
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007600 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7601 int opti, boolean dumpAll) {
7602 boolean needSep = false;
7603
7604 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007605 if (this.mIntentSenderRecords.size() > 0) {
7606 Iterator<WeakReference<PendingIntentRecord>> it
7607 = mIntentSenderRecords.values().iterator();
7608 while (it.hasNext()) {
7609 WeakReference<PendingIntentRecord> ref = it.next();
7610 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007611 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007612 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007613 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614 rec.dump(pw, " ");
7615 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007616 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007617 }
7618 }
7619 }
7620 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007621
7622 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007623 }
7624
7625 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007626 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007627 TaskRecord lastTask = null;
7628 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007629 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007630 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 if (lastTask != r.task) {
7632 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007633 pw.print(prefix);
7634 pw.print(full ? "* " : " ");
7635 pw.println(lastTask);
7636 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007637 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007639 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007640 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7641 pw.print(" #"); pw.print(i); pw.print(": ");
7642 pw.println(r);
7643 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007644 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646 }
7647 }
7648
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007649 private static String buildOomTag(String prefix, String space, int val, int base) {
7650 if (val == base) {
7651 if (space == null) return prefix;
7652 return prefix + " ";
7653 }
7654 return prefix + "+" + Integer.toString(val-base);
7655 }
7656
7657 private static final int dumpProcessList(PrintWriter pw,
7658 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007659 String prefix, String normalLabel, String persistentLabel,
7660 boolean inclOomAdj) {
7661 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007662 final int N = list.size()-1;
7663 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007664 ProcessRecord r = (ProcessRecord)list.get(i);
7665 if (false) {
7666 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7667 + " #" + i + ":");
7668 r.dump(pw, prefix + " ");
7669 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007670 String oomAdj;
7671 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007672 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007673 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007674 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7675 } else if (r.setAdj >= HOME_APP_ADJ) {
7676 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7677 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7678 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7679 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7680 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007681 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7682 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7683 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7684 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007685 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7686 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7687 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7688 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007689 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007690 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007691 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007692 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007693 } else {
7694 oomAdj = Integer.toString(r.setAdj);
7695 }
7696 String schedGroup;
7697 switch (r.setSchedGroup) {
7698 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7699 schedGroup = "B";
7700 break;
7701 case Process.THREAD_GROUP_DEFAULT:
7702 schedGroup = "F";
7703 break;
7704 default:
7705 schedGroup = Integer.toString(r.setSchedGroup);
7706 break;
7707 }
7708 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007710 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007711 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007712 pw.print(prefix);
7713 pw.print(" ");
7714 if (r.adjTarget instanceof ComponentName) {
7715 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7716 } else if (r.adjTarget != null) {
7717 pw.print(r.adjTarget.toString());
7718 } else {
7719 pw.print("{null}");
7720 }
7721 pw.print("<=");
7722 if (r.adjSource instanceof ProcessRecord) {
7723 pw.print("Proc{");
7724 pw.print(((ProcessRecord)r.adjSource).toShortString());
7725 pw.println("}");
7726 } else if (r.adjSource != null) {
7727 pw.println(r.adjSource.toString());
7728 } else {
7729 pw.println("{null}");
7730 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732 } else {
7733 pw.println(String.format("%s%s #%2d: %s",
7734 prefix, (r.persistent ? persistentLabel : normalLabel),
7735 i, r.toString()));
7736 }
7737 if (r.persistent) {
7738 numPers++;
7739 }
7740 }
7741 return numPers;
7742 }
7743
Dianne Hackborn472ad872010-04-07 17:31:48 -07007744 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007745 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007746 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007747 long uptime = SystemClock.uptimeMillis();
7748 long realtime = SystemClock.elapsedRealtime();
7749
7750 if (isCheckinRequest) {
7751 // short checkin version
7752 pw.println(uptime + "," + realtime);
7753 pw.flush();
7754 } else {
7755 pw.println("Applications Memory Usage (kB):");
7756 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7757 }
7758 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7759 ProcessRecord r = (ProcessRecord)list.get(i);
7760 if (r.thread != null) {
7761 if (!isCheckinRequest) {
7762 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7763 pw.flush();
7764 }
7765 try {
7766 r.thread.asBinder().dump(fd, args);
7767 } catch (RemoteException e) {
7768 if (!isCheckinRequest) {
7769 pw.println("Got RemoteException!");
7770 pw.flush();
7771 }
7772 }
7773 }
7774 }
7775 }
7776
7777 /**
7778 * Searches array of arguments for the specified string
7779 * @param args array of argument strings
7780 * @param value value to search for
7781 * @return true if the value is contained in the array
7782 */
7783 private static boolean scanArgs(String[] args, String value) {
7784 if (args != null) {
7785 for (String arg : args) {
7786 if (value.equals(arg)) {
7787 return true;
7788 }
7789 }
7790 }
7791 return false;
7792 }
7793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 private final void killServicesLocked(ProcessRecord app,
7795 boolean allowRestart) {
7796 // Report disconnected services.
7797 if (false) {
7798 // XXX we are letting the client link to the service for
7799 // death notifications.
7800 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007801 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007802 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007803 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007805 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007806 = r.connections.values().iterator();
7807 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007808 ArrayList<ConnectionRecord> cl = jt.next();
7809 for (int i=0; i<cl.size(); i++) {
7810 ConnectionRecord c = cl.get(i);
7811 if (c.binding.client != app) {
7812 try {
7813 //c.conn.connected(r.className, null);
7814 } catch (Exception e) {
7815 // todo: this should be asynchronous!
7816 Slog.w(TAG, "Exception thrown disconnected servce "
7817 + r.shortName
7818 + " from app " + app.processName, e);
7819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007820 }
7821 }
7822 }
7823 }
7824 }
7825 }
7826 }
7827
7828 // Clean up any connections this application has to other services.
7829 if (app.connections.size() > 0) {
7830 Iterator<ConnectionRecord> it = app.connections.iterator();
7831 while (it.hasNext()) {
7832 ConnectionRecord r = it.next();
7833 removeConnectionLocked(r, app, null);
7834 }
7835 }
7836 app.connections.clear();
7837
7838 if (app.services.size() != 0) {
7839 // Any services running in the application need to be placed
7840 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007841 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007843 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007844 synchronized (sr.stats.getBatteryStats()) {
7845 sr.stats.stopLaunchedLocked();
7846 }
7847 sr.app = null;
7848 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007849 if (mStoppingServices.remove(sr)) {
7850 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
7851 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007852
7853 boolean hasClients = sr.bindings.size() > 0;
7854 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007855 Iterator<IntentBindRecord> bindings
7856 = sr.bindings.values().iterator();
7857 while (bindings.hasNext()) {
7858 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007859 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007860 + ": shouldUnbind=" + b.hasBound);
7861 b.binder = null;
7862 b.requested = b.received = b.hasBound = false;
7863 }
7864 }
7865
7866 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007867 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007868 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007869 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007870 sr.crashCount, sr.shortName, app.pid);
7871 bringDownServiceLocked(sr, true);
7872 } else if (!allowRestart) {
7873 bringDownServiceLocked(sr, true);
7874 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007875 boolean canceled = scheduleServiceRestartLocked(sr, true);
7876
7877 // Should the service remain running? Note that in the
7878 // extreme case of so many attempts to deliver a command
7879 // that it failed, that we also will stop it here.
7880 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7881 if (sr.pendingStarts.size() == 0) {
7882 sr.startRequested = false;
7883 if (!hasClients) {
7884 // Whoops, no reason to restart!
7885 bringDownServiceLocked(sr, true);
7886 }
7887 }
7888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007889 }
7890 }
7891
7892 if (!allowRestart) {
7893 app.services.clear();
7894 }
7895 }
7896
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007897 // Make sure we have no more records on the stopping list.
7898 int i = mStoppingServices.size();
7899 while (i > 0) {
7900 i--;
7901 ServiceRecord sr = mStoppingServices.get(i);
7902 if (sr.app == app) {
7903 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007904 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007905 }
7906 }
7907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 app.executingServices.clear();
7909 }
7910
7911 private final void removeDyingProviderLocked(ProcessRecord proc,
7912 ContentProviderRecord cpr) {
7913 synchronized (cpr) {
7914 cpr.launchingApp = null;
7915 cpr.notifyAll();
7916 }
7917
7918 mProvidersByClass.remove(cpr.info.name);
7919 String names[] = cpr.info.authority.split(";");
7920 for (int j = 0; j < names.length; j++) {
7921 mProvidersByName.remove(names[j]);
7922 }
7923
7924 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7925 while (cit.hasNext()) {
7926 ProcessRecord capp = cit.next();
7927 if (!capp.persistent && capp.thread != null
7928 && capp.pid != 0
7929 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007930 Slog.i(TAG, "Kill " + capp.processName
7931 + " (pid " + capp.pid + "): provider " + cpr.info.name
7932 + " in dying process " + proc.processName);
7933 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7934 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 Process.killProcess(capp.pid);
7936 }
7937 }
7938
7939 mLaunchingProviders.remove(cpr);
7940 }
7941
7942 /**
7943 * Main code for cleaning up a process when it has gone away. This is
7944 * called both as a result of the process dying, or directly when stopping
7945 * a process when running in single process mode.
7946 */
7947 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7948 boolean restarting, int index) {
7949 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007950 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007951 }
7952
Dianne Hackborn36124872009-10-08 16:22:03 -07007953 mProcessesToGc.remove(app);
7954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 // Dismiss any open dialogs.
7956 if (app.crashDialog != null) {
7957 app.crashDialog.dismiss();
7958 app.crashDialog = null;
7959 }
7960 if (app.anrDialog != null) {
7961 app.anrDialog.dismiss();
7962 app.anrDialog = null;
7963 }
7964 if (app.waitDialog != null) {
7965 app.waitDialog.dismiss();
7966 app.waitDialog = null;
7967 }
7968
7969 app.crashing = false;
7970 app.notResponding = false;
7971
7972 app.resetPackageList();
7973 app.thread = null;
7974 app.forcingToForeground = null;
7975 app.foregroundServices = false;
7976
7977 killServicesLocked(app, true);
7978
7979 boolean restart = false;
7980
7981 int NL = mLaunchingProviders.size();
7982
7983 // Remove published content providers.
7984 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007985 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007986 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007987 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007988 cpr.provider = null;
7989 cpr.app = null;
7990
7991 // See if someone is waiting for this provider... in which
7992 // case we don't remove it, but just let it restart.
7993 int i = 0;
7994 if (!app.bad) {
7995 for (; i<NL; i++) {
7996 if (mLaunchingProviders.get(i) == cpr) {
7997 restart = true;
7998 break;
7999 }
8000 }
8001 } else {
8002 i = NL;
8003 }
8004
8005 if (i >= NL) {
8006 removeDyingProviderLocked(app, cpr);
8007 NL = mLaunchingProviders.size();
8008 }
8009 }
8010 app.pubProviders.clear();
8011 }
8012
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008013 // Take care of any launching providers waiting for this process.
8014 if (checkAppInLaunchingProvidersLocked(app, false)) {
8015 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008018 // Unregister from connected content providers.
8019 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008020 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 while (it.hasNext()) {
8022 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8023 cpr.clients.remove(app);
8024 }
8025 app.conProviders.clear();
8026 }
8027
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008028 // At this point there may be remaining entries in mLaunchingProviders
8029 // where we were the only one waiting, so they are no longer of use.
8030 // Look for these and clean up if found.
8031 // XXX Commented out for now. Trying to figure out a way to reproduce
8032 // the actual situation to identify what is actually going on.
8033 if (false) {
8034 for (int i=0; i<NL; i++) {
8035 ContentProviderRecord cpr = (ContentProviderRecord)
8036 mLaunchingProviders.get(i);
8037 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8038 synchronized (cpr) {
8039 cpr.launchingApp = null;
8040 cpr.notifyAll();
8041 }
8042 }
8043 }
8044 }
8045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046 skipCurrentReceiverLocked(app);
8047
8048 // Unregister any receivers.
8049 if (app.receivers.size() > 0) {
8050 Iterator<ReceiverList> it = app.receivers.iterator();
8051 while (it.hasNext()) {
8052 removeReceiverLocked(it.next());
8053 }
8054 app.receivers.clear();
8055 }
8056
Christopher Tate181fafa2009-05-14 11:12:14 -07008057 // If the app is undergoing backup, tell the backup manager about it
8058 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008059 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008060 try {
8061 IBackupManager bm = IBackupManager.Stub.asInterface(
8062 ServiceManager.getService(Context.BACKUP_SERVICE));
8063 bm.agentDisconnected(app.info.packageName);
8064 } catch (RemoteException e) {
8065 // can't happen; backup manager is local
8066 }
8067 }
8068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 // If the caller is restarting this app, then leave it in its
8070 // current lists and let the caller take care of it.
8071 if (restarting) {
8072 return;
8073 }
8074
8075 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008076 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 "Removing non-persistent process during cleanup: " + app);
8078 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008079 if (mHeavyWeightProcess == app) {
8080 mHeavyWeightProcess = null;
8081 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8082 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008083 } else if (!app.removed) {
8084 // This app is persistent, so we need to keep its record around.
8085 // If it is not already on the pending app list, add it there
8086 // and start a new process for it.
8087 app.thread = null;
8088 app.forcingToForeground = null;
8089 app.foregroundServices = false;
8090 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8091 mPersistentStartingProcesses.add(app);
8092 restart = true;
8093 }
8094 }
8095 mProcessesOnHold.remove(app);
8096
The Android Open Source Project4df24232009-03-05 14:34:35 -08008097 if (app == mHomeProcess) {
8098 mHomeProcess = null;
8099 }
8100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 if (restart) {
8102 // We have components that still need to be running in the
8103 // process, so re-launch it.
8104 mProcessNames.put(app.processName, app.info.uid, app);
8105 startProcessLocked(app, "restart", app.processName);
8106 } else if (app.pid > 0 && app.pid != MY_PID) {
8107 // Goodbye!
8108 synchronized (mPidsSelfLocked) {
8109 mPidsSelfLocked.remove(app.pid);
8110 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8111 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008112 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113 }
8114 }
8115
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008116 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8117 // Look through the content providers we are waiting to have launched,
8118 // and if any run in this process then either schedule a restart of
8119 // the process or kill the client waiting for it if this process has
8120 // gone bad.
8121 int NL = mLaunchingProviders.size();
8122 boolean restart = false;
8123 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008124 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008125 if (cpr.launchingApp == app) {
8126 if (!alwaysBad && !app.bad) {
8127 restart = true;
8128 } else {
8129 removeDyingProviderLocked(app, cpr);
8130 NL = mLaunchingProviders.size();
8131 }
8132 }
8133 }
8134 return restart;
8135 }
8136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 // =========================================================
8138 // SERVICES
8139 // =========================================================
8140
8141 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8142 ActivityManager.RunningServiceInfo info =
8143 new ActivityManager.RunningServiceInfo();
8144 info.service = r.name;
8145 if (r.app != null) {
8146 info.pid = r.app.pid;
8147 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008148 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 info.process = r.processName;
8150 info.foreground = r.isForeground;
8151 info.activeSince = r.createTime;
8152 info.started = r.startRequested;
8153 info.clientCount = r.connections.size();
8154 info.crashCount = r.crashCount;
8155 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008156 if (r.isForeground) {
8157 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8158 }
8159 if (r.startRequested) {
8160 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8161 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008162 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008163 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8164 }
8165 if (r.app != null && r.app.persistent) {
8166 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8167 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008168
8169 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8170 for (int i=0; i<connl.size(); i++) {
8171 ConnectionRecord conn = connl.get(i);
8172 if (conn.clientLabel != 0) {
8173 info.clientPackage = conn.binding.client.info.packageName;
8174 info.clientLabel = conn.clientLabel;
8175 return info;
8176 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008177 }
8178 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008179 return info;
8180 }
8181
8182 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8183 int flags) {
8184 synchronized (this) {
8185 ArrayList<ActivityManager.RunningServiceInfo> res
8186 = new ArrayList<ActivityManager.RunningServiceInfo>();
8187
8188 if (mServices.size() > 0) {
8189 Iterator<ServiceRecord> it = mServices.values().iterator();
8190 while (it.hasNext() && res.size() < maxNum) {
8191 res.add(makeRunningServiceInfoLocked(it.next()));
8192 }
8193 }
8194
8195 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8196 ServiceRecord r = mRestartingServices.get(i);
8197 ActivityManager.RunningServiceInfo info =
8198 makeRunningServiceInfoLocked(r);
8199 info.restarting = r.nextRestartTime;
8200 res.add(info);
8201 }
8202
8203 return res;
8204 }
8205 }
8206
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008207 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8208 synchronized (this) {
8209 ServiceRecord r = mServices.get(name);
8210 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008211 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8212 for (int i=0; i<conn.size(); i++) {
8213 if (conn.get(i).clientIntent != null) {
8214 return conn.get(i).clientIntent;
8215 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008216 }
8217 }
8218 }
8219 }
8220 return null;
8221 }
8222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 private final ServiceRecord findServiceLocked(ComponentName name,
8224 IBinder token) {
8225 ServiceRecord r = mServices.get(name);
8226 return r == token ? r : null;
8227 }
8228
8229 private final class ServiceLookupResult {
8230 final ServiceRecord record;
8231 final String permission;
8232
8233 ServiceLookupResult(ServiceRecord _record, String _permission) {
8234 record = _record;
8235 permission = _permission;
8236 }
8237 };
8238
8239 private ServiceLookupResult findServiceLocked(Intent service,
8240 String resolvedType) {
8241 ServiceRecord r = null;
8242 if (service.getComponent() != null) {
8243 r = mServices.get(service.getComponent());
8244 }
8245 if (r == null) {
8246 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8247 r = mServicesByIntent.get(filter);
8248 }
8249
8250 if (r == null) {
8251 try {
8252 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008253 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008254 service, resolvedType, 0);
8255 ServiceInfo sInfo =
8256 rInfo != null ? rInfo.serviceInfo : null;
8257 if (sInfo == null) {
8258 return null;
8259 }
8260
8261 ComponentName name = new ComponentName(
8262 sInfo.applicationInfo.packageName, sInfo.name);
8263 r = mServices.get(name);
8264 } catch (RemoteException ex) {
8265 // pm is in same process, this will never happen.
8266 }
8267 }
8268 if (r != null) {
8269 int callingPid = Binder.getCallingPid();
8270 int callingUid = Binder.getCallingUid();
8271 if (checkComponentPermission(r.permission,
8272 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8273 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008274 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008275 + " from pid=" + callingPid
8276 + ", uid=" + callingUid
8277 + " requires " + r.permission);
8278 return new ServiceLookupResult(null, r.permission);
8279 }
8280 return new ServiceLookupResult(r, null);
8281 }
8282 return null;
8283 }
8284
8285 private class ServiceRestarter implements Runnable {
8286 private ServiceRecord mService;
8287
8288 void setService(ServiceRecord service) {
8289 mService = service;
8290 }
8291
8292 public void run() {
8293 synchronized(ActivityManagerService.this) {
8294 performServiceRestartLocked(mService);
8295 }
8296 }
8297 }
8298
8299 private ServiceLookupResult retrieveServiceLocked(Intent service,
8300 String resolvedType, int callingPid, int callingUid) {
8301 ServiceRecord r = null;
8302 if (service.getComponent() != null) {
8303 r = mServices.get(service.getComponent());
8304 }
8305 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8306 r = mServicesByIntent.get(filter);
8307 if (r == null) {
8308 try {
8309 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008310 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008311 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 ServiceInfo sInfo =
8313 rInfo != null ? rInfo.serviceInfo : null;
8314 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008315 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008316 ": not found");
8317 return null;
8318 }
8319
8320 ComponentName name = new ComponentName(
8321 sInfo.applicationInfo.packageName, sInfo.name);
8322 r = mServices.get(name);
8323 if (r == null) {
8324 filter = new Intent.FilterComparison(service.cloneFilter());
8325 ServiceRestarter res = new ServiceRestarter();
8326 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8327 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8328 synchronized (stats) {
8329 ss = stats.getServiceStatsLocked(
8330 sInfo.applicationInfo.uid, sInfo.packageName,
8331 sInfo.name);
8332 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008333 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008334 res.setService(r);
8335 mServices.put(name, r);
8336 mServicesByIntent.put(filter, r);
8337
8338 // Make sure this component isn't in the pending list.
8339 int N = mPendingServices.size();
8340 for (int i=0; i<N; i++) {
8341 ServiceRecord pr = mPendingServices.get(i);
8342 if (pr.name.equals(name)) {
8343 mPendingServices.remove(i);
8344 i--;
8345 N--;
8346 }
8347 }
8348 }
8349 } catch (RemoteException ex) {
8350 // pm is in same process, this will never happen.
8351 }
8352 }
8353 if (r != null) {
8354 if (checkComponentPermission(r.permission,
8355 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8356 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008357 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008358 + " from pid=" + Binder.getCallingPid()
8359 + ", uid=" + Binder.getCallingUid()
8360 + " requires " + r.permission);
8361 return new ServiceLookupResult(null, r.permission);
8362 }
8363 return new ServiceLookupResult(r, null);
8364 }
8365 return null;
8366 }
8367
8368 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8369 long now = SystemClock.uptimeMillis();
8370 if (r.executeNesting == 0 && r.app != null) {
8371 if (r.app.executingServices.size() == 0) {
8372 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8373 msg.obj = r.app;
8374 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8375 }
8376 r.app.executingServices.add(r);
8377 }
8378 r.executeNesting++;
8379 r.executingStart = now;
8380 }
8381
8382 private final void sendServiceArgsLocked(ServiceRecord r,
8383 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008384 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 if (N == 0) {
8386 return;
8387 }
8388
Dianne Hackborn39792d22010-08-19 18:01:52 -07008389 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008390 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008391 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008392 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8393 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008394 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008395 // If somehow we got a dummy start at the front, then
8396 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008397 continue;
8398 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008399 si.deliveredTime = SystemClock.uptimeMillis();
8400 r.deliveredStarts.add(si);
8401 si.deliveryCount++;
8402 if (si.targetPermissionUid >= 0) {
8403 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008404 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008405 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008406 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 bumpServiceExecutingLocked(r);
8408 if (!oomAdjusted) {
8409 oomAdjusted = true;
8410 updateOomAdjLocked(r.app);
8411 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008412 int flags = 0;
8413 if (si.deliveryCount > 0) {
8414 flags |= Service.START_FLAG_RETRY;
8415 }
8416 if (si.doneExecutingCount > 0) {
8417 flags |= Service.START_FLAG_REDELIVERY;
8418 }
8419 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008420 } catch (RemoteException e) {
8421 // Remote process gone... we'll let the normal cleanup take
8422 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008423 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008424 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008426 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008427 break;
8428 }
8429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008430 }
8431
8432 private final boolean requestServiceBindingLocked(ServiceRecord r,
8433 IntentBindRecord i, boolean rebind) {
8434 if (r.app == null || r.app.thread == null) {
8435 // If service is not currently running, can't yet bind.
8436 return false;
8437 }
8438 if ((!i.requested || rebind) && i.apps.size() > 0) {
8439 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008440 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
8441 + " in " + i + ": shouldUnbind=" + i.hasBound);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008442 bumpServiceExecutingLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8444 if (!rebind) {
8445 i.requested = true;
8446 }
8447 i.hasBound = true;
8448 i.doRebind = false;
8449 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008450 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008451 return false;
8452 }
8453 }
8454 return true;
8455 }
8456
8457 private final void requestServiceBindingsLocked(ServiceRecord r) {
8458 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8459 while (bindings.hasNext()) {
8460 IntentBindRecord i = bindings.next();
8461 if (!requestServiceBindingLocked(r, i, false)) {
8462 break;
8463 }
8464 }
8465 }
8466
8467 private final void realStartServiceLocked(ServiceRecord r,
8468 ProcessRecord app) throws RemoteException {
8469 if (app.thread == null) {
8470 throw new RemoteException();
8471 }
8472
8473 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008474 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475
8476 app.services.add(r);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008477 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008478 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008479 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008480
8481 boolean created = false;
8482 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008483 mStringBuilder.setLength(0);
8484 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008485 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008487 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008488 synchronized (r.stats.getBatteryStats()) {
8489 r.stats.startLaunchedLocked();
8490 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008491 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008492 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008493 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008494 created = true;
8495 } finally {
8496 if (!created) {
8497 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008498 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008499 }
8500 }
8501
8502 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008503
8504 // If the service is in the started state, and there are no
8505 // pending arguments, then fake up one so its onStartCommand() will
8506 // be called.
8507 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8508 r.lastStartId++;
8509 if (r.lastStartId < 1) {
8510 r.lastStartId = 1;
8511 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008512 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008513 }
8514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 sendServiceArgsLocked(r, true);
8516 }
8517
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008518 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8519 boolean allowCancel) {
8520 boolean canceled = false;
8521
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008522 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008523 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008524 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008525
8526 // Any delivered but not yet finished starts should be put back
8527 // on the pending list.
8528 final int N = r.deliveredStarts.size();
8529 if (N > 0) {
8530 for (int i=N-1; i>=0; i--) {
8531 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008532 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008533 if (si.intent == null) {
8534 // We'll generate this again if needed.
8535 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8536 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8537 r.pendingStarts.add(0, si);
8538 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8539 dur *= 2;
8540 if (minDuration < dur) minDuration = dur;
8541 if (resetTime < dur) resetTime = dur;
8542 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008543 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008544 + r.name);
8545 canceled = true;
8546 }
8547 }
8548 r.deliveredStarts.clear();
8549 }
8550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008551 r.totalRestartCount++;
8552 if (r.restartDelay == 0) {
8553 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008554 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 } else {
8556 // If it has been a "reasonably long time" since the service
8557 // was started, then reset our restart duration back to
8558 // the beginning, so we don't infinitely increase the duration
8559 // on a service that just occasionally gets killed (which is
8560 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008561 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008562 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008563 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008564 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008565 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008566 if (r.restartDelay < minDuration) {
8567 r.restartDelay = minDuration;
8568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008569 }
8570 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008571
8572 r.nextRestartTime = now + r.restartDelay;
8573
8574 // Make sure that we don't end up restarting a bunch of services
8575 // all at the same time.
8576 boolean repeat;
8577 do {
8578 repeat = false;
8579 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8580 ServiceRecord r2 = mRestartingServices.get(i);
8581 if (r2 != r && r.nextRestartTime
8582 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8583 && r.nextRestartTime
8584 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8585 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8586 r.restartDelay = r.nextRestartTime - now;
8587 repeat = true;
8588 break;
8589 }
8590 }
8591 } while (repeat);
8592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008593 if (!mRestartingServices.contains(r)) {
8594 mRestartingServices.add(r);
8595 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008596
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008597 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008600 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008601 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008602 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008603 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008604 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008605 r.shortName, r.restartDelay);
8606
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008607 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008608 }
8609
8610 final void performServiceRestartLocked(ServiceRecord r) {
8611 if (!mRestartingServices.contains(r)) {
8612 return;
8613 }
8614 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8615 }
8616
8617 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8618 if (r.restartDelay == 0) {
8619 return false;
8620 }
8621 r.resetRestartCounter();
8622 mRestartingServices.remove(r);
8623 mHandler.removeCallbacks(r.restarter);
8624 return true;
8625 }
8626
8627 private final boolean bringUpServiceLocked(ServiceRecord r,
8628 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008629 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008630 //r.dump(" ");
8631
Dianne Hackborn36124872009-10-08 16:22:03 -07008632 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 sendServiceArgsLocked(r, false);
8634 return true;
8635 }
8636
8637 if (!whileRestarting && r.restartDelay > 0) {
8638 // If waiting for a restart, then do nothing.
8639 return true;
8640 }
8641
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008642 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008644 // We are now bringing the service up, so no longer in the
8645 // restarting state.
8646 mRestartingServices.remove(r);
8647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008648 final String appName = r.processName;
8649 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8650 if (app != null && app.thread != null) {
8651 try {
8652 realStartServiceLocked(r, app);
8653 return true;
8654 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008655 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 }
8657
8658 // If a dead object exception was thrown -- fall through to
8659 // restart the application.
8660 }
8661
Dianne Hackborn36124872009-10-08 16:22:03 -07008662 // Not running -- get it started, and enqueue this service record
8663 // to be executed when the app comes up.
8664 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8665 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008666 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008667 + r.appInfo.packageName + "/"
8668 + r.appInfo.uid + " for service "
8669 + r.intent.getIntent() + ": process is bad");
8670 bringDownServiceLocked(r, true);
8671 return false;
8672 }
8673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008674 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008675 mPendingServices.add(r);
8676 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008678 return true;
8679 }
8680
8681 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008682 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 //r.dump(" ");
8684
8685 // Does it still need to run?
8686 if (!force && r.startRequested) {
8687 return;
8688 }
8689 if (r.connections.size() > 0) {
8690 if (!force) {
8691 // XXX should probably keep a count of the number of auto-create
8692 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008693 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008695 ArrayList<ConnectionRecord> cr = it.next();
8696 for (int i=0; i<cr.size(); i++) {
8697 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8698 return;
8699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008700 }
8701 }
8702 }
8703
8704 // Report to all of the connections that the service is no longer
8705 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008706 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008707 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008708 ArrayList<ConnectionRecord> c = it.next();
8709 for (int i=0; i<c.size(); i++) {
8710 try {
8711 c.get(i).conn.connected(r.name, null);
8712 } catch (Exception e) {
8713 Slog.w(TAG, "Failure disconnecting service " + r.name +
8714 " to connection " + c.get(i).conn.asBinder() +
8715 " (in " + c.get(i).binding.client.processName + ")", e);
8716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 }
8718 }
8719 }
8720
8721 // Tell the service that it has been unbound.
8722 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8723 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8724 while (it.hasNext()) {
8725 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008726 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008727 + ": hasBound=" + ibr.hasBound);
8728 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8729 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008730 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
8731 + " for " + ibr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008732 bumpServiceExecutingLocked(r);
8733 updateOomAdjLocked(r.app);
8734 ibr.hasBound = false;
8735 r.app.thread.scheduleUnbindService(r,
8736 ibr.intent.getIntent());
8737 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008738 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008739 + r.shortName, e);
8740 serviceDoneExecutingLocked(r, true);
8741 }
8742 }
8743 }
8744 }
8745
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008746 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008747 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008748 System.identityHashCode(r), r.shortName,
8749 (r.app != null) ? r.app.pid : -1);
8750
8751 mServices.remove(r.name);
8752 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008753 r.totalRestartCount = 0;
8754 unscheduleServiceRestartLocked(r);
8755
8756 // Also make sure it is not on the pending list.
8757 int N = mPendingServices.size();
8758 for (int i=0; i<N; i++) {
8759 if (mPendingServices.get(i) == r) {
8760 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008761 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008762 i--;
8763 N--;
8764 }
8765 }
8766
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008767 r.cancelNotification();
8768 r.isForeground = false;
8769 r.foregroundId = 0;
8770 r.foregroundNoti = null;
8771
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008772 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008773 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008774 r.pendingStarts.clear();
8775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008776 if (r.app != null) {
8777 synchronized (r.stats.getBatteryStats()) {
8778 r.stats.stopLaunchedLocked();
8779 }
8780 r.app.services.remove(r);
8781 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008783 if (DEBUG_SERVICE) {
8784 RuntimeException here = new RuntimeException();
8785 here.fillInStackTrace();
8786 Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
8787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 bumpServiceExecutingLocked(r);
8789 mStoppingServices.add(r);
8790 updateOomAdjLocked(r.app);
8791 r.app.thread.scheduleStopService(r);
8792 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008793 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 + r.shortName, e);
8795 serviceDoneExecutingLocked(r, true);
8796 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008797 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008798 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008799 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008800 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008801 }
8802 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008803 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008804 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008805 }
8806 }
8807
8808 ComponentName startServiceLocked(IApplicationThread caller,
8809 Intent service, String resolvedType,
8810 int callingPid, int callingUid) {
8811 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008812 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 + " type=" + resolvedType + " args=" + service.getExtras());
8814
8815 if (caller != null) {
8816 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8817 if (callerApp == null) {
8818 throw new SecurityException(
8819 "Unable to find app for caller " + caller
8820 + " (pid=" + Binder.getCallingPid()
8821 + ") when starting service " + service);
8822 }
8823 }
8824
8825 ServiceLookupResult res =
8826 retrieveServiceLocked(service, resolvedType,
8827 callingPid, callingUid);
8828 if (res == null) {
8829 return null;
8830 }
8831 if (res.record == null) {
8832 return new ComponentName("!", res.permission != null
8833 ? res.permission : "private to package");
8834 }
8835 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07008836 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
8837 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008839 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008840 }
8841 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008842 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008843 r.lastStartId++;
8844 if (r.lastStartId < 1) {
8845 r.lastStartId = 1;
8846 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008847 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
8848 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 r.lastActivity = SystemClock.uptimeMillis();
8850 synchronized (r.stats.getBatteryStats()) {
8851 r.stats.startRunningLocked();
8852 }
8853 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8854 return new ComponentName("!", "Service process is bad");
8855 }
8856 return r.name;
8857 }
8858 }
8859
8860 public ComponentName startService(IApplicationThread caller, Intent service,
8861 String resolvedType) {
8862 // Refuse possible leaked file descriptors
8863 if (service != null && service.hasFileDescriptors() == true) {
8864 throw new IllegalArgumentException("File descriptors passed in Intent");
8865 }
8866
8867 synchronized(this) {
8868 final int callingPid = Binder.getCallingPid();
8869 final int callingUid = Binder.getCallingUid();
8870 final long origId = Binder.clearCallingIdentity();
8871 ComponentName res = startServiceLocked(caller, service,
8872 resolvedType, callingPid, callingUid);
8873 Binder.restoreCallingIdentity(origId);
8874 return res;
8875 }
8876 }
8877
8878 ComponentName startServiceInPackage(int uid,
8879 Intent service, String resolvedType) {
8880 synchronized(this) {
8881 final long origId = Binder.clearCallingIdentity();
8882 ComponentName res = startServiceLocked(null, service,
8883 resolvedType, -1, uid);
8884 Binder.restoreCallingIdentity(origId);
8885 return res;
8886 }
8887 }
8888
8889 public int stopService(IApplicationThread caller, Intent service,
8890 String resolvedType) {
8891 // Refuse possible leaked file descriptors
8892 if (service != null && service.hasFileDescriptors() == true) {
8893 throw new IllegalArgumentException("File descriptors passed in Intent");
8894 }
8895
8896 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008897 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008898 + " type=" + resolvedType);
8899
8900 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8901 if (caller != null && callerApp == null) {
8902 throw new SecurityException(
8903 "Unable to find app for caller " + caller
8904 + " (pid=" + Binder.getCallingPid()
8905 + ") when stopping service " + service);
8906 }
8907
8908 // If this service is active, make sure it is stopped.
8909 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8910 if (r != null) {
8911 if (r.record != null) {
8912 synchronized (r.record.stats.getBatteryStats()) {
8913 r.record.stats.stopRunningLocked();
8914 }
8915 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008916 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 final long origId = Binder.clearCallingIdentity();
8918 bringDownServiceLocked(r.record, false);
8919 Binder.restoreCallingIdentity(origId);
8920 return 1;
8921 }
8922 return -1;
8923 }
8924 }
8925
8926 return 0;
8927 }
8928
8929 public IBinder peekService(Intent service, String resolvedType) {
8930 // Refuse possible leaked file descriptors
8931 if (service != null && service.hasFileDescriptors() == true) {
8932 throw new IllegalArgumentException("File descriptors passed in Intent");
8933 }
8934
8935 IBinder ret = null;
8936
8937 synchronized(this) {
8938 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8939
8940 if (r != null) {
8941 // r.record is null if findServiceLocked() failed the caller permission check
8942 if (r.record == null) {
8943 throw new SecurityException(
8944 "Permission Denial: Accessing service " + r.record.name
8945 + " from pid=" + Binder.getCallingPid()
8946 + ", uid=" + Binder.getCallingUid()
8947 + " requires " + r.permission);
8948 }
8949 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8950 if (ib != null) {
8951 ret = ib.binder;
8952 }
8953 }
8954 }
8955
8956 return ret;
8957 }
8958
8959 public boolean stopServiceToken(ComponentName className, IBinder token,
8960 int startId) {
8961 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008962 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008963 + " " + token + " startId=" + startId);
8964 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008965 if (r != null) {
8966 if (startId >= 0) {
8967 // Asked to only stop if done with all work. Note that
8968 // to avoid leaks, we will take this as dropping all
8969 // start items up to and including this one.
8970 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8971 if (si != null) {
8972 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008973 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
8974 cur.removeUriPermissionsLocked();
8975 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008976 break;
8977 }
8978 }
8979 }
8980
8981 if (r.lastStartId != startId) {
8982 return false;
8983 }
8984
8985 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008986 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008987 + " is last, but have " + r.deliveredStarts.size()
8988 + " remaining args");
8989 }
8990 }
8991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008992 synchronized (r.stats.getBatteryStats()) {
8993 r.stats.stopRunningLocked();
8994 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008995 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 }
8997 final long origId = Binder.clearCallingIdentity();
8998 bringDownServiceLocked(r, false);
8999 Binder.restoreCallingIdentity(origId);
9000 return true;
9001 }
9002 }
9003 return false;
9004 }
9005
9006 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009007 int id, Notification notification, boolean removeNotification) {
9008 final long origId = Binder.clearCallingIdentity();
9009 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009010 synchronized(this) {
9011 ServiceRecord r = findServiceLocked(className, token);
9012 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009013 if (id != 0) {
9014 if (notification == null) {
9015 throw new IllegalArgumentException("null notification");
9016 }
9017 if (r.foregroundId != id) {
9018 r.cancelNotification();
9019 r.foregroundId = id;
9020 }
9021 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9022 r.foregroundNoti = notification;
9023 r.isForeground = true;
9024 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009025 if (r.app != null) {
9026 updateServiceForegroundLocked(r.app, true);
9027 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009028 } else {
9029 if (r.isForeground) {
9030 r.isForeground = false;
9031 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009032 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009033 updateServiceForegroundLocked(r.app, true);
9034 }
9035 }
9036 if (removeNotification) {
9037 r.cancelNotification();
9038 r.foregroundId = 0;
9039 r.foregroundNoti = null;
9040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 }
9042 }
9043 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009044 } finally {
9045 Binder.restoreCallingIdentity(origId);
9046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009047 }
9048
9049 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9050 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009051 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009052 if (sr.isForeground) {
9053 anyForeground = true;
9054 break;
9055 }
9056 }
9057 if (anyForeground != proc.foregroundServices) {
9058 proc.foregroundServices = anyForeground;
9059 if (oomAdj) {
9060 updateOomAdjLocked();
9061 }
9062 }
9063 }
9064
9065 public int bindService(IApplicationThread caller, IBinder token,
9066 Intent service, String resolvedType,
9067 IServiceConnection connection, int flags) {
9068 // Refuse possible leaked file descriptors
9069 if (service != null && service.hasFileDescriptors() == true) {
9070 throw new IllegalArgumentException("File descriptors passed in Intent");
9071 }
9072
9073 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009074 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009075 + " type=" + resolvedType + " conn=" + connection.asBinder()
9076 + " flags=0x" + Integer.toHexString(flags));
9077 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9078 if (callerApp == null) {
9079 throw new SecurityException(
9080 "Unable to find app for caller " + caller
9081 + " (pid=" + Binder.getCallingPid()
9082 + ") when binding service " + service);
9083 }
9084
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009085 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009087 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009089 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009090 return 0;
9091 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009092 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009093 }
9094
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009095 int clientLabel = 0;
9096 PendingIntent clientIntent = null;
9097
9098 if (callerApp.info.uid == Process.SYSTEM_UID) {
9099 // Hacky kind of thing -- allow system stuff to tell us
9100 // what they are, so we can report this elsewhere for
9101 // others to know why certain services are running.
9102 try {
9103 clientIntent = (PendingIntent)service.getParcelableExtra(
9104 Intent.EXTRA_CLIENT_INTENT);
9105 } catch (RuntimeException e) {
9106 }
9107 if (clientIntent != null) {
9108 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9109 if (clientLabel != 0) {
9110 // There are no useful extras in the intent, trash them.
9111 // System code calling with this stuff just needs to know
9112 // this will happen.
9113 service = service.cloneFilter();
9114 }
9115 }
9116 }
9117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118 ServiceLookupResult res =
9119 retrieveServiceLocked(service, resolvedType,
9120 Binder.getCallingPid(), Binder.getCallingUid());
9121 if (res == null) {
9122 return 0;
9123 }
9124 if (res.record == null) {
9125 return -1;
9126 }
9127 ServiceRecord s = res.record;
9128
9129 final long origId = Binder.clearCallingIdentity();
9130
9131 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009132 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009133 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009134 }
9135
9136 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9137 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009138 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009139
9140 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009141 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9142 if (clist == null) {
9143 clist = new ArrayList<ConnectionRecord>();
9144 s.connections.put(binder, clist);
9145 }
9146 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 b.connections.add(c);
9148 if (activity != null) {
9149 if (activity.connections == null) {
9150 activity.connections = new HashSet<ConnectionRecord>();
9151 }
9152 activity.connections.add(c);
9153 }
9154 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009155 clist = mServiceConnections.get(binder);
9156 if (clist == null) {
9157 clist = new ArrayList<ConnectionRecord>();
9158 mServiceConnections.put(binder, clist);
9159 }
9160 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009161
9162 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9163 s.lastActivity = SystemClock.uptimeMillis();
9164 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9165 return 0;
9166 }
9167 }
9168
9169 if (s.app != null) {
9170 // This could have made the service more important.
9171 updateOomAdjLocked(s.app);
9172 }
9173
Joe Onorato8a9b2202010-02-26 18:56:32 -08009174 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009175 + ": received=" + b.intent.received
9176 + " apps=" + b.intent.apps.size()
9177 + " doRebind=" + b.intent.doRebind);
9178
9179 if (s.app != null && b.intent.received) {
9180 // Service is already running, so we can immediately
9181 // publish the connection.
9182 try {
9183 c.conn.connected(s.name, b.intent.binder);
9184 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009185 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 + " to connection " + c.conn.asBinder()
9187 + " (in " + c.binding.client.processName + ")", e);
9188 }
9189
9190 // If this is the first app connected back to this binding,
9191 // and the service had previously asked to be told when
9192 // rebound, then do so.
9193 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9194 requestServiceBindingLocked(s, b.intent, true);
9195 }
9196 } else if (!b.intent.requested) {
9197 requestServiceBindingLocked(s, b.intent, false);
9198 }
9199
9200 Binder.restoreCallingIdentity(origId);
9201 }
9202
9203 return 1;
9204 }
9205
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009206 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009207 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009208 IBinder binder = c.conn.asBinder();
9209 AppBindRecord b = c.binding;
9210 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009211 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9212 if (clist != null) {
9213 clist.remove(c);
9214 if (clist.size() == 0) {
9215 s.connections.remove(binder);
9216 }
9217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 b.connections.remove(c);
9219 if (c.activity != null && c.activity != skipAct) {
9220 if (c.activity.connections != null) {
9221 c.activity.connections.remove(c);
9222 }
9223 }
9224 if (b.client != skipApp) {
9225 b.client.connections.remove(c);
9226 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009227 clist = mServiceConnections.get(binder);
9228 if (clist != null) {
9229 clist.remove(c);
9230 if (clist.size() == 0) {
9231 mServiceConnections.remove(binder);
9232 }
9233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009234
9235 if (b.connections.size() == 0) {
9236 b.intent.apps.remove(b.client);
9237 }
9238
Joe Onorato8a9b2202010-02-26 18:56:32 -08009239 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 + ": shouldUnbind=" + b.intent.hasBound);
9241 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9242 && b.intent.hasBound) {
9243 try {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009244 if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
9245 + " from " + b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009246 bumpServiceExecutingLocked(s);
9247 updateOomAdjLocked(s.app);
9248 b.intent.hasBound = false;
9249 // Assume the client doesn't want to know about a rebind;
9250 // we will deal with that later if it asks for one.
9251 b.intent.doRebind = false;
9252 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9253 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009254 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009255 serviceDoneExecutingLocked(s, true);
9256 }
9257 }
9258
9259 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9260 bringDownServiceLocked(s, false);
9261 }
9262 }
9263
9264 public boolean unbindService(IServiceConnection connection) {
9265 synchronized (this) {
9266 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009267 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009268 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9269 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009270 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 + connection.asBinder());
9272 return false;
9273 }
9274
9275 final long origId = Binder.clearCallingIdentity();
9276
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009277 while (clist.size() > 0) {
9278 ConnectionRecord r = clist.get(0);
9279 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009280
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009281 if (r.binding.service.app != null) {
9282 // This could have made the service less important.
9283 updateOomAdjLocked(r.binding.service.app);
9284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 }
9286
9287 Binder.restoreCallingIdentity(origId);
9288 }
9289
9290 return true;
9291 }
9292
9293 public void publishService(IBinder token, Intent intent, IBinder service) {
9294 // Refuse possible leaked file descriptors
9295 if (intent != null && intent.hasFileDescriptors() == true) {
9296 throw new IllegalArgumentException("File descriptors passed in Intent");
9297 }
9298
9299 synchronized(this) {
9300 if (!(token instanceof ServiceRecord)) {
9301 throw new IllegalArgumentException("Invalid service token");
9302 }
9303 ServiceRecord r = (ServiceRecord)token;
9304
9305 final long origId = Binder.clearCallingIdentity();
9306
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009307 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 + " " + intent + ": " + service);
9309 if (r != null) {
9310 Intent.FilterComparison filter
9311 = new Intent.FilterComparison(intent);
9312 IntentBindRecord b = r.bindings.get(filter);
9313 if (b != null && !b.received) {
9314 b.binder = service;
9315 b.requested = true;
9316 b.received = true;
9317 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009318 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009319 = r.connections.values().iterator();
9320 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009321 ArrayList<ConnectionRecord> clist = it.next();
9322 for (int i=0; i<clist.size(); i++) {
9323 ConnectionRecord c = clist.get(i);
9324 if (!filter.equals(c.binding.intent.intent)) {
9325 if (DEBUG_SERVICE) Slog.v(
9326 TAG, "Not publishing to: " + c);
9327 if (DEBUG_SERVICE) Slog.v(
9328 TAG, "Bound intent: " + c.binding.intent.intent);
9329 if (DEBUG_SERVICE) Slog.v(
9330 TAG, "Published intent: " + intent);
9331 continue;
9332 }
9333 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9334 try {
9335 c.conn.connected(r.name, service);
9336 } catch (Exception e) {
9337 Slog.w(TAG, "Failure sending service " + r.name +
9338 " to connection " + c.conn.asBinder() +
9339 " (in " + c.binding.client.processName + ")", e);
9340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009341 }
9342 }
9343 }
9344 }
9345
9346 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9347
9348 Binder.restoreCallingIdentity(origId);
9349 }
9350 }
9351 }
9352
9353 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9354 // Refuse possible leaked file descriptors
9355 if (intent != null && intent.hasFileDescriptors() == true) {
9356 throw new IllegalArgumentException("File descriptors passed in Intent");
9357 }
9358
9359 synchronized(this) {
9360 if (!(token instanceof ServiceRecord)) {
9361 throw new IllegalArgumentException("Invalid service token");
9362 }
9363 ServiceRecord r = (ServiceRecord)token;
9364
9365 final long origId = Binder.clearCallingIdentity();
9366
9367 if (r != null) {
9368 Intent.FilterComparison filter
9369 = new Intent.FilterComparison(intent);
9370 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009371 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009372 + " at " + b + ": apps="
9373 + (b != null ? b.apps.size() : 0));
9374 if (b != null) {
9375 if (b.apps.size() > 0) {
9376 // Applications have already bound since the last
9377 // unbind, so just rebind right here.
9378 requestServiceBindingLocked(r, b, true);
9379 } else {
9380 // Note to tell the service the next time there is
9381 // a new client.
9382 b.doRebind = true;
9383 }
9384 }
9385
9386 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9387
9388 Binder.restoreCallingIdentity(origId);
9389 }
9390 }
9391 }
9392
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009393 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 synchronized(this) {
9395 if (!(token instanceof ServiceRecord)) {
9396 throw new IllegalArgumentException("Invalid service token");
9397 }
9398 ServiceRecord r = (ServiceRecord)token;
9399 boolean inStopping = mStoppingServices.contains(token);
9400 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009401 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009402 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009403 + " with incorrect token: given " + token
9404 + ", expected " + r);
9405 return;
9406 }
9407
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009408 if (type == 1) {
9409 // This is a call from a service start... take care of
9410 // book-keeping.
9411 r.callStart = true;
9412 switch (res) {
9413 case Service.START_STICKY_COMPATIBILITY:
9414 case Service.START_STICKY: {
9415 // We are done with the associated start arguments.
9416 r.findDeliveredStart(startId, true);
9417 // Don't stop if killed.
9418 r.stopIfKilled = false;
9419 break;
9420 }
9421 case Service.START_NOT_STICKY: {
9422 // We are done with the associated start arguments.
9423 r.findDeliveredStart(startId, true);
9424 if (r.lastStartId == startId) {
9425 // There is no more work, and this service
9426 // doesn't want to hang around if killed.
9427 r.stopIfKilled = true;
9428 }
9429 break;
9430 }
9431 case Service.START_REDELIVER_INTENT: {
9432 // We'll keep this item until they explicitly
9433 // call stop for it, but keep track of the fact
9434 // that it was delivered.
9435 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9436 if (si != null) {
9437 si.deliveryCount = 0;
9438 si.doneExecutingCount++;
9439 // Don't stop if killed.
9440 r.stopIfKilled = true;
9441 }
9442 break;
9443 }
9444 default:
9445 throw new IllegalArgumentException(
9446 "Unknown service start result: " + res);
9447 }
9448 if (res == Service.START_STICKY_COMPATIBILITY) {
9449 r.callStart = false;
9450 }
9451 }
9452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009453 final long origId = Binder.clearCallingIdentity();
9454 serviceDoneExecutingLocked(r, inStopping);
9455 Binder.restoreCallingIdentity(origId);
9456 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009457 Slog.w(TAG, "Done executing unknown service from pid "
9458 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009459 }
9460 }
9461 }
9462
9463 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009464 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9465 + ": nesting=" + r.executeNesting
9466 + ", inStopping=" + inStopping + ", app=" + r.app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009467 r.executeNesting--;
9468 if (r.executeNesting <= 0 && r.app != null) {
9469 r.app.executingServices.remove(r);
9470 if (r.app.executingServices.size() == 0) {
9471 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9472 }
9473 if (inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009474 if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009475 mStoppingServices.remove(r);
9476 }
9477 updateOomAdjLocked(r.app);
9478 }
9479 }
9480
9481 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009482 String anrMessage = null;
9483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 synchronized(this) {
9485 if (proc.executingServices.size() == 0 || proc.thread == null) {
9486 return;
9487 }
9488 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9489 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9490 ServiceRecord timeout = null;
9491 long nextTime = 0;
9492 while (it.hasNext()) {
9493 ServiceRecord sr = it.next();
9494 if (sr.executingStart < maxTime) {
9495 timeout = sr;
9496 break;
9497 }
9498 if (sr.executingStart > nextTime) {
9499 nextTime = sr.executingStart;
9500 }
9501 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009502 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009503 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009504 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009505 } else {
9506 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9507 msg.obj = proc;
9508 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9509 }
9510 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009511
9512 if (anrMessage != null) {
9513 appNotResponding(proc, null, null, anrMessage);
9514 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009515 }
9516
9517 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009518 // BACKUP AND RESTORE
9519 // =========================================================
9520
9521 // Cause the target app to be launched if necessary and its backup agent
9522 // instantiated. The backup agent will invoke backupAgentCreated() on the
9523 // activity manager to announce its creation.
9524 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009525 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009526 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9527
9528 synchronized(this) {
9529 // !!! TODO: currently no check here that we're already bound
9530 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9531 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9532 synchronized (stats) {
9533 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9534 }
9535
9536 BackupRecord r = new BackupRecord(ss, app, backupMode);
9537 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9538 // startProcessLocked() returns existing proc's record if it's already running
9539 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009540 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009541 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009542 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009543 return false;
9544 }
9545
9546 r.app = proc;
9547 mBackupTarget = r;
9548 mBackupAppName = app.packageName;
9549
Christopher Tate6fa95972009-06-05 18:43:55 -07009550 // Try not to kill the process during backup
9551 updateOomAdjLocked(proc);
9552
Christopher Tate181fafa2009-05-14 11:12:14 -07009553 // If the process is already attached, schedule the creation of the backup agent now.
9554 // If it is not yet live, this will be done when it attaches to the framework.
9555 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009556 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009557 try {
9558 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9559 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009560 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009561 }
9562 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009563 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009564 }
9565 // Invariants: at this point, the target app process exists and the application
9566 // is either already running or in the process of coming up. mBackupTarget and
9567 // mBackupAppName describe the app, so that when it binds back to the AM we
9568 // know that it's scheduled for a backup-agent operation.
9569 }
9570
9571 return true;
9572 }
9573
9574 // A backup agent has just come up
9575 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009576 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009577 + " = " + agent);
9578
9579 synchronized(this) {
9580 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009581 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009582 return;
9583 }
9584
Christopher Tate043dadc2009-06-02 16:11:00 -07009585 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009586 try {
9587 IBackupManager bm = IBackupManager.Stub.asInterface(
9588 ServiceManager.getService(Context.BACKUP_SERVICE));
9589 bm.agentConnected(agentPackageName, agent);
9590 } catch (RemoteException e) {
9591 // can't happen; the backup manager service is local
9592 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009593 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009594 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009595 } finally {
9596 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009597 }
9598 }
9599 }
9600
9601 // done with this agent
9602 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009603 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009604 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009605 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009606 return;
9607 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009608
9609 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009610 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009611 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009612 return;
9613 }
9614
Christopher Tate181fafa2009-05-14 11:12:14 -07009615 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009616 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009617 return;
9618 }
9619
Christopher Tate6fa95972009-06-05 18:43:55 -07009620 ProcessRecord proc = mBackupTarget.app;
9621 mBackupTarget = null;
9622 mBackupAppName = null;
9623
9624 // Not backing this app up any more; reset its OOM adjustment
9625 updateOomAdjLocked(proc);
9626
Christopher Tatec7b31e32009-06-10 15:49:30 -07009627 // If the app crashed during backup, 'thread' will be null here
9628 if (proc.thread != null) {
9629 try {
9630 proc.thread.scheduleDestroyBackupAgent(appInfo);
9631 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009632 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009633 e.printStackTrace();
9634 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009635 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009636 }
9637 }
9638 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009639 // BROADCASTS
9640 // =========================================================
9641
Josh Bartel7f208742010-02-25 11:01:44 -06009642 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 List cur) {
9644 final ContentResolver resolver = mContext.getContentResolver();
9645 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9646 if (list == null) {
9647 return cur;
9648 }
9649 int N = list.size();
9650 for (int i=0; i<N; i++) {
9651 Intent intent = list.get(i);
9652 if (filter.match(resolver, intent, true, TAG) >= 0) {
9653 if (cur == null) {
9654 cur = new ArrayList<Intent>();
9655 }
9656 cur.add(intent);
9657 }
9658 }
9659 return cur;
9660 }
9661
9662 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009663 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 + mBroadcastsScheduled);
9665
9666 if (mBroadcastsScheduled) {
9667 return;
9668 }
9669 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9670 mBroadcastsScheduled = true;
9671 }
9672
9673 public Intent registerReceiver(IApplicationThread caller,
9674 IIntentReceiver receiver, IntentFilter filter, String permission) {
9675 synchronized(this) {
9676 ProcessRecord callerApp = null;
9677 if (caller != null) {
9678 callerApp = getRecordForAppLocked(caller);
9679 if (callerApp == null) {
9680 throw new SecurityException(
9681 "Unable to find app for caller " + caller
9682 + " (pid=" + Binder.getCallingPid()
9683 + ") when registering receiver " + receiver);
9684 }
9685 }
9686
9687 List allSticky = null;
9688
9689 // Look for any matching sticky broadcasts...
9690 Iterator actions = filter.actionsIterator();
9691 if (actions != null) {
9692 while (actions.hasNext()) {
9693 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009694 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009695 }
9696 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009697 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009698 }
9699
9700 // The first sticky in the list is returned directly back to
9701 // the client.
9702 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9703
Joe Onorato8a9b2202010-02-26 18:56:32 -08009704 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009705 + ": " + sticky);
9706
9707 if (receiver == null) {
9708 return sticky;
9709 }
9710
9711 ReceiverList rl
9712 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9713 if (rl == null) {
9714 rl = new ReceiverList(this, callerApp,
9715 Binder.getCallingPid(),
9716 Binder.getCallingUid(), receiver);
9717 if (rl.app != null) {
9718 rl.app.receivers.add(rl);
9719 } else {
9720 try {
9721 receiver.asBinder().linkToDeath(rl, 0);
9722 } catch (RemoteException e) {
9723 return sticky;
9724 }
9725 rl.linkedToDeath = true;
9726 }
9727 mRegisteredReceivers.put(receiver.asBinder(), rl);
9728 }
9729 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9730 rl.add(bf);
9731 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009732 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009733 }
9734 mReceiverResolver.addFilter(bf);
9735
9736 // Enqueue broadcasts for all existing stickies that match
9737 // this filter.
9738 if (allSticky != null) {
9739 ArrayList receivers = new ArrayList();
9740 receivers.add(bf);
9741
9742 int N = allSticky.size();
9743 for (int i=0; i<N; i++) {
9744 Intent intent = (Intent)allSticky.get(i);
9745 BroadcastRecord r = new BroadcastRecord(intent, null,
9746 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009747 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009748 if (mParallelBroadcasts.size() == 0) {
9749 scheduleBroadcastsLocked();
9750 }
9751 mParallelBroadcasts.add(r);
9752 }
9753 }
9754
9755 return sticky;
9756 }
9757 }
9758
9759 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009760 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009761
9762 boolean doNext = false;
9763
9764 synchronized(this) {
9765 ReceiverList rl
9766 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9767 if (rl != null) {
9768 if (rl.curBroadcast != null) {
9769 BroadcastRecord r = rl.curBroadcast;
9770 doNext = finishReceiverLocked(
9771 receiver.asBinder(), r.resultCode, r.resultData,
9772 r.resultExtras, r.resultAbort, true);
9773 }
9774
9775 if (rl.app != null) {
9776 rl.app.receivers.remove(rl);
9777 }
9778 removeReceiverLocked(rl);
9779 if (rl.linkedToDeath) {
9780 rl.linkedToDeath = false;
9781 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9782 }
9783 }
9784 }
9785
9786 if (!doNext) {
9787 return;
9788 }
9789
9790 final long origId = Binder.clearCallingIdentity();
9791 processNextBroadcast(false);
9792 trimApplications();
9793 Binder.restoreCallingIdentity(origId);
9794 }
9795
9796 void removeReceiverLocked(ReceiverList rl) {
9797 mRegisteredReceivers.remove(rl.receiver.asBinder());
9798 int N = rl.size();
9799 for (int i=0; i<N; i++) {
9800 mReceiverResolver.removeFilter(rl.get(i));
9801 }
9802 }
9803
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009804 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9805 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9806 ProcessRecord r = mLruProcesses.get(i);
9807 if (r.thread != null) {
9808 try {
9809 r.thread.dispatchPackageBroadcast(cmd, packages);
9810 } catch (RemoteException ex) {
9811 }
9812 }
9813 }
9814 }
9815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009816 private final int broadcastIntentLocked(ProcessRecord callerApp,
9817 String callerPackage, Intent intent, String resolvedType,
9818 IIntentReceiver resultTo, int resultCode, String resultData,
9819 Bundle map, String requiredPermission,
9820 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9821 intent = new Intent(intent);
9822
Joe Onorato8a9b2202010-02-26 18:56:32 -08009823 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9825 + " ordered=" + ordered);
9826 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009827 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009828 }
9829
9830 // Handle special intents: if this broadcast is from the package
9831 // manager about a package being removed, we need to remove all of
9832 // its activities from the history stack.
9833 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9834 intent.getAction());
9835 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9836 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009837 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009838 || uidRemoved) {
9839 if (checkComponentPermission(
9840 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9841 callingPid, callingUid, -1)
9842 == PackageManager.PERMISSION_GRANTED) {
9843 if (uidRemoved) {
9844 final Bundle intentExtras = intent.getExtras();
9845 final int uid = intentExtras != null
9846 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9847 if (uid >= 0) {
9848 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9849 synchronized (bs) {
9850 bs.removeUidStatsLocked(uid);
9851 }
9852 }
9853 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009854 // If resources are unvailble just force stop all
9855 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009856 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009857 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9858 if (list != null && (list.length > 0)) {
9859 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009860 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009861 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009862 sendPackageBroadcastLocked(
9863 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009864 }
9865 } else {
9866 Uri data = intent.getData();
9867 String ssp;
9868 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9869 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9870 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009871 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009872 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009873 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9874 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9875 new String[] {ssp});
9876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 }
9878 }
9879 }
9880 } else {
9881 String msg = "Permission Denial: " + intent.getAction()
9882 + " broadcast from " + callerPackage + " (pid=" + callingPid
9883 + ", uid=" + callingUid + ")"
9884 + " requires "
9885 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009886 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009887 throw new SecurityException(msg);
9888 }
9889 }
9890
9891 /*
9892 * If this is the time zone changed action, queue up a message that will reset the timezone
9893 * of all currently running processes. This message will get queued up before the broadcast
9894 * happens.
9895 */
9896 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9897 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9898 }
9899
Dianne Hackborn854060af2009-07-09 18:14:31 -07009900 /*
9901 * Prevent non-system code (defined here to be non-persistent
9902 * processes) from sending protected broadcasts.
9903 */
9904 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9905 || callingUid == Process.SHELL_UID || callingUid == 0) {
9906 // Always okay.
9907 } else if (callerApp == null || !callerApp.persistent) {
9908 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009909 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009910 intent.getAction())) {
9911 String msg = "Permission Denial: not allowed to send broadcast "
9912 + intent.getAction() + " from pid="
9913 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009914 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009915 throw new SecurityException(msg);
9916 }
9917 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009918 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009919 return BROADCAST_SUCCESS;
9920 }
9921 }
9922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009923 // Add to the sticky list if requested.
9924 if (sticky) {
9925 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9926 callingPid, callingUid)
9927 != PackageManager.PERMISSION_GRANTED) {
9928 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9929 + callingPid + ", uid=" + callingUid
9930 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009931 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009932 throw new SecurityException(msg);
9933 }
9934 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009935 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009936 + " and enforce permission " + requiredPermission);
9937 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9938 }
9939 if (intent.getComponent() != null) {
9940 throw new SecurityException(
9941 "Sticky broadcasts can't target a specific component");
9942 }
9943 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9944 if (list == null) {
9945 list = new ArrayList<Intent>();
9946 mStickyBroadcasts.put(intent.getAction(), list);
9947 }
9948 int N = list.size();
9949 int i;
9950 for (i=0; i<N; i++) {
9951 if (intent.filterEquals(list.get(i))) {
9952 // This sticky already exists, replace it.
9953 list.set(i, new Intent(intent));
9954 break;
9955 }
9956 }
9957 if (i >= N) {
9958 list.add(new Intent(intent));
9959 }
9960 }
9961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 // Figure out who all will receive this broadcast.
9963 List receivers = null;
9964 List<BroadcastFilter> registeredReceivers = null;
9965 try {
9966 if (intent.getComponent() != null) {
9967 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009968 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009969 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009970 if (ai != null) {
9971 receivers = new ArrayList();
9972 ResolveInfo ri = new ResolveInfo();
9973 ri.activityInfo = ai;
9974 receivers.add(ri);
9975 }
9976 } else {
9977 // Need to resolve the intent to interested receivers...
9978 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9979 == 0) {
9980 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009981 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009982 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009983 }
Mihai Preda074edef2009-05-18 17:13:31 +02009984 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009985 }
9986 } catch (RemoteException ex) {
9987 // pm is in same process, this will never happen.
9988 }
9989
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009990 final boolean replacePending =
9991 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9992
Joe Onorato8a9b2202010-02-26 18:56:32 -08009993 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009994 + " replacePending=" + replacePending);
9995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009996 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9997 if (!ordered && NR > 0) {
9998 // If we are not serializing this broadcast, then send the
9999 // registered receivers separately so they don't wait for the
10000 // components to be launched.
10001 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10002 callerPackage, callingPid, callingUid, requiredPermission,
10003 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010004 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010005 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 TAG, "Enqueueing parallel broadcast " + r
10007 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010008 boolean replaced = false;
10009 if (replacePending) {
10010 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10011 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010012 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010013 "***** DROPPING PARALLEL: " + intent);
10014 mParallelBroadcasts.set(i, r);
10015 replaced = true;
10016 break;
10017 }
10018 }
10019 }
10020 if (!replaced) {
10021 mParallelBroadcasts.add(r);
10022 scheduleBroadcastsLocked();
10023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010024 registeredReceivers = null;
10025 NR = 0;
10026 }
10027
10028 // Merge into one list.
10029 int ir = 0;
10030 if (receivers != null) {
10031 // A special case for PACKAGE_ADDED: do not allow the package
10032 // being added to see this broadcast. This prevents them from
10033 // using this as a back door to get run as soon as they are
10034 // installed. Maybe in the future we want to have a special install
10035 // broadcast or such for apps, but we'd like to deliberately make
10036 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010037 String skipPackages[] = null;
10038 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10039 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10040 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10041 Uri data = intent.getData();
10042 if (data != null) {
10043 String pkgName = data.getSchemeSpecificPart();
10044 if (pkgName != null) {
10045 skipPackages = new String[] { pkgName };
10046 }
10047 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010048 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010049 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010050 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010051 if (skipPackages != null && (skipPackages.length > 0)) {
10052 for (String skipPackage : skipPackages) {
10053 if (skipPackage != null) {
10054 int NT = receivers.size();
10055 for (int it=0; it<NT; it++) {
10056 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10057 if (curt.activityInfo.packageName.equals(skipPackage)) {
10058 receivers.remove(it);
10059 it--;
10060 NT--;
10061 }
10062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010063 }
10064 }
10065 }
10066
10067 int NT = receivers != null ? receivers.size() : 0;
10068 int it = 0;
10069 ResolveInfo curt = null;
10070 BroadcastFilter curr = null;
10071 while (it < NT && ir < NR) {
10072 if (curt == null) {
10073 curt = (ResolveInfo)receivers.get(it);
10074 }
10075 if (curr == null) {
10076 curr = registeredReceivers.get(ir);
10077 }
10078 if (curr.getPriority() >= curt.priority) {
10079 // Insert this broadcast record into the final list.
10080 receivers.add(it, curr);
10081 ir++;
10082 curr = null;
10083 it++;
10084 NT++;
10085 } else {
10086 // Skip to the next ResolveInfo in the final list.
10087 it++;
10088 curt = null;
10089 }
10090 }
10091 }
10092 while (ir < NR) {
10093 if (receivers == null) {
10094 receivers = new ArrayList();
10095 }
10096 receivers.add(registeredReceivers.get(ir));
10097 ir++;
10098 }
10099
10100 if ((receivers != null && receivers.size() > 0)
10101 || resultTo != null) {
10102 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10103 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010104 receivers, resultTo, resultCode, resultData, map, ordered,
10105 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010106 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010107 TAG, "Enqueueing ordered broadcast " + r
10108 + ": prev had " + mOrderedBroadcasts.size());
10109 if (DEBUG_BROADCAST) {
10110 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010111 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010113 boolean replaced = false;
10114 if (replacePending) {
10115 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
10116 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010117 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010118 "***** DROPPING ORDERED: " + intent);
10119 mOrderedBroadcasts.set(i, r);
10120 replaced = true;
10121 break;
10122 }
10123 }
10124 }
10125 if (!replaced) {
10126 mOrderedBroadcasts.add(r);
10127 scheduleBroadcastsLocked();
10128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010129 }
10130
10131 return BROADCAST_SUCCESS;
10132 }
10133
10134 public final int broadcastIntent(IApplicationThread caller,
10135 Intent intent, String resolvedType, IIntentReceiver resultTo,
10136 int resultCode, String resultData, Bundle map,
10137 String requiredPermission, boolean serialized, boolean sticky) {
10138 // Refuse possible leaked file descriptors
10139 if (intent != null && intent.hasFileDescriptors() == true) {
10140 throw new IllegalArgumentException("File descriptors passed in Intent");
10141 }
10142
10143 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010144 int flags = intent.getFlags();
10145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146 if (!mSystemReady) {
10147 // if the caller really truly claims to know what they're doing, go
10148 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010149 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10150 intent = new Intent(intent);
10151 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10152 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -080010153 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010154 + " before boot completion");
10155 throw new IllegalStateException("Cannot broadcast before boot completed");
10156 }
10157 }
10158
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010159 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10160 throw new IllegalArgumentException(
10161 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10162 }
10163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010164 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10165 final int callingPid = Binder.getCallingPid();
10166 final int callingUid = Binder.getCallingUid();
10167 final long origId = Binder.clearCallingIdentity();
10168 int res = broadcastIntentLocked(callerApp,
10169 callerApp != null ? callerApp.info.packageName : null,
10170 intent, resolvedType, resultTo,
10171 resultCode, resultData, map, requiredPermission, serialized,
10172 sticky, callingPid, callingUid);
10173 Binder.restoreCallingIdentity(origId);
10174 return res;
10175 }
10176 }
10177
10178 int broadcastIntentInPackage(String packageName, int uid,
10179 Intent intent, String resolvedType, IIntentReceiver resultTo,
10180 int resultCode, String resultData, Bundle map,
10181 String requiredPermission, boolean serialized, boolean sticky) {
10182 synchronized(this) {
10183 final long origId = Binder.clearCallingIdentity();
10184 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10185 resultTo, resultCode, resultData, map, requiredPermission,
10186 serialized, sticky, -1, uid);
10187 Binder.restoreCallingIdentity(origId);
10188 return res;
10189 }
10190 }
10191
10192 public final void unbroadcastIntent(IApplicationThread caller,
10193 Intent intent) {
10194 // Refuse possible leaked file descriptors
10195 if (intent != null && intent.hasFileDescriptors() == true) {
10196 throw new IllegalArgumentException("File descriptors passed in Intent");
10197 }
10198
10199 synchronized(this) {
10200 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10201 != PackageManager.PERMISSION_GRANTED) {
10202 String msg = "Permission Denial: unbroadcastIntent() from pid="
10203 + Binder.getCallingPid()
10204 + ", uid=" + Binder.getCallingUid()
10205 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010206 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010207 throw new SecurityException(msg);
10208 }
10209 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10210 if (list != null) {
10211 int N = list.size();
10212 int i;
10213 for (i=0; i<N; i++) {
10214 if (intent.filterEquals(list.get(i))) {
10215 list.remove(i);
10216 break;
10217 }
10218 }
10219 }
10220 }
10221 }
10222
10223 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10224 String resultData, Bundle resultExtras, boolean resultAbort,
10225 boolean explicit) {
10226 if (mOrderedBroadcasts.size() == 0) {
10227 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010228 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 }
10230 return false;
10231 }
10232 BroadcastRecord r = mOrderedBroadcasts.get(0);
10233 if (r.receiver == null) {
10234 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010235 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 }
10237 return false;
10238 }
10239 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010240 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010241 return false;
10242 }
10243 int state = r.state;
10244 r.state = r.IDLE;
10245 if (state == r.IDLE) {
10246 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010247 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010248 }
10249 }
10250 r.receiver = null;
10251 r.intent.setComponent(null);
10252 if (r.curApp != null) {
10253 r.curApp.curReceiver = null;
10254 }
10255 if (r.curFilter != null) {
10256 r.curFilter.receiverList.curBroadcast = null;
10257 }
10258 r.curFilter = null;
10259 r.curApp = null;
10260 r.curComponent = null;
10261 r.curReceiver = null;
10262 mPendingBroadcast = null;
10263
10264 r.resultCode = resultCode;
10265 r.resultData = resultData;
10266 r.resultExtras = resultExtras;
10267 r.resultAbort = resultAbort;
10268
10269 // We will process the next receiver right now if this is finishing
10270 // an app receiver (which is always asynchronous) or after we have
10271 // come back from calling a receiver.
10272 return state == BroadcastRecord.APP_RECEIVE
10273 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10274 }
10275
10276 public void finishReceiver(IBinder who, int resultCode, String resultData,
10277 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010278 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010279
10280 // Refuse possible leaked file descriptors
10281 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10282 throw new IllegalArgumentException("File descriptors passed in Bundle");
10283 }
10284
10285 boolean doNext;
10286
10287 final long origId = Binder.clearCallingIdentity();
10288
10289 synchronized(this) {
10290 doNext = finishReceiverLocked(
10291 who, resultCode, resultData, resultExtras, resultAbort, true);
10292 }
10293
10294 if (doNext) {
10295 processNextBroadcast(false);
10296 }
10297 trimApplications();
10298
10299 Binder.restoreCallingIdentity(origId);
10300 }
10301
10302 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10303 if (r.nextReceiver > 0) {
10304 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10305 if (curReceiver instanceof BroadcastFilter) {
10306 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010307 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010308 System.identityHashCode(r),
10309 r.intent.getAction(),
10310 r.nextReceiver - 1,
10311 System.identityHashCode(bf));
10312 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010313 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 System.identityHashCode(r),
10315 r.intent.getAction(),
10316 r.nextReceiver - 1,
10317 ((ResolveInfo)curReceiver).toString());
10318 }
10319 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010320 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010321 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010322 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010323 System.identityHashCode(r),
10324 r.intent.getAction(),
10325 r.nextReceiver,
10326 "NONE");
10327 }
10328 }
10329
10330 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010331 ProcessRecord app = null;
10332 String anrMessage = null;
10333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010334 synchronized (this) {
10335 if (mOrderedBroadcasts.size() == 0) {
10336 return;
10337 }
10338 long now = SystemClock.uptimeMillis();
10339 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010340 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010341 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010342 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010343 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010344 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010345 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010346 return;
10347 }
10348
Joe Onorato8a9b2202010-02-26 18:56:32 -080010349 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010350 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010351 r.anrCount++;
10352
10353 // Current receiver has passed its expiration date.
10354 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010355 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010356 return;
10357 }
10358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010359 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010360 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010361 logBroadcastReceiverDiscard(r);
10362 if (curReceiver instanceof BroadcastFilter) {
10363 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10364 if (bf.receiverList.pid != 0
10365 && bf.receiverList.pid != MY_PID) {
10366 synchronized (this.mPidsSelfLocked) {
10367 app = this.mPidsSelfLocked.get(
10368 bf.receiverList.pid);
10369 }
10370 }
10371 } else {
10372 app = r.curApp;
10373 }
10374
10375 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010376 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010377 }
10378
10379 if (mPendingBroadcast == r) {
10380 mPendingBroadcast = null;
10381 }
10382
10383 // Move on to the next receiver.
10384 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10385 r.resultExtras, r.resultAbort, true);
10386 scheduleBroadcastsLocked();
10387 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010388
10389 if (anrMessage != null) {
10390 appNotResponding(app, null, null, anrMessage);
10391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010392 }
10393
10394 private final void processCurBroadcastLocked(BroadcastRecord r,
10395 ProcessRecord app) throws RemoteException {
10396 if (app.thread == null) {
10397 throw new RemoteException();
10398 }
10399 r.receiver = app.thread.asBinder();
10400 r.curApp = app;
10401 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010402 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403
10404 // Tell the application to launch this receiver.
10405 r.intent.setComponent(r.curComponent);
10406
10407 boolean started = false;
10408 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010409 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010410 "Delivering to component " + r.curComponent
10411 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010412 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010413 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10414 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10415 started = true;
10416 } finally {
10417 if (!started) {
10418 r.receiver = null;
10419 r.curApp = null;
10420 app.curReceiver = null;
10421 }
10422 }
10423
10424 }
10425
10426 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010427 Intent intent, int resultCode, String data, Bundle extras,
10428 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010429 if (app != null && app.thread != null) {
10430 // If we have an app thread, do the call through that so it is
10431 // correctly ordered with other one-way calls.
10432 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010433 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010434 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010435 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010436 }
10437 }
10438
10439 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10440 BroadcastFilter filter, boolean ordered) {
10441 boolean skip = false;
10442 if (filter.requiredPermission != null) {
10443 int perm = checkComponentPermission(filter.requiredPermission,
10444 r.callingPid, r.callingUid, -1);
10445 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010446 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010447 + r.intent.toString()
10448 + " from " + r.callerPackage + " (pid="
10449 + r.callingPid + ", uid=" + r.callingUid + ")"
10450 + " requires " + filter.requiredPermission
10451 + " due to registered receiver " + filter);
10452 skip = true;
10453 }
10454 }
10455 if (r.requiredPermission != null) {
10456 int perm = checkComponentPermission(r.requiredPermission,
10457 filter.receiverList.pid, filter.receiverList.uid, -1);
10458 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010459 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 + r.intent.toString()
10461 + " to " + filter.receiverList.app
10462 + " (pid=" + filter.receiverList.pid
10463 + ", uid=" + filter.receiverList.uid + ")"
10464 + " requires " + r.requiredPermission
10465 + " due to sender " + r.callerPackage
10466 + " (uid " + r.callingUid + ")");
10467 skip = true;
10468 }
10469 }
10470
10471 if (!skip) {
10472 // If this is not being sent as an ordered broadcast, then we
10473 // don't want to touch the fields that keep track of the current
10474 // state of ordered broadcasts.
10475 if (ordered) {
10476 r.receiver = filter.receiverList.receiver.asBinder();
10477 r.curFilter = filter;
10478 filter.receiverList.curBroadcast = r;
10479 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010480 if (filter.receiverList.app != null) {
10481 // Bump hosting application to no longer be in background
10482 // scheduling class. Note that we can't do that if there
10483 // isn't an app... but we can only be in that case for
10484 // things that directly call the IActivityManager API, which
10485 // are already core system stuff so don't matter for this.
10486 r.curApp = filter.receiverList.app;
10487 filter.receiverList.app.curReceiver = r;
10488 updateOomAdjLocked();
10489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 }
10491 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010492 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010493 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010494 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010495 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010496 }
10497 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10498 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010499 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 if (ordered) {
10501 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10502 }
10503 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010504 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010505 if (ordered) {
10506 r.receiver = null;
10507 r.curFilter = null;
10508 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010509 if (filter.receiverList.app != null) {
10510 filter.receiverList.app.curReceiver = null;
10511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010512 }
10513 }
10514 }
10515 }
10516
Dianne Hackborn12527f92009-11-11 17:39:50 -080010517 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10518 if (r.callingUid < 0) {
10519 // This was from a registerReceiver() call; ignore it.
10520 return;
10521 }
10522 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10523 MAX_BROADCAST_HISTORY-1);
10524 r.finishTime = SystemClock.uptimeMillis();
10525 mBroadcastHistory[0] = r;
10526 }
10527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 private final void processNextBroadcast(boolean fromMsg) {
10529 synchronized(this) {
10530 BroadcastRecord r;
10531
Joe Onorato8a9b2202010-02-26 18:56:32 -080010532 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010533 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010534 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010535
10536 updateCpuStats();
10537
10538 if (fromMsg) {
10539 mBroadcastsScheduled = false;
10540 }
10541
10542 // First, deliver any non-serialized broadcasts right away.
10543 while (mParallelBroadcasts.size() > 0) {
10544 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010545 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010547 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010548 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010549 for (int i=0; i<N; i++) {
10550 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010551 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010552 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010553 + target + ": " + r);
10554 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10555 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010556 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010557 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010558 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010559 }
10560
10561 // Now take care of the next serialized one...
10562
10563 // If we are waiting for a process to come up to handle the next
10564 // broadcast, then do nothing at this point. Just in case, we
10565 // check that the process we're waiting for still exists.
10566 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010567 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010568 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010569 + mPendingBroadcast.curApp);
10570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010571
10572 boolean isDead;
10573 synchronized (mPidsSelfLocked) {
10574 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10575 }
10576 if (!isDead) {
10577 // It's still alive, so keep waiting
10578 return;
10579 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010580 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 + " died before responding to broadcast");
10582 mPendingBroadcast = null;
10583 }
10584 }
10585
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010586 boolean looped = false;
10587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010588 do {
10589 if (mOrderedBroadcasts.size() == 0) {
10590 // No more broadcasts pending, so all done!
10591 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010592 if (looped) {
10593 // If we had finished the last ordered broadcast, then
10594 // make sure all processes have correct oom and sched
10595 // adjustments.
10596 updateOomAdjLocked();
10597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010598 return;
10599 }
10600 r = mOrderedBroadcasts.get(0);
10601 boolean forceReceive = false;
10602
10603 // Ensure that even if something goes awry with the timeout
10604 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010605 // and continue to make progress.
10606 //
10607 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10608 // receivers don't get executed with with timeouts. They're intended for
10609 // one time heavy lifting after system upgrades and can take
10610 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010612 if (mSystemReady && r.dispatchTime > 0) {
10613 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 if ((numReceivers > 0) &&
10615 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010616 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010617 + " now=" + now
10618 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010619 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 + " intent=" + r.intent
10621 + " numReceivers=" + numReceivers
10622 + " nextReceiver=" + r.nextReceiver
10623 + " state=" + r.state);
10624 broadcastTimeout(); // forcibly finish this broadcast
10625 forceReceive = true;
10626 r.state = BroadcastRecord.IDLE;
10627 }
10628 }
10629
10630 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010631 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 "processNextBroadcast() called when not idle (state="
10633 + r.state + ")");
10634 return;
10635 }
10636
10637 if (r.receivers == null || r.nextReceiver >= numReceivers
10638 || r.resultAbort || forceReceive) {
10639 // No more receivers for this broadcast! Send the final
10640 // result if requested...
10641 if (r.resultTo != null) {
10642 try {
10643 if (DEBUG_BROADCAST) {
10644 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010645 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010646 + " seq=" + seq + " app=" + r.callerApp);
10647 }
10648 performReceive(r.callerApp, r.resultTo,
10649 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010650 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010651 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010652 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010653 }
10654 }
10655
Joe Onorato8a9b2202010-02-26 18:56:32 -080010656 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010657 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10658
Joe Onorato8a9b2202010-02-26 18:56:32 -080010659 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010660 + r);
10661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010662 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010663 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010664 mOrderedBroadcasts.remove(0);
10665 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010666 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 continue;
10668 }
10669 } while (r == null);
10670
10671 // Get the next receiver...
10672 int recIdx = r.nextReceiver++;
10673
10674 // Keep track of when this receiver started, and make sure there
10675 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010676 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010677 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010678 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010679
Joe Onorato8a9b2202010-02-26 18:56:32 -080010680 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010681 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010682 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010683 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010684 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010685 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010686 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010687 }
10688
10689 Object nextReceiver = r.receivers.get(recIdx);
10690 if (nextReceiver instanceof BroadcastFilter) {
10691 // Simple case: this is a registered receiver who gets
10692 // a direct call.
10693 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010694 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010695 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010696 + filter + ": " + r);
10697 deliverToRegisteredReceiver(r, filter, r.ordered);
10698 if (r.receiver == null || !r.ordered) {
10699 // The receiver has already finished, so schedule to
10700 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010701 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10702 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010703 r.state = BroadcastRecord.IDLE;
10704 scheduleBroadcastsLocked();
10705 }
10706 return;
10707 }
10708
10709 // Hard case: need to instantiate the receiver, possibly
10710 // starting its application process to host it.
10711
10712 ResolveInfo info =
10713 (ResolveInfo)nextReceiver;
10714
10715 boolean skip = false;
10716 int perm = checkComponentPermission(info.activityInfo.permission,
10717 r.callingPid, r.callingUid,
10718 info.activityInfo.exported
10719 ? -1 : info.activityInfo.applicationInfo.uid);
10720 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010721 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010722 + r.intent.toString()
10723 + " from " + r.callerPackage + " (pid=" + r.callingPid
10724 + ", uid=" + r.callingUid + ")"
10725 + " requires " + info.activityInfo.permission
10726 + " due to receiver " + info.activityInfo.packageName
10727 + "/" + info.activityInfo.name);
10728 skip = true;
10729 }
10730 if (r.callingUid != Process.SYSTEM_UID &&
10731 r.requiredPermission != null) {
10732 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010733 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010734 checkPermission(r.requiredPermission,
10735 info.activityInfo.applicationInfo.packageName);
10736 } catch (RemoteException e) {
10737 perm = PackageManager.PERMISSION_DENIED;
10738 }
10739 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010740 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010741 + r.intent + " to "
10742 + info.activityInfo.applicationInfo.packageName
10743 + " requires " + r.requiredPermission
10744 + " due to sender " + r.callerPackage
10745 + " (uid " + r.callingUid + ")");
10746 skip = true;
10747 }
10748 }
10749 if (r.curApp != null && r.curApp.crashing) {
10750 // If the target process is crashing, just skip it.
10751 skip = true;
10752 }
10753
10754 if (skip) {
10755 r.receiver = null;
10756 r.curFilter = null;
10757 r.state = BroadcastRecord.IDLE;
10758 scheduleBroadcastsLocked();
10759 return;
10760 }
10761
10762 r.state = BroadcastRecord.APP_RECEIVE;
10763 String targetProcess = info.activityInfo.processName;
10764 r.curComponent = new ComponentName(
10765 info.activityInfo.applicationInfo.packageName,
10766 info.activityInfo.name);
10767 r.curReceiver = info.activityInfo;
10768
10769 // Is this receiver's application already running?
10770 ProcessRecord app = getProcessRecordLocked(targetProcess,
10771 info.activityInfo.applicationInfo.uid);
10772 if (app != null && app.thread != null) {
10773 try {
10774 processCurBroadcastLocked(r, app);
10775 return;
10776 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010777 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 + r.curComponent, e);
10779 }
10780
10781 // If a dead object exception was thrown -- fall through to
10782 // restart the application.
10783 }
10784
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010785 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786 if ((r.curApp=startProcessLocked(targetProcess,
10787 info.activityInfo.applicationInfo, true,
10788 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010789 "broadcast", r.curComponent,
10790 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10791 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010792 // Ah, this recipient is unavailable. Finish it if necessary,
10793 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010794 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010795 + info.activityInfo.applicationInfo.packageName + "/"
10796 + info.activityInfo.applicationInfo.uid + " for broadcast "
10797 + r.intent + ": process is bad");
10798 logBroadcastReceiverDiscard(r);
10799 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10800 r.resultExtras, r.resultAbort, true);
10801 scheduleBroadcastsLocked();
10802 r.state = BroadcastRecord.IDLE;
10803 return;
10804 }
10805
10806 mPendingBroadcast = r;
10807 }
10808 }
10809
10810 // =========================================================
10811 // INSTRUMENTATION
10812 // =========================================================
10813
10814 public boolean startInstrumentation(ComponentName className,
10815 String profileFile, int flags, Bundle arguments,
10816 IInstrumentationWatcher watcher) {
10817 // Refuse possible leaked file descriptors
10818 if (arguments != null && arguments.hasFileDescriptors()) {
10819 throw new IllegalArgumentException("File descriptors passed in Bundle");
10820 }
10821
10822 synchronized(this) {
10823 InstrumentationInfo ii = null;
10824 ApplicationInfo ai = null;
10825 try {
10826 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010827 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010828 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010829 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 } catch (PackageManager.NameNotFoundException e) {
10831 }
10832 if (ii == null) {
10833 reportStartInstrumentationFailure(watcher, className,
10834 "Unable to find instrumentation info for: " + className);
10835 return false;
10836 }
10837 if (ai == null) {
10838 reportStartInstrumentationFailure(watcher, className,
10839 "Unable to find instrumentation target package: " + ii.targetPackage);
10840 return false;
10841 }
10842
10843 int match = mContext.getPackageManager().checkSignatures(
10844 ii.targetPackage, ii.packageName);
10845 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10846 String msg = "Permission Denial: starting instrumentation "
10847 + className + " from pid="
10848 + Binder.getCallingPid()
10849 + ", uid=" + Binder.getCallingPid()
10850 + " not allowed because package " + ii.packageName
10851 + " does not have a signature matching the target "
10852 + ii.targetPackage;
10853 reportStartInstrumentationFailure(watcher, className, msg);
10854 throw new SecurityException(msg);
10855 }
10856
10857 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010858 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 ProcessRecord app = addAppLocked(ai);
10860 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010861 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010862 app.instrumentationProfileFile = profileFile;
10863 app.instrumentationArguments = arguments;
10864 app.instrumentationWatcher = watcher;
10865 app.instrumentationResultClass = className;
10866 Binder.restoreCallingIdentity(origId);
10867 }
10868
10869 return true;
10870 }
10871
10872 /**
10873 * Report errors that occur while attempting to start Instrumentation. Always writes the
10874 * error to the logs, but if somebody is watching, send the report there too. This enables
10875 * the "am" command to report errors with more information.
10876 *
10877 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10878 * @param cn The component name of the instrumentation.
10879 * @param report The error report.
10880 */
10881 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10882 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010883 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010884 try {
10885 if (watcher != null) {
10886 Bundle results = new Bundle();
10887 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10888 results.putString("Error", report);
10889 watcher.instrumentationStatus(cn, -1, results);
10890 }
10891 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010892 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 }
10894 }
10895
10896 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10897 if (app.instrumentationWatcher != null) {
10898 try {
10899 // NOTE: IInstrumentationWatcher *must* be oneway here
10900 app.instrumentationWatcher.instrumentationFinished(
10901 app.instrumentationClass,
10902 resultCode,
10903 results);
10904 } catch (RemoteException e) {
10905 }
10906 }
10907 app.instrumentationWatcher = null;
10908 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010909 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010910 app.instrumentationProfileFile = null;
10911 app.instrumentationArguments = null;
10912
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010913 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 }
10915
10916 public void finishInstrumentation(IApplicationThread target,
10917 int resultCode, Bundle results) {
10918 // Refuse possible leaked file descriptors
10919 if (results != null && results.hasFileDescriptors()) {
10920 throw new IllegalArgumentException("File descriptors passed in Intent");
10921 }
10922
10923 synchronized(this) {
10924 ProcessRecord app = getRecordForAppLocked(target);
10925 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010926 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927 return;
10928 }
10929 final long origId = Binder.clearCallingIdentity();
10930 finishInstrumentationLocked(app, resultCode, results);
10931 Binder.restoreCallingIdentity(origId);
10932 }
10933 }
10934
10935 // =========================================================
10936 // CONFIGURATION
10937 // =========================================================
10938
10939 public ConfigurationInfo getDeviceConfigurationInfo() {
10940 ConfigurationInfo config = new ConfigurationInfo();
10941 synchronized (this) {
10942 config.reqTouchScreen = mConfiguration.touchscreen;
10943 config.reqKeyboardType = mConfiguration.keyboard;
10944 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010945 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10946 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010947 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10948 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010949 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10950 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10952 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010953 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 }
10955 return config;
10956 }
10957
10958 public Configuration getConfiguration() {
10959 Configuration ci;
10960 synchronized(this) {
10961 ci = new Configuration(mConfiguration);
10962 }
10963 return ci;
10964 }
10965
10966 public void updateConfiguration(Configuration values) {
10967 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10968 "updateConfiguration()");
10969
10970 synchronized(this) {
10971 if (values == null && mWindowManager != null) {
10972 // sentinel: fetch the current configuration from the window manager
10973 values = mWindowManager.computeNewConfiguration();
10974 }
10975
10976 final long origId = Binder.clearCallingIdentity();
10977 updateConfigurationLocked(values, null);
10978 Binder.restoreCallingIdentity(origId);
10979 }
10980 }
10981
10982 /**
10983 * Do either or both things: (1) change the current configuration, and (2)
10984 * make sure the given activity is running with the (now) current
10985 * configuration. Returns true if the activity has been left running, or
10986 * false if <var>starting</var> is being destroyed to match the new
10987 * configuration.
10988 */
10989 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010990 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010991 int changes = 0;
10992
10993 boolean kept = true;
10994
10995 if (values != null) {
10996 Configuration newConfig = new Configuration(mConfiguration);
10997 changes = newConfig.updateFrom(values);
10998 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010999 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011000 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 }
11002
Doug Zongker2bec3d42009-12-04 12:52:44 -080011003 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011004
11005 if (values.locale != null) {
11006 saveLocaleLocked(values.locale,
11007 !values.locale.equals(mConfiguration.locale),
11008 values.userSetLocale);
11009 }
11010
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011011 mConfigurationSeq++;
11012 if (mConfigurationSeq <= 0) {
11013 mConfigurationSeq = 1;
11014 }
11015 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011017 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011018
11019 AttributeCache ac = AttributeCache.instance();
11020 if (ac != null) {
11021 ac.updateConfiguration(mConfiguration);
11022 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011024 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11025 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11026 msg.obj = new Configuration(mConfiguration);
11027 mHandler.sendMessage(msg);
11028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011030 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11031 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011032 try {
11033 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011034 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011035 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 app.thread.scheduleConfigurationChanged(mConfiguration);
11037 }
11038 } catch (Exception e) {
11039 }
11040 }
11041 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011042 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11043 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11045 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011046 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11047 broadcastIntentLocked(null, null,
11048 new Intent(Intent.ACTION_LOCALE_CHANGED),
11049 null, null, 0, null, null,
11050 null, false, false, MY_PID, Process.SYSTEM_UID);
11051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 }
11053 }
11054
11055 if (changes != 0 && starting == null) {
11056 // If the configuration changed, and the caller is not already
11057 // in the process of starting an activity, then find the top
11058 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011059 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060 }
11061
11062 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011063 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 if (kept) {
11065 // If this didn't result in the starting activity being
11066 // destroyed, then we need to make sure at this point that all
11067 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011068 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011069 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011070 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011071 }
11072 }
11073
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011074 if (values != null && mWindowManager != null) {
11075 mWindowManager.setNewConfiguration(mConfiguration);
11076 }
11077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011078 return kept;
11079 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080
11081 /**
11082 * Save the locale. You must be inside a synchronized (this) block.
11083 */
11084 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11085 if(isDiff) {
11086 SystemProperties.set("user.language", l.getLanguage());
11087 SystemProperties.set("user.region", l.getCountry());
11088 }
11089
11090 if(isPersist) {
11091 SystemProperties.set("persist.sys.language", l.getLanguage());
11092 SystemProperties.set("persist.sys.country", l.getCountry());
11093 SystemProperties.set("persist.sys.localevar", l.getVariant());
11094 }
11095 }
11096
11097 // =========================================================
11098 // LIFETIME MANAGEMENT
11099 // =========================================================
11100
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011101 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11102 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011103 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011104 // This adjustment has already been computed. If we are calling
11105 // from the top, we may have already computed our adjustment with
11106 // an earlier hidden adjustment that isn't really for us... if
11107 // so, use the new hidden adjustment.
11108 if (!recursed && app.hidden) {
11109 app.curAdj = hiddenAdj;
11110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011111 return app.curAdj;
11112 }
11113
11114 if (app.thread == null) {
11115 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011116 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 return (app.curAdj=EMPTY_APP_ADJ);
11118 }
11119
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011120 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11121 // The max adjustment doesn't allow this app to be anything
11122 // below foreground, so it is not worth doing work for it.
11123 app.adjType = "fixed";
11124 app.adjSeq = mAdjSeq;
11125 app.curRawAdj = app.maxAdj;
11126 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11127 return (app.curAdj=app.maxAdj);
11128 }
11129
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011130 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011131 app.adjSource = null;
11132 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011133 app.empty = false;
11134 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011135
The Android Open Source Project4df24232009-03-05 14:34:35 -080011136 // Determine the importance of the process, starting with most
11137 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011138 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011139 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011141 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 // The last app on the list is the foreground app.
11143 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011144 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011145 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011146 } else if (app.instrumentationClass != null) {
11147 // Don't want to kill running instrumentation.
11148 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011149 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011150 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011151 } else if (app.persistentActivities > 0) {
11152 // Special persistent activities... shouldn't be used these days.
11153 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011154 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011155 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 } else if (app.curReceiver != null ||
11157 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11158 // An app that is currently receiving a broadcast 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 = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011163 } else if (app.executingServices.size() > 0) {
11164 // An app that is currently executing a service callback also
11165 // counts as being in the foreground.
11166 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011167 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011168 app.adjType = "exec-service";
11169 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011171 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011172 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011173 app.adjType = "foreground-service";
11174 } else if (app.forcingToForeground != null) {
11175 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011176 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011177 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011178 app.adjType = "force-foreground";
11179 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011180 } else if (app == mHeavyWeightProcess) {
11181 // We don't want to kill the current heavy-weight process.
11182 adj = HEAVY_WEIGHT_APP_ADJ;
11183 schedGroup = Process.THREAD_GROUP_DEFAULT;
11184 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011185 } else if (app == mHomeProcess) {
11186 // This process is hosting what we currently consider to be the
11187 // home app, so we don't want to let it go into the background.
11188 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011189 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011190 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011191 } else if ((N=app.activities.size()) != 0) {
11192 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011193 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011195 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011196 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011197 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011199 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011200 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011201 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011203 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011204 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011205 break;
11206 }
11207 }
11208 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011209 // A very not-needed process. If this is lower in the lru list,
11210 // we will push it in to the empty bucket.
11211 app.hidden = true;
11212 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011213 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011214 adj = hiddenAdj;
11215 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011216 }
11217
Joe Onorato8a9b2202010-02-26 18:56:32 -080011218 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011219
The Android Open Source Project4df24232009-03-05 14:34:35 -080011220 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011221 // there are applications dependent on our services or providers, but
11222 // this gives us a baseline and makes sure we don't get into an
11223 // infinite recursion.
11224 app.adjSeq = mAdjSeq;
11225 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011226
Christopher Tate6fa95972009-06-05 18:43:55 -070011227 if (mBackupTarget != null && app == mBackupTarget.app) {
11228 // If possible we want to avoid killing apps while they're being backed up
11229 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011230 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011231 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011232 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011233 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011234 }
11235 }
11236
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011237 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11238 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011239 final long now = SystemClock.uptimeMillis();
11240 // This process is more important if the top activity is
11241 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011242 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011243 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011244 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011245 if (s.startRequested) {
11246 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11247 // This service has seen some activity within
11248 // recent memory, so we will keep its process ahead
11249 // of the background processes.
11250 if (adj > SECONDARY_SERVER_ADJ) {
11251 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011252 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011253 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254 }
11255 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011256 // If we have let the service slide into the background
11257 // state, still have some text describing what it is doing
11258 // even though the service no longer has an impact.
11259 if (adj > SECONDARY_SERVER_ADJ) {
11260 app.adjType = "started-bg-services";
11261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011263 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11264 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011265 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 = s.connections.values().iterator();
11267 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011268 ArrayList<ConnectionRecord> clist = kt.next();
11269 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11270 // XXX should compute this based on the max of
11271 // all connected clients.
11272 ConnectionRecord cr = clist.get(i);
11273 if (cr.binding.client == app) {
11274 // Binding to ourself is not interesting.
11275 continue;
11276 }
11277 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11278 ProcessRecord client = cr.binding.client;
11279 int myHiddenAdj = hiddenAdj;
11280 if (myHiddenAdj > client.hiddenAdj) {
11281 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11282 myHiddenAdj = client.hiddenAdj;
11283 } else {
11284 myHiddenAdj = VISIBLE_APP_ADJ;
11285 }
11286 }
11287 int clientAdj = computeOomAdjLocked(
11288 client, myHiddenAdj, TOP_APP, true);
11289 if (adj > clientAdj) {
11290 adj = clientAdj >= VISIBLE_APP_ADJ
11291 ? clientAdj : VISIBLE_APP_ADJ;
11292 if (!client.hidden) {
11293 app.hidden = false;
11294 }
11295 app.adjType = "service";
11296 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11297 .REASON_SERVICE_IN_USE;
11298 app.adjSource = cr.binding.client;
11299 app.adjTarget = s.name;
11300 }
11301 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11302 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11303 schedGroup = Process.THREAD_GROUP_DEFAULT;
11304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011305 }
11306 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011307 ActivityRecord a = cr.activity;
11308 //if (a != null) {
11309 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11310 //}
11311 if (a != null && adj > FOREGROUND_APP_ADJ &&
11312 (a.state == ActivityState.RESUMED
11313 || a.state == ActivityState.PAUSING)) {
11314 adj = FOREGROUND_APP_ADJ;
11315 schedGroup = Process.THREAD_GROUP_DEFAULT;
11316 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011317 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011318 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11319 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011320 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011321 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011323 }
11324 }
11325 }
11326 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011327
11328 // Finally, f this process has active services running in it, we
11329 // would like to avoid killing it unless it would prevent the current
11330 // application from running. By default we put the process in
11331 // with the rest of the background processes; as we scan through
11332 // its services we may bump it up from there.
11333 if (adj > hiddenAdj) {
11334 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011335 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011336 app.adjType = "bg-services";
11337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011338 }
11339
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011340 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11341 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011342 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011343 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11344 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011345 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011346 if (cpr.clients.size() != 0) {
11347 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11348 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11349 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011350 if (client == app) {
11351 // Being our own client is not interesting.
11352 continue;
11353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011354 int myHiddenAdj = hiddenAdj;
11355 if (myHiddenAdj > client.hiddenAdj) {
11356 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11357 myHiddenAdj = client.hiddenAdj;
11358 } else {
11359 myHiddenAdj = FOREGROUND_APP_ADJ;
11360 }
11361 }
11362 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011363 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 if (adj > clientAdj) {
11365 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011366 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011367 if (!client.hidden) {
11368 app.hidden = false;
11369 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011370 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011371 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11372 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011373 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011374 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011375 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011376 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11377 schedGroup = Process.THREAD_GROUP_DEFAULT;
11378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011379 }
11380 }
11381 // If the provider has external (non-framework) process
11382 // dependencies, ensure that its adjustment is at least
11383 // FOREGROUND_APP_ADJ.
11384 if (cpr.externals != 0) {
11385 if (adj > FOREGROUND_APP_ADJ) {
11386 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011387 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011388 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011389 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011390 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011391 }
11392 }
11393 }
11394 }
11395
11396 app.curRawAdj = adj;
11397
Joe Onorato8a9b2202010-02-26 18:56:32 -080011398 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11400 if (adj > app.maxAdj) {
11401 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011402 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011403 schedGroup = Process.THREAD_GROUP_DEFAULT;
11404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 }
11406
11407 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011408 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410 return adj;
11411 }
11412
11413 /**
11414 * Ask a given process to GC right now.
11415 */
11416 final void performAppGcLocked(ProcessRecord app) {
11417 try {
11418 app.lastRequestedGc = SystemClock.uptimeMillis();
11419 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011420 if (app.reportLowMemory) {
11421 app.reportLowMemory = false;
11422 app.thread.scheduleLowMemory();
11423 } else {
11424 app.thread.processInBackground();
11425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426 }
11427 } catch (Exception e) {
11428 // whatever.
11429 }
11430 }
11431
11432 /**
11433 * Returns true if things are idle enough to perform GCs.
11434 */
Josh Bartel7f208742010-02-25 11:01:44 -060011435 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 return mParallelBroadcasts.size() == 0
11437 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011438 && (mSleeping || (mMainStack.mResumedActivity != null &&
11439 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011440 }
11441
11442 /**
11443 * Perform GCs on all processes that are waiting for it, but only
11444 * if things are idle.
11445 */
11446 final void performAppGcsLocked() {
11447 final int N = mProcessesToGc.size();
11448 if (N <= 0) {
11449 return;
11450 }
Josh Bartel7f208742010-02-25 11:01:44 -060011451 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 while (mProcessesToGc.size() > 0) {
11453 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011454 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011455 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11456 <= SystemClock.uptimeMillis()) {
11457 // To avoid spamming the system, we will GC processes one
11458 // at a time, waiting a few seconds between each.
11459 performAppGcLocked(proc);
11460 scheduleAppGcsLocked();
11461 return;
11462 } else {
11463 // It hasn't been long enough since we last GCed this
11464 // process... put it in the list to wait for its time.
11465 addProcessToGcListLocked(proc);
11466 break;
11467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468 }
11469 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011470
11471 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 }
11473 }
11474
11475 /**
11476 * If all looks good, perform GCs on all processes waiting for them.
11477 */
11478 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011479 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011480 performAppGcsLocked();
11481 return;
11482 }
11483 // Still not idle, wait some more.
11484 scheduleAppGcsLocked();
11485 }
11486
11487 /**
11488 * Schedule the execution of all pending app GCs.
11489 */
11490 final void scheduleAppGcsLocked() {
11491 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011492
11493 if (mProcessesToGc.size() > 0) {
11494 // Schedule a GC for the time to the next process.
11495 ProcessRecord proc = mProcessesToGc.get(0);
11496 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11497
11498 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11499 long now = SystemClock.uptimeMillis();
11500 if (when < (now+GC_TIMEOUT)) {
11501 when = now + GC_TIMEOUT;
11502 }
11503 mHandler.sendMessageAtTime(msg, when);
11504 }
11505 }
11506
11507 /**
11508 * Add a process to the array of processes waiting to be GCed. Keeps the
11509 * list in sorted order by the last GC time. The process can't already be
11510 * on the list.
11511 */
11512 final void addProcessToGcListLocked(ProcessRecord proc) {
11513 boolean added = false;
11514 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11515 if (mProcessesToGc.get(i).lastRequestedGc <
11516 proc.lastRequestedGc) {
11517 added = true;
11518 mProcessesToGc.add(i+1, proc);
11519 break;
11520 }
11521 }
11522 if (!added) {
11523 mProcessesToGc.add(0, proc);
11524 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011525 }
11526
11527 /**
11528 * Set up to ask a process to GC itself. This will either do it
11529 * immediately, or put it on the list of processes to gc the next
11530 * time things are idle.
11531 */
11532 final void scheduleAppGcLocked(ProcessRecord app) {
11533 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011534 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011535 return;
11536 }
11537 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011538 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011539 scheduleAppGcsLocked();
11540 }
11541 }
11542
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011543 final void checkExcessiveWakeLocksLocked(boolean doKills) {
11544 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11545 if (mLastWakeLockCheckTime == 0) {
11546 doKills = false;
11547 }
11548 if (stats.isScreenOn()) {
11549 doKills = false;
11550 }
11551 final long curRealtime = SystemClock.elapsedRealtime();
11552 final long timeSince = curRealtime - mLastWakeLockCheckTime;
11553 mLastWakeLockCheckTime = curRealtime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011554 if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011555 doKills = false;
11556 }
11557 int i = mLruProcesses.size();
11558 while (i > 0) {
11559 i--;
11560 ProcessRecord app = mLruProcesses.get(i);
11561 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
11562 long wtime;
11563 synchronized (stats) {
11564 wtime = stats.getProcessWakeTime(app.info.uid,
11565 app.pid, curRealtime);
11566 }
11567 long timeUsed = wtime - app.lastWakeTime;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011568 if (false) {
11569 StringBuilder sb = new StringBuilder(128);
11570 sb.append("Wake for ");
11571 app.toShortString(sb);
11572 sb.append(": over ");
11573 TimeUtils.formatDuration(timeSince, sb);
11574 sb.append(" used ");
11575 TimeUtils.formatDuration(timeUsed, sb);
11576 sb.append(" (");
11577 sb.append((timeUsed*100)/timeSince);
11578 sb.append("%)");
11579 Slog.i(TAG, sb.toString());
11580 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011581 // If a process has held a wake lock for more
11582 // than 50% of the time during this period,
11583 // that sounds pad. Kill!
11584 if (doKills && timeSince > 0
11585 && ((timeUsed*100)/timeSince) >= 50) {
11586 Slog.i(TAG, "Excessive wake lock in " + app.processName
11587 + " (pid " + app.pid + "): held " + timeUsed
11588 + " during " + timeSince);
11589 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11590 app.processName, app.setAdj, "excessive wake lock");
11591 Process.killProcessQuiet(app.pid);
11592 } else {
11593 app.lastWakeTime = wtime;
11594 }
11595 }
11596 }
11597 }
11598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599 private final boolean updateOomAdjLocked(
11600 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11601 app.hiddenAdj = hiddenAdj;
11602
11603 if (app.thread == null) {
11604 return true;
11605 }
11606
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011607 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011608
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011609 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011610 if (app.curRawAdj != app.setRawAdj) {
11611 if (app.curRawAdj > FOREGROUND_APP_ADJ
11612 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11613 // If this app is transitioning from foreground to
11614 // non-foreground, have it do a gc.
11615 scheduleAppGcLocked(app);
11616 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11617 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11618 // Likewise do a gc when an app is moving in to the
11619 // background (such as a service stopping).
11620 scheduleAppGcLocked(app);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011621 // And note its current wake lock time.
11622 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11623 synchronized (stats) {
11624 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11625 app.pid, SystemClock.elapsedRealtime());
11626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011627 }
11628 app.setRawAdj = app.curRawAdj;
11629 }
11630 if (adj != app.setAdj) {
11631 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011632 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 TAG, "Set app " + app.processName +
11634 " oom adj to " + adj);
11635 app.setAdj = adj;
11636 } else {
11637 return false;
11638 }
11639 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011640 if (app.setSchedGroup != app.curSchedGroup) {
11641 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011642 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011643 "Setting process group of " + app.processName
11644 + " to " + app.curSchedGroup);
11645 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011646 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011647 try {
11648 Process.setProcessGroup(app.pid, app.curSchedGroup);
11649 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011650 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011651 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011652 e.printStackTrace();
11653 } finally {
11654 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011655 }
11656 }
11657 if (false) {
11658 if (app.thread != null) {
11659 try {
11660 app.thread.setSchedulingGroup(app.curSchedGroup);
11661 } catch (RemoteException e) {
11662 }
11663 }
11664 }
11665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 }
11667
11668 return true;
11669 }
11670
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011671 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011672 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011674 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011675 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011676 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011677 }
11678 }
11679 return resumedActivity;
11680 }
11681
11682 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011683 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011684 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11685 int curAdj = app.curAdj;
11686 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11687 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11688
11689 mAdjSeq++;
11690
11691 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11692 if (res) {
11693 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11694 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11695 if (nowHidden != wasHidden) {
11696 // Changed to/from hidden state, so apps after it in the LRU
11697 // list may also be changed.
11698 updateOomAdjLocked();
11699 }
11700 }
11701 return res;
11702 }
11703
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011704 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011705 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011706 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11708
11709 if (false) {
11710 RuntimeException e = new RuntimeException();
11711 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011712 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011713 }
11714
11715 mAdjSeq++;
11716
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011717 // Let's determine how many processes we have running vs.
11718 // how many slots we have for background processes; we may want
11719 // to put multiple processes in a slot of there are enough of
11720 // them.
11721 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11722 int factor = (mLruProcesses.size()-4)/numSlots;
11723 if (factor < 1) factor = 1;
11724 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011725 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011727 // First try updating the OOM adjustment for each of the
11728 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011729 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11731 while (i > 0) {
11732 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011733 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011734 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011735 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011736 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011737 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011738 step++;
11739 if (step >= factor) {
11740 step = 0;
11741 curHiddenAdj++;
11742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011743 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011744 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011745 if (!app.killedBackground) {
11746 numHidden++;
11747 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011748 Slog.i(TAG, "No longer want " + app.processName
11749 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011750 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11751 app.processName, app.setAdj, "too many background");
11752 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011753 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011754 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011755 }
11756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011757 } else {
11758 didOomAdj = false;
11759 }
11760 }
11761
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011762 // If we return false, we will fall back on killing processes to
11763 // have a fixed limit. Do this if a limit has been requested; else
11764 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011765 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11766 }
11767
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011768 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011769 synchronized (this) {
11770 int i;
11771
11772 // First remove any unused application processes whose package
11773 // has been removed.
11774 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11775 final ProcessRecord app = mRemovedProcesses.get(i);
11776 if (app.activities.size() == 0
11777 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011778 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 TAG, "Exiting empty application process "
11780 + app.processName + " ("
11781 + (app.thread != null ? app.thread.asBinder() : null)
11782 + ")\n");
11783 if (app.pid > 0 && app.pid != MY_PID) {
11784 Process.killProcess(app.pid);
11785 } else {
11786 try {
11787 app.thread.scheduleExit();
11788 } catch (Exception e) {
11789 // Ignore exceptions.
11790 }
11791 }
11792 cleanUpApplicationRecordLocked(app, false, -1);
11793 mRemovedProcesses.remove(i);
11794
11795 if (app.persistent) {
11796 if (app.persistent) {
11797 addAppLocked(app.info);
11798 }
11799 }
11800 }
11801 }
11802
11803 // Now try updating the OOM adjustment for each of the
11804 // application processes based on their current state.
11805 // If the setOomAdj() API is not supported, then go with our
11806 // back-up plan...
11807 if (!updateOomAdjLocked()) {
11808
11809 // Count how many processes are running services.
11810 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011811 for (i=mLruProcesses.size()-1; i>=0; i--) {
11812 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011813
11814 if (app.persistent || app.services.size() != 0
11815 || app.curReceiver != null
11816 || app.persistentActivities > 0) {
11817 // Don't count processes holding services against our
11818 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011819 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011820 TAG, "Not trimming app " + app + " with services: "
11821 + app.services);
11822 numServiceProcs++;
11823 }
11824 }
11825
11826 int curMaxProcs = mProcessLimit;
11827 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11828 if (mAlwaysFinishActivities) {
11829 curMaxProcs = 1;
11830 }
11831 curMaxProcs += numServiceProcs;
11832
11833 // Quit as many processes as we can to get down to the desired
11834 // process count. First remove any processes that no longer
11835 // have activites running in them.
11836 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011837 i<mLruProcesses.size()
11838 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011839 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011840 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011841 // Quit an application only if it is not currently
11842 // running any activities.
11843 if (!app.persistent && app.activities.size() == 0
11844 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011845 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 TAG, "Exiting empty application process "
11847 + app.processName + " ("
11848 + (app.thread != null ? app.thread.asBinder() : null)
11849 + ")\n");
11850 if (app.pid > 0 && app.pid != MY_PID) {
11851 Process.killProcess(app.pid);
11852 } else {
11853 try {
11854 app.thread.scheduleExit();
11855 } catch (Exception e) {
11856 // Ignore exceptions.
11857 }
11858 }
11859 // todo: For now we assume the application is not buggy
11860 // or evil, and will quit as a result of our request.
11861 // Eventually we need to drive this off of the death
11862 // notification, and kill the process if it takes too long.
11863 cleanUpApplicationRecordLocked(app, false, i);
11864 i--;
11865 }
11866 }
11867
11868 // If we still have too many processes, now from the least
11869 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011870 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011871 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011872 " of " + curMaxProcs + " processes");
11873 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011874 i<mLruProcesses.size()
11875 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011877 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011878 // Quit the application only if we have a state saved for
11879 // all of its activities.
11880 boolean canQuit = !app.persistent && app.curReceiver == null
11881 && app.services.size() == 0
11882 && app.persistentActivities == 0;
11883 int NUMA = app.activities.size();
11884 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011885 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011886 TAG, "Looking to quit " + app.processName);
11887 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011888 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011889 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011890 TAG, " " + r.intent.getComponent().flattenToShortString()
11891 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11892 canQuit = (r.haveState || !r.stateNotNeeded)
11893 && !r.visible && r.stopped;
11894 }
11895 if (canQuit) {
11896 // Finish all of the activities, and then the app itself.
11897 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011898 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011899 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011900 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011901 }
11902 r.resultTo = null;
11903 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011904 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011905 + app.processName + " ("
11906 + (app.thread != null ? app.thread.asBinder() : null)
11907 + ")\n");
11908 if (app.pid > 0 && app.pid != MY_PID) {
11909 Process.killProcess(app.pid);
11910 } else {
11911 try {
11912 app.thread.scheduleExit();
11913 } catch (Exception e) {
11914 // Ignore exceptions.
11915 }
11916 }
11917 // todo: For now we assume the application is not buggy
11918 // or evil, and will quit as a result of our request.
11919 // Eventually we need to drive this off of the death
11920 // notification, and kill the process if it takes too long.
11921 cleanUpApplicationRecordLocked(app, false, i);
11922 i--;
11923 //dump();
11924 }
11925 }
11926
11927 }
11928
11929 int curMaxActivities = MAX_ACTIVITIES;
11930 if (mAlwaysFinishActivities) {
11931 curMaxActivities = 1;
11932 }
11933
11934 // Finally, if there are too many activities now running, try to
11935 // finish as many as we can to get back down to the limit.
11936 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011937 i<mMainStack.mLRUActivities.size()
11938 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011939 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011940 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011941 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011942
11943 // We can finish this one if we have its icicle saved and
11944 // it is not persistent.
11945 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11946 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011947 final int origSize = mMainStack.mLRUActivities.size();
11948 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011949
11950 // This will remove it from the LRU list, so keep
11951 // our index at the same value. Note that this check to
11952 // see if the size changes is just paranoia -- if
11953 // something unexpected happens, we don't want to end up
11954 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011955 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011956 i--;
11957 }
11958 }
11959 }
11960 }
11961 }
11962
11963 /** This method sends the specified signal to each of the persistent apps */
11964 public void signalPersistentProcesses(int sig) throws RemoteException {
11965 if (sig != Process.SIGNAL_USR1) {
11966 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11967 }
11968
11969 synchronized (this) {
11970 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11971 != PackageManager.PERMISSION_GRANTED) {
11972 throw new SecurityException("Requires permission "
11973 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11974 }
11975
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011976 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11977 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011978 if (r.thread != null && r.persistent) {
11979 Process.sendSignal(r.pid, sig);
11980 }
11981 }
11982 }
11983 }
11984
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011985 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011986 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011987
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011988 try {
11989 synchronized (this) {
11990 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11991 // its own permission.
11992 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11993 != PackageManager.PERMISSION_GRANTED) {
11994 throw new SecurityException("Requires permission "
11995 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011996 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011997
11998 if (start && fd == null) {
11999 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012000 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012001
12002 ProcessRecord proc = null;
12003 try {
12004 int pid = Integer.parseInt(process);
12005 synchronized (mPidsSelfLocked) {
12006 proc = mPidsSelfLocked.get(pid);
12007 }
12008 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012009 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012010
12011 if (proc == null) {
12012 HashMap<String, SparseArray<ProcessRecord>> all
12013 = mProcessNames.getMap();
12014 SparseArray<ProcessRecord> procs = all.get(process);
12015 if (procs != null && procs.size() > 0) {
12016 proc = procs.valueAt(0);
12017 }
12018 }
12019
12020 if (proc == null || proc.thread == null) {
12021 throw new IllegalArgumentException("Unknown process: " + process);
12022 }
12023
12024 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12025 if (isSecure) {
12026 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12027 throw new SecurityException("Process not debuggable: " + proc);
12028 }
12029 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012030
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012031 proc.thread.profilerControl(start, path, fd);
12032 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012033 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012034 }
12035 } catch (RemoteException e) {
12036 throw new IllegalStateException("Process disappeared");
12037 } finally {
12038 if (fd != null) {
12039 try {
12040 fd.close();
12041 } catch (IOException e) {
12042 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012043 }
12044 }
12045 }
12046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012047 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12048 public void monitor() {
12049 synchronized (this) { }
12050 }
12051}