blob: cb2ae735b9f57445c999967dfe6610fe35968bca [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;
20import com.android.internal.app.HeavyWeightSwitcherActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070022import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import com.android.server.IntentResolver;
24import com.android.server.ProcessMap;
25import com.android.server.ProcessStats;
26import com.android.server.SystemServer;
27import com.android.server.Watchdog;
28import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070029import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
Dianne Hackborndd71fc82009-12-16 19:24:32 -080031import dalvik.system.Zygote;
32
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.app.Activity;
34import android.app.ActivityManager;
35import android.app.ActivityManagerNative;
36import android.app.ActivityThread;
37import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070038import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020039import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070041import android.app.IActivityController;
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -080042import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.app.IActivityWatcher;
44import android.app.IApplicationThread;
45import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070046import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.app.IServiceConnection;
48import android.app.IThumbnailReceiver;
49import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070050import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070051import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.app.PendingIntent;
53import android.app.ResultInfo;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070054import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080055import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020056import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080057import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.ComponentName;
59import android.content.ContentResolver;
60import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020061import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.content.Intent;
63import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070064import android.content.IIntentReceiver;
65import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070066import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.ActivityInfo;
68import android.content.pm.ApplicationInfo;
69import android.content.pm.ConfigurationInfo;
70import android.content.pm.IPackageDataObserver;
71import android.content.pm.IPackageManager;
72import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080073import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070075import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.pm.ProviderInfo;
77import android.content.pm.ResolveInfo;
78import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070079import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.content.res.Configuration;
81import android.graphics.Bitmap;
82import android.net.Uri;
83import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080084import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070086import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080087import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080089import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.FileUtils;
91import android.os.Handler;
92import android.os.IBinder;
93import android.os.IPermissionController;
94import android.os.Looper;
95import android.os.Message;
96import android.os.Parcel;
97import android.os.ParcelFileDescriptor;
98import android.os.PowerManager;
99import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700100import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.os.RemoteException;
102import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700103import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.os.SystemClock;
105import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.util.Config;
108import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800109import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800110import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import android.util.PrintWriterPrinter;
112import android.util.SparseArray;
113import android.view.Gravity;
114import android.view.LayoutInflater;
115import android.view.View;
116import android.view.WindowManager;
117import android.view.WindowManagerPolicy;
118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119import java.io.File;
120import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200122import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800123import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124import java.io.PrintWriter;
125import java.lang.IllegalStateException;
126import java.lang.ref.WeakReference;
127import java.util.ArrayList;
128import java.util.HashMap;
129import java.util.HashSet;
130import java.util.Iterator;
131import java.util.List;
132import java.util.Locale;
133import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700134import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700135import java.util.concurrent.atomic.AtomicBoolean;
136import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137
138public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
139 static final String TAG = "ActivityManager";
140 static final boolean DEBUG = false;
141 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
142 static final boolean DEBUG_SWITCH = localLOGV || false;
143 static final boolean DEBUG_TASKS = localLOGV || false;
144 static final boolean DEBUG_PAUSE = localLOGV || false;
145 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
146 static final boolean DEBUG_TRANSITION = localLOGV || false;
147 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700148 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 static final boolean DEBUG_SERVICE = localLOGV || false;
150 static final boolean DEBUG_VISBILITY = localLOGV || false;
151 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700152 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800153 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700155 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700156 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700157 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 static final boolean VALIDATE_TOKENS = false;
159 static final boolean SHOW_ACTIVITY_START_TIME = true;
160
161 // Control over CPU and battery monitoring.
162 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
163 static final boolean MONITOR_CPU_USAGE = true;
164 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
165 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
166 static final boolean MONITOR_THREAD_CPU_USAGE = false;
167
Dianne Hackborn1655be42009-05-08 14:29:01 -0700168 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700169 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 private static final String SYSTEM_SECURE = "ro.secure";
172
173 // This is the maximum number of application processes we would like
174 // to have running. Due to the asynchronous nature of things, we can
175 // temporarily go beyond this limit.
176 static final int MAX_PROCESSES = 2;
177
178 // Set to false to leave processes running indefinitely, relying on
179 // the kernel killing them as resources are required.
180 static final boolean ENFORCE_PROCESS_LIMIT = false;
181
182 // This is the maximum number of activities that we would like to have
183 // running at a given time.
184 static final int MAX_ACTIVITIES = 20;
185
186 // Maximum number of recent tasks that we can remember.
187 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700188
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700189 // Amount of time after a call to stopAppSwitches() during which we will
190 // prevent further untrusted switches from happening.
191 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
193 // How long we wait for a launched process to attach to the activity manager
194 // before we decide it's never going to come up for real.
195 static final int PROC_START_TIMEOUT = 10*1000;
196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 // How long to wait after going idle before forcing apps to GC.
198 static final int GC_TIMEOUT = 5*1000;
199
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700200 // The minimum amount of time between successive GC requests for a process.
201 static final int GC_MIN_INTERVAL = 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 */
613 final HashMap<IBinder, ConnectionRecord> mServiceConnections
614 = new HashMap<IBinder, ConnectionRecord>();
615
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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754
755 Context mContext;
756
757 int mFactoryTest;
758
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700759 boolean mCheckedForSetup;
760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700762 * The time at which we will allow normal application switches again,
763 * after a call to {@link #stopAppSwitches()}.
764 */
765 long mAppSwitchesAllowedTime;
766
767 /**
768 * This is set to true after the first switch after mAppSwitchesAllowedTime
769 * is set; any switches after that will clear the time.
770 */
771 boolean mDidAppSwitch;
772
773 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 * Set while we are wanting to sleep, to prevent any
775 * activities from being started/resumed.
776 */
777 boolean mSleeping = false;
778
779 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700780 * Set if we are shutting down the system, similar to sleeping.
781 */
782 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783
784 /**
785 * Task identifier that activities are currently being started
786 * in. Incremented each time a new task is created.
787 * todo: Replace this with a TokenSpace class that generates non-repeating
788 * integers that won't wrap.
789 */
790 int mCurTask = 1;
791
792 /**
793 * Current sequence id for oom_adj computation traversal.
794 */
795 int mAdjSeq = 0;
796
797 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700798 * Current sequence id for process LRU updating.
799 */
800 int mLruSeq = 0;
801
802 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
804 * is set, indicating the user wants processes started in such a way
805 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
806 * running in each process (thus no pre-initialized process, etc).
807 */
808 boolean mSimpleProcessManagement = false;
809
810 /**
811 * System monitoring: number of processes that died since the last
812 * N procs were started.
813 */
814 int[] mProcDeaths = new int[20];
815
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700816 /**
817 * This is set if we had to do a delayed dexopt of an app before launching
818 * it, to increasing the ANR timeouts in that case.
819 */
820 boolean mDidDexOpt;
821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 String mDebugApp = null;
823 boolean mWaitForDebugger = false;
824 boolean mDebugTransient = false;
825 String mOrigDebugApp = null;
826 boolean mOrigWaitForDebugger = false;
827 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700828 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700830 final RemoteCallbackList<IActivityWatcher> mWatchers
831 = new RemoteCallbackList<IActivityWatcher>();
832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 /**
834 * Callback of last caller to {@link #requestPss}.
835 */
836 Runnable mRequestPssCallback;
837
838 /**
839 * Remaining processes for which we are waiting results from the last
840 * call to {@link #requestPss}.
841 */
842 final ArrayList<ProcessRecord> mRequestPssList
843 = new ArrayList<ProcessRecord>();
844
845 /**
846 * Runtime statistics collection thread. This object's lock is used to
847 * protect all related state.
848 */
849 final Thread mProcessStatsThread;
850
851 /**
852 * Used to collect process stats when showing not responding dialog.
853 * Protected by mProcessStatsThread.
854 */
855 final ProcessStats mProcessStats = new ProcessStats(
856 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700857 final AtomicLong mLastCpuTime = new AtomicLong(0);
858 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 long mLastWriteTime = 0;
861
862 /**
863 * Set to true after the system has finished booting.
864 */
865 boolean mBooted = false;
866
867 int mProcessLimit = 0;
868
869 WindowManagerService mWindowManager;
870
871 static ActivityManagerService mSelf;
872 static ActivityThread mSystemThread;
873
874 private final class AppDeathRecipient implements IBinder.DeathRecipient {
875 final ProcessRecord mApp;
876 final int mPid;
877 final IApplicationThread mAppThread;
878
879 AppDeathRecipient(ProcessRecord app, int pid,
880 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800881 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800882 TAG, "New death recipient " + this
883 + " for thread " + thread.asBinder());
884 mApp = app;
885 mPid = pid;
886 mAppThread = thread;
887 }
888
889 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800890 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 TAG, "Death received in " + this
892 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 synchronized(ActivityManagerService.this) {
894 appDiedLocked(mApp, mPid, mAppThread);
895 }
896 }
897 }
898
899 static final int SHOW_ERROR_MSG = 1;
900 static final int SHOW_NOT_RESPONDING_MSG = 2;
901 static final int SHOW_FACTORY_ERROR_MSG = 3;
902 static final int UPDATE_CONFIGURATION_MSG = 4;
903 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
904 static final int WAIT_FOR_DEBUGGER_MSG = 6;
905 static final int BROADCAST_INTENT_MSG = 7;
906 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 static final int SERVICE_TIMEOUT_MSG = 12;
908 static final int UPDATE_TIME_ZONE = 13;
909 static final int SHOW_UID_ERROR_MSG = 14;
910 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700912 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700913 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800914 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700915 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
916 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700917 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918
919 AlertDialog mUidAlert;
920
921 final Handler mHandler = new Handler() {
922 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800923 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 //}
925
926 public void handleMessage(Message msg) {
927 switch (msg.what) {
928 case SHOW_ERROR_MSG: {
929 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 synchronized (ActivityManagerService.this) {
931 ProcessRecord proc = (ProcessRecord)data.get("app");
932 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800933 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 return;
935 }
936 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700937 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800938 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 d.show();
940 proc.crashDialog = d;
941 } else {
942 // The device is asleep, so just pretend that the user
943 // saw a crash dialog and hit "force quit".
944 res.set(0);
945 }
946 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700947
948 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 } break;
950 case SHOW_NOT_RESPONDING_MSG: {
951 synchronized (ActivityManagerService.this) {
952 HashMap data = (HashMap) msg.obj;
953 ProcessRecord proc = (ProcessRecord)data.get("app");
954 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800955 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 return;
957 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800958
959 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
960 null, null, 0, null, null, null,
961 false, false, MY_PID, Process.SYSTEM_UID);
962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700964 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 d.show();
966 proc.anrDialog = d;
967 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700968
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700969 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700971 case SHOW_STRICT_MODE_VIOLATION_MSG: {
972 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
973 synchronized (ActivityManagerService.this) {
974 ProcessRecord proc = (ProcessRecord) data.get("app");
975 if (proc == null) {
976 Slog.e(TAG, "App not found when showing strict mode dialog.");
977 break;
978 }
979 if (proc.crashDialog != null) {
980 Slog.e(TAG, "App already has strict mode dialog: " + proc);
981 return;
982 }
983 AppErrorResult res = (AppErrorResult) data.get("result");
984 if (!mSleeping && !mShuttingDown) {
985 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
986 d.show();
987 proc.crashDialog = d;
988 } else {
989 // The device is asleep, so just pretend that the user
990 // saw a crash dialog and hit "force quit".
991 res.set(0);
992 }
993 }
994 ensureBootCompleted();
995 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 case SHOW_FACTORY_ERROR_MSG: {
997 Dialog d = new FactoryErrorDialog(
998 mContext, msg.getData().getCharSequence("msg"));
999 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001000 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 } break;
1002 case UPDATE_CONFIGURATION_MSG: {
1003 final ContentResolver resolver = mContext.getContentResolver();
1004 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1005 } break;
1006 case GC_BACKGROUND_PROCESSES_MSG: {
1007 synchronized (ActivityManagerService.this) {
1008 performAppGcsIfAppropriateLocked();
1009 }
1010 } break;
1011 case WAIT_FOR_DEBUGGER_MSG: {
1012 synchronized (ActivityManagerService.this) {
1013 ProcessRecord app = (ProcessRecord)msg.obj;
1014 if (msg.arg1 != 0) {
1015 if (!app.waitedForDebugger) {
1016 Dialog d = new AppWaitingForDebuggerDialog(
1017 ActivityManagerService.this,
1018 mContext, app);
1019 app.waitDialog = d;
1020 app.waitedForDebugger = true;
1021 d.show();
1022 }
1023 } else {
1024 if (app.waitDialog != null) {
1025 app.waitDialog.dismiss();
1026 app.waitDialog = null;
1027 }
1028 }
1029 }
1030 } break;
1031 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001032 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 TAG, "Received BROADCAST_INTENT_MSG");
1034 processNextBroadcast(true);
1035 } break;
1036 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001037 if (mDidDexOpt) {
1038 mDidDexOpt = false;
1039 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1040 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1041 return;
1042 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001043 // Only process broadcast timeouts if the system is ready. That way
1044 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1045 // to do heavy lifting for system up
1046 if (mSystemReady) {
1047 broadcastTimeout();
1048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001051 if (mDidDexOpt) {
1052 mDidDexOpt = false;
1053 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1054 nmsg.obj = msg.obj;
1055 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1056 return;
1057 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 serviceTimeout((ProcessRecord)msg.obj);
1059 } break;
1060 case UPDATE_TIME_ZONE: {
1061 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001062 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1063 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 if (r.thread != null) {
1065 try {
1066 r.thread.updateTimeZone();
1067 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001068 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 }
1070 }
1071 }
1072 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001073 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 case SHOW_UID_ERROR_MSG: {
1075 // XXX This is a temporary dialog, no need to localize.
1076 AlertDialog d = new BaseErrorDialog(mContext);
1077 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1078 d.setCancelable(false);
1079 d.setTitle("System UIDs Inconsistent");
1080 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001081 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1083 mUidAlert = d;
1084 d.show();
1085 } break;
1086 case IM_FEELING_LUCKY_MSG: {
1087 if (mUidAlert != null) {
1088 mUidAlert.dismiss();
1089 mUidAlert = null;
1090 }
1091 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001093 if (mDidDexOpt) {
1094 mDidDexOpt = false;
1095 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1096 nmsg.obj = msg.obj;
1097 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1098 return;
1099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 ProcessRecord app = (ProcessRecord)msg.obj;
1101 synchronized (ActivityManagerService.this) {
1102 processStartTimedOutLocked(app);
1103 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001104 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001105 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1106 synchronized (ActivityManagerService.this) {
1107 doPendingActivityLaunchesLocked(true);
1108 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001109 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001110 case KILL_APPLICATION_MSG: {
1111 synchronized (ActivityManagerService.this) {
1112 int uid = msg.arg1;
1113 boolean restart = (msg.arg2 == 1);
1114 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001115 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001116 }
1117 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001118 case FINALIZE_PENDING_INTENT_MSG: {
1119 ((PendingIntentRecord)msg.obj).completeFinalize();
1120 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001121 case POST_HEAVY_NOTIFICATION_MSG: {
1122 INotificationManager inm = NotificationManager.getService();
1123 if (inm == null) {
1124 return;
1125 }
1126
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001127 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001128 ProcessRecord process = root.app;
1129 if (process == null) {
1130 return;
1131 }
1132
1133 try {
1134 Context context = mContext.createPackageContext(process.info.packageName, 0);
1135 String text = mContext.getString(R.string.heavy_weight_notification,
1136 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1137 Notification notification = new Notification();
1138 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1139 notification.when = 0;
1140 notification.flags = Notification.FLAG_ONGOING_EVENT;
1141 notification.tickerText = text;
1142 notification.defaults = 0; // please be quiet
1143 notification.sound = null;
1144 notification.vibrate = null;
1145 notification.setLatestEventInfo(context, text,
1146 mContext.getText(R.string.heavy_weight_notification_detail),
1147 PendingIntent.getActivity(mContext, 0, root.intent,
1148 PendingIntent.FLAG_CANCEL_CURRENT));
1149
1150 try {
1151 int[] outId = new int[1];
1152 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1153 notification, outId);
1154 } catch (RuntimeException e) {
1155 Slog.w(ActivityManagerService.TAG,
1156 "Error showing notification for heavy-weight app", e);
1157 } catch (RemoteException e) {
1158 }
1159 } catch (NameNotFoundException e) {
1160 Log.w(TAG, "Unable to create context for heavy notification", e);
1161 }
1162 } break;
1163 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1164 INotificationManager inm = NotificationManager.getService();
1165 if (inm == null) {
1166 return;
1167 }
1168 try {
1169 inm.cancelNotification("android",
1170 R.string.heavy_weight_notification);
1171 } catch (RuntimeException e) {
1172 Slog.w(ActivityManagerService.TAG,
1173 "Error canceling notification for service", e);
1174 } catch (RemoteException e) {
1175 }
1176 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 }
1178 }
1179 };
1180
1181 public static void setSystemProcess() {
1182 try {
1183 ActivityManagerService m = mSelf;
1184
1185 ServiceManager.addService("activity", m);
1186 ServiceManager.addService("meminfo", new MemBinder(m));
1187 if (MONITOR_CPU_USAGE) {
1188 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 ServiceManager.addService("permission", new PermissionController(m));
1191
1192 ApplicationInfo info =
1193 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001194 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001195 mSystemThread.installSystemApplicationInfo(info);
1196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 synchronized (mSelf) {
1198 ProcessRecord app = mSelf.newProcessRecordLocked(
1199 mSystemThread.getApplicationThread(), info,
1200 info.processName);
1201 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001202 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 app.maxAdj = SYSTEM_ADJ;
1204 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1205 synchronized (mSelf.mPidsSelfLocked) {
1206 mSelf.mPidsSelfLocked.put(app.pid, app);
1207 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001208 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 }
1210 } catch (PackageManager.NameNotFoundException e) {
1211 throw new RuntimeException(
1212 "Unable to find android system package", e);
1213 }
1214 }
1215
1216 public void setWindowManager(WindowManagerService wm) {
1217 mWindowManager = wm;
1218 }
1219
1220 public static final Context main(int factoryTest) {
1221 AThread thr = new AThread();
1222 thr.start();
1223
1224 synchronized (thr) {
1225 while (thr.mService == null) {
1226 try {
1227 thr.wait();
1228 } catch (InterruptedException e) {
1229 }
1230 }
1231 }
1232
1233 ActivityManagerService m = thr.mService;
1234 mSelf = m;
1235 ActivityThread at = ActivityThread.systemMain();
1236 mSystemThread = at;
1237 Context context = at.getSystemContext();
1238 m.mContext = context;
1239 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001240 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241
1242 m.mBatteryStatsService.publish(context);
1243 m.mUsageStatsService.publish(context);
1244
1245 synchronized (thr) {
1246 thr.mReady = true;
1247 thr.notifyAll();
1248 }
1249
1250 m.startRunning(null, null, null, null);
1251
1252 return context;
1253 }
1254
1255 public static ActivityManagerService self() {
1256 return mSelf;
1257 }
1258
1259 static class AThread extends Thread {
1260 ActivityManagerService mService;
1261 boolean mReady = false;
1262
1263 public AThread() {
1264 super("ActivityManager");
1265 }
1266
1267 public void run() {
1268 Looper.prepare();
1269
1270 android.os.Process.setThreadPriority(
1271 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001272 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273
1274 ActivityManagerService m = new ActivityManagerService();
1275
1276 synchronized (this) {
1277 mService = m;
1278 notifyAll();
1279 }
1280
1281 synchronized (this) {
1282 while (!mReady) {
1283 try {
1284 wait();
1285 } catch (InterruptedException e) {
1286 }
1287 }
1288 }
1289
1290 Looper.loop();
1291 }
1292 }
1293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294 static class MemBinder extends Binder {
1295 ActivityManagerService mActivityManagerService;
1296 MemBinder(ActivityManagerService activityManagerService) {
1297 mActivityManagerService = activityManagerService;
1298 }
1299
1300 @Override
1301 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1302 ActivityManagerService service = mActivityManagerService;
1303 ArrayList<ProcessRecord> procs;
1304 synchronized (mActivityManagerService) {
1305 if (args != null && args.length > 0
1306 && args[0].charAt(0) != '-') {
1307 procs = new ArrayList<ProcessRecord>();
1308 int pid = -1;
1309 try {
1310 pid = Integer.parseInt(args[0]);
1311 } catch (NumberFormatException e) {
1312
1313 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001314 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1315 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 if (proc.pid == pid) {
1317 procs.add(proc);
1318 } else if (proc.processName.equals(args[0])) {
1319 procs.add(proc);
1320 }
1321 }
1322 if (procs.size() <= 0) {
1323 pw.println("No process found for: " + args[0]);
1324 return;
1325 }
1326 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001327 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 }
1329 }
1330 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1331 }
1332 }
1333
1334 static class CpuBinder extends Binder {
1335 ActivityManagerService mActivityManagerService;
1336 CpuBinder(ActivityManagerService activityManagerService) {
1337 mActivityManagerService = activityManagerService;
1338 }
1339
1340 @Override
1341 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1342 synchronized (mActivityManagerService.mProcessStatsThread) {
1343 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1344 }
1345 }
1346 }
1347
1348 private ActivityManagerService() {
1349 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1350 if (v != null && Integer.getInteger(v) != 0) {
1351 mSimpleProcessManagement = true;
1352 }
1353 v = System.getenv("ANDROID_DEBUG_APP");
1354 if (v != null) {
1355 mSimpleProcessManagement = true;
1356 }
1357
Joe Onorato8a9b2202010-02-26 18:56:32 -08001358 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 File dataDir = Environment.getDataDirectory();
1361 File systemDir = new File(dataDir, "system");
1362 systemDir.mkdirs();
1363 mBatteryStatsService = new BatteryStatsService(new File(
1364 systemDir, "batterystats.bin").toString());
1365 mBatteryStatsService.getActiveStatistics().readLocked();
1366 mBatteryStatsService.getActiveStatistics().writeLocked();
1367
1368 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001369 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370
Jack Palevichb90d28c2009-07-22 15:35:24 -07001371 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1372 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1373
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001374 mConfiguration.setToDefaults();
1375 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001376 mProcessStats.init();
1377
1378 // Add ourself to the Watchdog monitors.
1379 Watchdog.getInstance().addMonitor(this);
1380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 mProcessStatsThread = new Thread("ProcessStats") {
1382 public void run() {
1383 while (true) {
1384 try {
1385 try {
1386 synchronized(this) {
1387 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001388 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001390 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 // + ", write delay=" + nextWriteDelay);
1392 if (nextWriteDelay < nextCpuDelay) {
1393 nextCpuDelay = nextWriteDelay;
1394 }
1395 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001396 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 this.wait(nextCpuDelay);
1398 }
1399 }
1400 } catch (InterruptedException e) {
1401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 updateCpuStatsNow();
1403 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001404 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 }
1406 }
1407 }
1408 };
1409 mProcessStatsThread.start();
1410 }
1411
1412 @Override
1413 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1414 throws RemoteException {
1415 try {
1416 return super.onTransact(code, data, reply, flags);
1417 } catch (RuntimeException e) {
1418 // The activity manager only throws security exceptions, so let's
1419 // log all others.
1420 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001421 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422 }
1423 throw e;
1424 }
1425 }
1426
1427 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001428 final long now = SystemClock.uptimeMillis();
1429 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1430 return;
1431 }
1432 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1433 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 mProcessStatsThread.notify();
1435 }
1436 }
1437 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 void updateCpuStatsNow() {
1440 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001441 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 final long now = SystemClock.uptimeMillis();
1443 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001446 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1447 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 haveNewCpuStats = true;
1449 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001450 //Slog.i(TAG, mProcessStats.printCurrentState());
1451 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 // + mProcessStats.getTotalCpuPercent() + "%");
1453
Joe Onorato8a9b2202010-02-26 18:56:32 -08001454 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 if ("true".equals(SystemProperties.get("events.cpu"))) {
1456 int user = mProcessStats.getLastUserTime();
1457 int system = mProcessStats.getLastSystemTime();
1458 int iowait = mProcessStats.getLastIoWaitTime();
1459 int irq = mProcessStats.getLastIrqTime();
1460 int softIrq = mProcessStats.getLastSoftIrqTime();
1461 int idle = mProcessStats.getLastIdleTime();
1462
1463 int total = user + system + iowait + irq + softIrq + idle;
1464 if (total == 0) total = 1;
1465
Doug Zongker2bec3d42009-12-04 12:52:44 -08001466 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 ((user+system+iowait+irq+softIrq) * 100) / total,
1468 (user * 100) / total,
1469 (system * 100) / total,
1470 (iowait * 100) / total,
1471 (irq * 100) / total,
1472 (softIrq * 100) / total);
1473 }
1474 }
1475
Amith Yamasanie43530a2009-08-21 13:11:37 -07001476 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001477 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001478 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 synchronized(mPidsSelfLocked) {
1480 if (haveNewCpuStats) {
1481 if (mBatteryStatsService.isOnBattery()) {
1482 final int N = mProcessStats.countWorkingStats();
1483 for (int i=0; i<N; i++) {
1484 ProcessStats.Stats st
1485 = mProcessStats.getWorkingStats(i);
1486 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1487 if (pr != null) {
1488 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1489 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001490 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001491 } else {
1492 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001493 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001494 if (ps != null) {
1495 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001496 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 }
1499 }
1500 }
1501 }
1502 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1505 mLastWriteTime = now;
1506 mBatteryStatsService.getActiveStatistics().writeLocked();
1507 }
1508 }
1509 }
1510 }
1511
1512 /**
1513 * Initialize the application bind args. These are passed to each
1514 * process when the bindApplication() IPC is sent to the process. They're
1515 * lazily setup to make sure the services are running when they're asked for.
1516 */
1517 private HashMap<String, IBinder> getCommonServicesLocked() {
1518 if (mAppBindArgs == null) {
1519 mAppBindArgs = new HashMap<String, IBinder>();
1520
1521 // Setup the application init args
1522 mAppBindArgs.put("package", ServiceManager.getService("package"));
1523 mAppBindArgs.put("window", ServiceManager.getService("window"));
1524 mAppBindArgs.put(Context.ALARM_SERVICE,
1525 ServiceManager.getService(Context.ALARM_SERVICE));
1526 }
1527 return mAppBindArgs;
1528 }
1529
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001530 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 if (mFocusedActivity != r) {
1532 mFocusedActivity = r;
1533 mWindowManager.setFocusedApp(r, true);
1534 }
1535 }
1536
Dianne Hackborn906497c2010-05-10 15:57:38 -07001537 private final void updateLruProcessInternalLocked(ProcessRecord app,
1538 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001540 int lrui = mLruProcesses.indexOf(app);
1541 if (lrui >= 0) mLruProcesses.remove(lrui);
1542
1543 int i = mLruProcesses.size()-1;
1544 int skipTop = 0;
1545
Dianne Hackborn906497c2010-05-10 15:57:38 -07001546 app.lruSeq = mLruSeq;
1547
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001548 // compute the new weight for this process.
1549 if (updateActivityTime) {
1550 app.lastActivityTime = SystemClock.uptimeMillis();
1551 }
1552 if (app.activities.size() > 0) {
1553 // If this process has activities, we more strongly want to keep
1554 // it around.
1555 app.lruWeight = app.lastActivityTime;
1556 } else if (app.pubProviders.size() > 0) {
1557 // If this process contains content providers, we want to keep
1558 // it a little more strongly.
1559 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1560 // Also don't let it kick out the first few "real" hidden processes.
1561 skipTop = MIN_HIDDEN_APPS;
1562 } else {
1563 // If this process doesn't have activities, we less strongly
1564 // want to keep it around, and generally want to avoid getting
1565 // in front of any very recently used activities.
1566 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1567 // Also don't let it kick out the first few "real" hidden processes.
1568 skipTop = MIN_HIDDEN_APPS;
1569 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001570
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001571 while (i >= 0) {
1572 ProcessRecord p = mLruProcesses.get(i);
1573 // If this app shouldn't be in front of the first N background
1574 // apps, then skip over that many that are currently hidden.
1575 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1576 skipTop--;
1577 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001578 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001579 mLruProcesses.add(i+1, app);
1580 break;
1581 }
1582 i--;
1583 }
1584 if (i < 0) {
1585 mLruProcesses.add(0, app);
1586 }
1587
Dianne Hackborn906497c2010-05-10 15:57:38 -07001588 // If the app is currently using a content provider or service,
1589 // bump those processes as well.
1590 if (app.connections.size() > 0) {
1591 for (ConnectionRecord cr : app.connections) {
1592 if (cr.binding != null && cr.binding.service != null
1593 && cr.binding.service.app != null
1594 && cr.binding.service.app.lruSeq != mLruSeq) {
1595 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1596 updateActivityTime, i+1);
1597 }
1598 }
1599 }
1600 if (app.conProviders.size() > 0) {
1601 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1602 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1603 updateLruProcessInternalLocked(cpr.app, oomAdj,
1604 updateActivityTime, i+1);
1605 }
1606 }
1607 }
1608
Joe Onorato8a9b2202010-02-26 18:56:32 -08001609 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 if (oomAdj) {
1611 updateOomAdjLocked();
1612 }
1613 }
1614
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001615 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001616 boolean oomAdj, boolean updateActivityTime) {
1617 mLruSeq++;
1618 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1619 }
1620
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001621 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 String processName, int uid) {
1623 if (uid == Process.SYSTEM_UID) {
1624 // The system gets to run in any process. If there are multiple
1625 // processes with the same uid, just pick the first (this
1626 // should never happen).
1627 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1628 processName);
1629 return procs != null ? procs.valueAt(0) : null;
1630 }
1631 ProcessRecord proc = mProcessNames.get(processName, uid);
1632 return proc;
1633 }
1634
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001635 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001636 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001637 try {
1638 if (pm.performDexOpt(packageName)) {
1639 mDidDexOpt = true;
1640 }
1641 } catch (RemoteException e) {
1642 }
1643 }
1644
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001645 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 int transit = mWindowManager.getPendingAppTransition();
1647 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1648 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1649 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1650 }
1651
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001652 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001654 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1656 // We don't have to do anything more if:
1657 // (1) There is an existing application record; and
1658 // (2) The caller doesn't think it is dead, OR there is no thread
1659 // object attached to it so we know it couldn't have crashed; and
1660 // (3) There is a pid assigned to it, so it is either starting or
1661 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001662 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 + " app=" + app + " knownToBeDead=" + knownToBeDead
1664 + " thread=" + (app != null ? app.thread : null)
1665 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001666 if (app != null && app.pid > 0) {
1667 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001668 // We already have the app running, or are waiting for it to
1669 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001670 return app;
1671 } else {
1672 // An application record is attached to a previous process,
1673 // clean it up now.
1674 handleAppDiedLocked(app, true);
1675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 String hostingNameStr = hostingName != null
1679 ? hostingName.flattenToShortString() : null;
1680
1681 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1682 // If we are in the background, then check to see if this process
1683 // is bad. If so, we will just silently fail.
1684 if (mBadProcesses.get(info.processName, info.uid) != null) {
1685 return null;
1686 }
1687 } else {
1688 // When the user is explicitly starting a process, then clear its
1689 // crash count so that we won't make it bad until they see at
1690 // least one crash dialog again, and make the process good again
1691 // if it had been bad.
1692 mProcessCrashTimes.remove(info.processName, info.uid);
1693 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001694 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 info.processName);
1696 mBadProcesses.remove(info.processName, info.uid);
1697 if (app != null) {
1698 app.bad = false;
1699 }
1700 }
1701 }
1702
1703 if (app == null) {
1704 app = newProcessRecordLocked(null, info, processName);
1705 mProcessNames.put(processName, info.uid, app);
1706 } else {
1707 // If this is a new package in the process, add the package to the list
1708 app.addPackage(info.packageName);
1709 }
1710
1711 // If the system is not ready yet, then hold off on starting this
1712 // process until it is.
1713 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001714 && !isAllowedWhileBooting(info)
1715 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 if (!mProcessesOnHold.contains(app)) {
1717 mProcessesOnHold.add(app);
1718 }
1719 return app;
1720 }
1721
1722 startProcessLocked(app, hostingType, hostingNameStr);
1723 return (app.pid != 0) ? app : null;
1724 }
1725
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001726 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1727 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1728 }
1729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 private final void startProcessLocked(ProcessRecord app,
1731 String hostingType, String hostingNameStr) {
1732 if (app.pid > 0 && app.pid != MY_PID) {
1733 synchronized (mPidsSelfLocked) {
1734 mPidsSelfLocked.remove(app.pid);
1735 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1736 }
1737 app.pid = 0;
1738 }
1739
1740 mProcessesOnHold.remove(app);
1741
1742 updateCpuStats();
1743
1744 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1745 mProcDeaths[0] = 0;
1746
1747 try {
1748 int uid = app.info.uid;
1749 int[] gids = null;
1750 try {
1751 gids = mContext.getPackageManager().getPackageGids(
1752 app.info.packageName);
1753 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001754 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 }
1756 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1757 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1758 && mTopComponent != null
1759 && app.processName.equals(mTopComponent.getPackageName())) {
1760 uid = 0;
1761 }
1762 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1763 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1764 uid = 0;
1765 }
1766 }
1767 int debugFlags = 0;
1768 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1769 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1770 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001771 // Run the app in safe mode if its manifest requests so or the
1772 // system is booted in safe mode.
1773 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1774 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001775 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1778 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1779 }
1780 if ("1".equals(SystemProperties.get("debug.assert"))) {
1781 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1782 }
1783 int pid = Process.start("android.app.ActivityThread",
1784 mSimpleProcessManagement ? app.processName : null, uid, uid,
1785 gids, debugFlags, null);
1786 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1787 synchronized (bs) {
1788 if (bs.isOnBattery()) {
1789 app.batteryStats.incStartsLocked();
1790 }
1791 }
1792
Doug Zongker2bec3d42009-12-04 12:52:44 -08001793 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 app.processName, hostingType,
1795 hostingNameStr != null ? hostingNameStr : "");
1796
1797 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001798 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 }
1800
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001801 StringBuilder buf = mStringBuilder;
1802 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 buf.append("Start proc ");
1804 buf.append(app.processName);
1805 buf.append(" for ");
1806 buf.append(hostingType);
1807 if (hostingNameStr != null) {
1808 buf.append(" ");
1809 buf.append(hostingNameStr);
1810 }
1811 buf.append(": pid=");
1812 buf.append(pid);
1813 buf.append(" uid=");
1814 buf.append(uid);
1815 buf.append(" gids={");
1816 if (gids != null) {
1817 for (int gi=0; gi<gids.length; gi++) {
1818 if (gi != 0) buf.append(", ");
1819 buf.append(gids[gi]);
1820
1821 }
1822 }
1823 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001824 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 if (pid == 0 || pid == MY_PID) {
1826 // Processes are being emulated with threads.
1827 app.pid = MY_PID;
1828 app.removed = false;
1829 mStartingProcesses.add(app);
1830 } else if (pid > 0) {
1831 app.pid = pid;
1832 app.removed = false;
1833 synchronized (mPidsSelfLocked) {
1834 this.mPidsSelfLocked.put(pid, app);
1835 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1836 msg.obj = app;
1837 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1838 }
1839 } else {
1840 app.pid = 0;
1841 RuntimeException e = new RuntimeException(
1842 "Failure starting process " + app.processName
1843 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001844 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845 }
1846 } catch (RuntimeException e) {
1847 // XXX do better error recovery.
1848 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001849 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 }
1851 }
1852
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001853 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 if (resumed) {
1855 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1856 } else {
1857 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1858 }
1859 }
1860
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001861 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001862 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1863 && mTopAction == null) {
1864 // We are running in factory test mode, but unable to find
1865 // the factory test app, so just sit around displaying the
1866 // error message and don't try to start anything.
1867 return false;
1868 }
1869 Intent intent = new Intent(
1870 mTopAction,
1871 mTopData != null ? Uri.parse(mTopData) : null);
1872 intent.setComponent(mTopComponent);
1873 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1874 intent.addCategory(Intent.CATEGORY_HOME);
1875 }
1876 ActivityInfo aInfo =
1877 intent.resolveActivityInfo(mContext.getPackageManager(),
1878 STOCK_PM_FLAGS);
1879 if (aInfo != null) {
1880 intent.setComponent(new ComponentName(
1881 aInfo.applicationInfo.packageName, aInfo.name));
1882 // Don't do this if the home app is currently being
1883 // instrumented.
1884 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1885 aInfo.applicationInfo.uid);
1886 if (app == null || app.instrumentationClass == null) {
1887 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001888 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001889 null, null, 0, 0, 0, false, false);
1890 }
1891 }
1892
1893
1894 return true;
1895 }
1896
1897 /**
1898 * Starts the "new version setup screen" if appropriate.
1899 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001900 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001901 // Only do this once per boot.
1902 if (mCheckedForSetup) {
1903 return;
1904 }
1905
1906 // We will show this screen if the current one is a different
1907 // version than the last one shown, and we are not running in
1908 // low-level factory test mode.
1909 final ContentResolver resolver = mContext.getContentResolver();
1910 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1911 Settings.Secure.getInt(resolver,
1912 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1913 mCheckedForSetup = true;
1914
1915 // See if we should be showing the platform update setup UI.
1916 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1917 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1918 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1919
1920 // We don't allow third party apps to replace this.
1921 ResolveInfo ri = null;
1922 for (int i=0; ris != null && i<ris.size(); i++) {
1923 if ((ris.get(i).activityInfo.applicationInfo.flags
1924 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1925 ri = ris.get(i);
1926 break;
1927 }
1928 }
1929
1930 if (ri != null) {
1931 String vers = ri.activityInfo.metaData != null
1932 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1933 : null;
1934 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1935 vers = ri.activityInfo.applicationInfo.metaData.getString(
1936 Intent.METADATA_SETUP_VERSION);
1937 }
1938 String lastVers = Settings.Secure.getString(
1939 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1940 if (vers != null && !vers.equals(lastVers)) {
1941 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1942 intent.setComponent(new ComponentName(
1943 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001944 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001945 null, null, 0, 0, 0, false, false);
1946 }
1947 }
1948 }
1949 }
1950
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001951 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001952 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001953
1954 final int identHash = System.identityHashCode(r);
1955 updateUsageStats(r, true);
1956
1957 int i = mWatchers.beginBroadcast();
1958 while (i > 0) {
1959 i--;
1960 IActivityWatcher w = mWatchers.getBroadcastItem(i);
1961 if (w != null) {
1962 try {
1963 w.activityResuming(identHash);
1964 } catch (RemoteException e) {
1965 }
1966 }
1967 }
1968 mWatchers.finishBroadcast();
1969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001971 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001972 final int N = mPendingActivityLaunches.size();
1973 if (N <= 0) {
1974 return;
1975 }
1976 for (int i=0; i<N; i++) {
1977 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001978 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001979 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
1980 doResume && i == (N-1));
1981 }
1982 mPendingActivityLaunches.clear();
1983 }
1984
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001985 public final int startActivity(IApplicationThread caller,
1986 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1987 int grantedMode, IBinder resultTo,
1988 String resultWho, int requestCode, boolean onlyIfNeeded,
1989 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001990 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07001991 grantedUriPermissions, grantedMode, resultTo, resultWho,
1992 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001993 }
1994
1995 public final WaitResult startActivityAndWait(IApplicationThread caller,
1996 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1997 int grantedMode, IBinder resultTo,
1998 String resultWho, int requestCode, boolean onlyIfNeeded,
1999 boolean debug) {
2000 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002001 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002002 grantedUriPermissions, grantedMode, resultTo, resultWho,
2003 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002004 return res;
2005 }
2006
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002007 public final int startActivityWithConfig(IApplicationThread caller,
2008 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2009 int grantedMode, IBinder resultTo,
2010 String resultWho, int requestCode, boolean onlyIfNeeded,
2011 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002012 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002013 grantedUriPermissions, grantedMode, resultTo, resultWho,
2014 requestCode, onlyIfNeeded, debug, null, config);
2015 }
2016
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002017 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002018 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002019 IBinder resultTo, String resultWho, int requestCode,
2020 int flagsMask, int flagsValues) {
2021 // Refuse possible leaked file descriptors
2022 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2023 throw new IllegalArgumentException("File descriptors passed in Intent");
2024 }
2025
2026 IIntentSender sender = intent.getTarget();
2027 if (!(sender instanceof PendingIntentRecord)) {
2028 throw new IllegalArgumentException("Bad PendingIntent object");
2029 }
2030
2031 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002032
2033 synchronized (this) {
2034 // If this is coming from the currently resumed activity, it is
2035 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002036 if (mMainStack.mResumedActivity != null
2037 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002038 Binder.getCallingUid()) {
2039 mAppSwitchesAllowedTime = 0;
2040 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002041 }
2042
2043 return pir.sendInner(0, fillInIntent, resolvedType,
2044 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2045 }
2046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 public boolean startNextMatchingActivity(IBinder callingActivity,
2048 Intent intent) {
2049 // Refuse possible leaked file descriptors
2050 if (intent != null && intent.hasFileDescriptors() == true) {
2051 throw new IllegalArgumentException("File descriptors passed in Intent");
2052 }
2053
2054 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002055 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 if (index < 0) {
2057 return false;
2058 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002059 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002060 if (r.app == null || r.app.thread == null) {
2061 // The caller is not running... d'oh!
2062 return false;
2063 }
2064 intent = new Intent(intent);
2065 // The caller is not allowed to change the data.
2066 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2067 // And we are resetting to find the next component...
2068 intent.setComponent(null);
2069
2070 ActivityInfo aInfo = null;
2071 try {
2072 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002073 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002075 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076
2077 // Look for the original activity in the list...
2078 final int N = resolves != null ? resolves.size() : 0;
2079 for (int i=0; i<N; i++) {
2080 ResolveInfo rInfo = resolves.get(i);
2081 if (rInfo.activityInfo.packageName.equals(r.packageName)
2082 && rInfo.activityInfo.name.equals(r.info.name)) {
2083 // We found the current one... the next matching is
2084 // after it.
2085 i++;
2086 if (i<N) {
2087 aInfo = resolves.get(i).activityInfo;
2088 }
2089 break;
2090 }
2091 }
2092 } catch (RemoteException e) {
2093 }
2094
2095 if (aInfo == null) {
2096 // Nobody who is next!
2097 return false;
2098 }
2099
2100 intent.setComponent(new ComponentName(
2101 aInfo.applicationInfo.packageName, aInfo.name));
2102 intent.setFlags(intent.getFlags()&~(
2103 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2104 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2105 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2106 Intent.FLAG_ACTIVITY_NEW_TASK));
2107
2108 // Okay now we need to start the new activity, replacing the
2109 // currently running activity. This is a little tricky because
2110 // we want to start the new one as if the current one is finished,
2111 // but not finish the current one first so that there is no flicker.
2112 // And thus...
2113 final boolean wasFinishing = r.finishing;
2114 r.finishing = true;
2115
2116 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002117 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 final String resultWho = r.resultWho;
2119 final int requestCode = r.requestCode;
2120 r.resultTo = null;
2121 if (resultTo != null) {
2122 resultTo.removeResultsLocked(r, resultWho, requestCode);
2123 }
2124
2125 final long origId = Binder.clearCallingIdentity();
2126 // XXX we are not dealing with propagating grantedUriPermissions...
2127 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002128 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002130 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131 Binder.restoreCallingIdentity(origId);
2132
2133 r.finishing = wasFinishing;
2134 if (res != START_SUCCESS) {
2135 return false;
2136 }
2137 return true;
2138 }
2139 }
2140
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002141 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 Intent intent, String resolvedType, IBinder resultTo,
2143 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002144
2145 // This is so super not safe, that only the system (or okay root)
2146 // can do it.
2147 final int callingUid = Binder.getCallingUid();
2148 if (callingUid != 0 && callingUid != Process.myUid()) {
2149 throw new SecurityException(
2150 "startActivityInPackage only available to the system");
2151 }
2152
The Android Open Source Project4df24232009-03-05 14:34:35 -08002153 final boolean componentSpecified = intent.getComponent() != null;
2154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 // Don't modify the client's object!
2156 intent = new Intent(intent);
2157
2158 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 ActivityInfo aInfo;
2160 try {
2161 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002162 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002164 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 aInfo = rInfo != null ? rInfo.activityInfo : null;
2166 } catch (RemoteException e) {
2167 aInfo = null;
2168 }
2169
2170 if (aInfo != null) {
2171 // Store the found target back into the intent, because now that
2172 // we have it we never want to do this again. For example, if the
2173 // user navigates back to this point in the history, we should
2174 // always restart the exact same activity.
2175 intent.setComponent(new ComponentName(
2176 aInfo.applicationInfo.packageName, aInfo.name));
2177 }
2178
2179 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002180 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002182 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 }
2184 }
2185
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002186 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 // Remove any existing entries that are the same kind of task.
2188 int N = mRecentTasks.size();
2189 for (int i=0; i<N; i++) {
2190 TaskRecord tr = mRecentTasks.get(i);
2191 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2192 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2193 mRecentTasks.remove(i);
2194 i--;
2195 N--;
2196 if (task.intent == null) {
2197 // If the new recent task we are adding is not fully
2198 // specified, then replace it with the existing recent task.
2199 task = tr;
2200 }
2201 }
2202 }
2203 if (N >= MAX_RECENT_TASKS) {
2204 mRecentTasks.remove(N-1);
2205 }
2206 mRecentTasks.add(0, task);
2207 }
2208
2209 public void setRequestedOrientation(IBinder token,
2210 int requestedOrientation) {
2211 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002212 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 if (index < 0) {
2214 return;
2215 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002216 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002217 final long origId = Binder.clearCallingIdentity();
2218 mWindowManager.setAppOrientation(r, requestedOrientation);
2219 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002220 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 r.mayFreezeScreenLocked(r.app) ? r : null);
2222 if (config != null) {
2223 r.frozenBeforeDestroy = true;
2224 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002225 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002226 }
2227 }
2228 Binder.restoreCallingIdentity(origId);
2229 }
2230 }
2231
2232 public int getRequestedOrientation(IBinder token) {
2233 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002234 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002235 if (index < 0) {
2236 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2237 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002238 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 return mWindowManager.getAppOrientation(r);
2240 }
2241 }
2242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 /**
2244 * This is the internal entry point for handling Activity.finish().
2245 *
2246 * @param token The Binder token referencing the Activity we want to finish.
2247 * @param resultCode Result code, if any, from this Activity.
2248 * @param resultData Result data (Intent), if any, from this Activity.
2249 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002250 * @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 -08002251 */
2252 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2253 // Refuse possible leaked file descriptors
2254 if (resultData != null && resultData.hasFileDescriptors() == true) {
2255 throw new IllegalArgumentException("File descriptors passed in Intent");
2256 }
2257
2258 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002259 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002261 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002262 if (next != null) {
2263 // ask watcher if this is allowed
2264 boolean resumeOK = true;
2265 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002266 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002268 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 }
2270
2271 if (!resumeOK) {
2272 return false;
2273 }
2274 }
2275 }
2276 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002277 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278 resultData, "app-request");
2279 Binder.restoreCallingIdentity(origId);
2280 return res;
2281 }
2282 }
2283
Dianne Hackborn860755f2010-06-03 18:47:52 -07002284 public final void finishHeavyWeightApp() {
2285 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2286 != PackageManager.PERMISSION_GRANTED) {
2287 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2288 + Binder.getCallingPid()
2289 + ", uid=" + Binder.getCallingUid()
2290 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2291 Slog.w(TAG, msg);
2292 throw new SecurityException(msg);
2293 }
2294
2295 synchronized(this) {
2296 if (mHeavyWeightProcess == null) {
2297 return;
2298 }
2299
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002300 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002301 mHeavyWeightProcess.activities);
2302 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002303 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002304 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002305 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002306 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002307 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002308 null, "finish-heavy");
2309 }
2310 }
2311 }
2312
2313 mHeavyWeightProcess = null;
2314 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2315 }
2316 }
2317
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002318 public void crashApplication(int uid, int initialPid, String packageName,
2319 String message) {
2320 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2321 != PackageManager.PERMISSION_GRANTED) {
2322 String msg = "Permission Denial: crashApplication() from pid="
2323 + Binder.getCallingPid()
2324 + ", uid=" + Binder.getCallingUid()
2325 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2326 Slog.w(TAG, msg);
2327 throw new SecurityException(msg);
2328 }
2329
2330 synchronized(this) {
2331 ProcessRecord proc = null;
2332
2333 // Figure out which process to kill. We don't trust that initialPid
2334 // still has any relation to current pids, so must scan through the
2335 // list.
2336 synchronized (mPidsSelfLocked) {
2337 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2338 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2339 if (p.info.uid != uid) {
2340 continue;
2341 }
2342 if (p.pid == initialPid) {
2343 proc = p;
2344 break;
2345 }
2346 for (String str : p.pkgList) {
2347 if (str.equals(packageName)) {
2348 proc = p;
2349 }
2350 }
2351 }
2352 }
2353
2354 if (proc == null) {
2355 Log.w(TAG, "crashApplication: nothing for uid=" + uid
2356 + " initialPid=" + initialPid
2357 + " packageName=" + packageName);
2358 return;
2359 }
2360
2361 if (proc.thread != null) {
2362 long ident = Binder.clearCallingIdentity();
2363 try {
2364 proc.thread.scheduleCrash(message);
2365 } catch (RemoteException e) {
2366 }
2367 Binder.restoreCallingIdentity(ident);
2368 }
2369 }
2370 }
2371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 public final void finishSubActivity(IBinder token, String resultWho,
2373 int requestCode) {
2374 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002375 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 if (index < 0) {
2377 return;
2378 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002379 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380
2381 final long origId = Binder.clearCallingIdentity();
2382
2383 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002384 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2385 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002386 if (r.resultTo == self && r.requestCode == requestCode) {
2387 if ((r.resultWho == null && resultWho == null) ||
2388 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002389 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 Activity.RESULT_CANCELED, null, "request-sub");
2391 }
2392 }
2393 }
2394
2395 Binder.restoreCallingIdentity(origId);
2396 }
2397 }
2398
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002399 public boolean willActivityBeVisible(IBinder token) {
2400 synchronized(this) {
2401 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002402 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2403 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002404 if (r == token) {
2405 return true;
2406 }
2407 if (r.fullscreen && !r.finishing) {
2408 return false;
2409 }
2410 }
2411 return true;
2412 }
2413 }
2414
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002415 public void overridePendingTransition(IBinder token, String packageName,
2416 int enterAnim, int exitAnim) {
2417 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002418 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002419 if (index < 0) {
2420 return;
2421 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002422 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002423
2424 final long origId = Binder.clearCallingIdentity();
2425
2426 if (self.state == ActivityState.RESUMED
2427 || self.state == ActivityState.PAUSING) {
2428 mWindowManager.overridePendingAppTransition(packageName,
2429 enterAnim, exitAnim);
2430 }
2431
2432 Binder.restoreCallingIdentity(origId);
2433 }
2434 }
2435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002437 * Main function for removing an existing process from the activity manager
2438 * as a result of that process going away. Clears out all connections
2439 * to the process.
2440 */
2441 private final void handleAppDiedLocked(ProcessRecord app,
2442 boolean restarting) {
2443 cleanUpApplicationRecordLocked(app, restarting, -1);
2444 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002445 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002446 }
2447
2448 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002449 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2450 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2451 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002452 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002453 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2454 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002455 }
2456
2457 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002458 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002459
2460 boolean atTop = true;
2461 boolean hasVisibleActivities = false;
2462
2463 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002464 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002465 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 TAG, "Removing app " + app + " from history with " + i + " entries");
2467 while (i > 0) {
2468 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002469 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002470 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2472 if (r.app == app) {
2473 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002474 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002475 TAG, "Removing this entry! frozen=" + r.haveState
2476 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002477 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478
2479 r.inHistory = false;
2480 mWindowManager.removeAppToken(r);
2481 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002482 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002483 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002484 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002485
2486 } else {
2487 // We have the current state for this activity, so
2488 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002489 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002490 TAG, "Keeping entry, setting app to null");
2491 if (r.visible) {
2492 hasVisibleActivities = true;
2493 }
2494 r.app = null;
2495 r.nowVisible = false;
2496 if (!r.haveState) {
2497 r.icicle = null;
2498 }
2499 }
2500
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002501 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 r.state = ActivityState.STOPPED;
2503 }
2504 atTop = false;
2505 }
2506
2507 app.activities.clear();
2508
2509 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002510 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 + " running instrumentation " + app.instrumentationClass);
2512 Bundle info = new Bundle();
2513 info.putString("shortMsg", "Process crashed.");
2514 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2515 }
2516
2517 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002518 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002519 // If there was nothing to resume, and we are not already
2520 // restarting this process, but there is a visible activity that
2521 // is hosted by the process... then make sure all visible
2522 // activities are running, taking care of restarting this
2523 // process.
2524 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002525 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 }
2527 }
2528 }
2529 }
2530
2531 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2532 IBinder threadBinder = thread.asBinder();
2533
2534 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002535 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2536 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2538 return i;
2539 }
2540 }
2541 return -1;
2542 }
2543
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002544 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 IApplicationThread thread) {
2546 if (thread == null) {
2547 return null;
2548 }
2549
2550 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002551 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 }
2553
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002554 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 IApplicationThread thread) {
2556
2557 mProcDeaths[0]++;
2558
Magnus Edlund7bb25812010-02-24 15:45:06 +01002559 // Clean up already done if the process has been re-started.
2560 if (app.pid == pid && app.thread != null &&
2561 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002562 if (!app.killedBackground) {
2563 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2564 + ") has died.");
2565 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002566 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002567 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 TAG, "Dying app: " + app + ", pid: " + pid
2569 + ", thread: " + thread.asBinder());
2570 boolean doLowMem = app.instrumentationClass == null;
2571 handleAppDiedLocked(app, false);
2572
2573 if (doLowMem) {
2574 // If there are no longer any background processes running,
2575 // and the app that died was not running instrumentation,
2576 // then tell everyone we are now low on memory.
2577 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002578 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2579 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2581 haveBg = true;
2582 break;
2583 }
2584 }
2585
2586 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002587 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002588 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002589 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002590 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2591 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002592 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002593 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2594 // The low memory report is overriding any current
2595 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002596 // heavy/important/visible/foreground processes first.
2597 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002598 rec.lastRequestedGc = 0;
2599 } else {
2600 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002602 rec.reportLowMemory = true;
2603 rec.lastLowMemory = now;
2604 mProcessesToGc.remove(rec);
2605 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002606 }
2607 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002608 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 }
2610 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002611 } else if (app.pid != pid) {
2612 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002613 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002614 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002615 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002616 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002617 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 + thread.asBinder());
2619 }
2620 }
2621
Dan Egnor42471dd2010-01-07 17:25:22 -08002622 /**
2623 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002624 * @param clearTraces causes the dump file to be erased prior to the new
2625 * traces being written, if true; when false, the new traces will be
2626 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08002627 * @param pids of dalvik VM processes to dump stack traces for
2628 * @return file containing stack traces, or null if no dump file is configured
2629 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07002630 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002631 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2632 if (tracesPath == null || tracesPath.length() == 0) {
2633 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002635
2636 File tracesFile = new File(tracesPath);
2637 try {
2638 File tracesDir = tracesFile.getParentFile();
2639 if (!tracesDir.exists()) tracesFile.mkdirs();
2640 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2641
Christopher Tate6ee412d2010-05-28 12:01:56 -07002642 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002643 tracesFile.createNewFile();
2644 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2645 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002646 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002647 return null;
2648 }
2649
2650 // Use a FileObserver to detect when traces finish writing.
2651 // The order of traces is considered important to maintain for legibility.
2652 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2653 public synchronized void onEvent(int event, String path) { notify(); }
2654 };
2655
2656 try {
2657 observer.startWatching();
2658 int num = pids.size();
2659 for (int i = 0; i < num; i++) {
2660 synchronized (observer) {
2661 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
2662 observer.wait(200); // Wait for write-close, give up after 200msec
2663 }
2664 }
2665 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08002666 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002667 } finally {
2668 observer.stopWatching();
2669 }
2670
2671 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 }
2673
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002674 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2675 ActivityRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002676 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002677
2678 synchronized (this) {
2679 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2680 if (mShuttingDown) {
2681 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2682 return;
2683 } else if (app.notResponding) {
2684 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2685 return;
2686 } else if (app.crashing) {
2687 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2688 return;
2689 }
2690
2691 // In case we come through here for the same app before completing
2692 // this one, mark as anring now so we will bail out.
2693 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002694
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002695 // Log the ANR to the event log.
2696 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2697 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002698
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002699 // Dump thread traces as quickly as we can, starting with "interesting" processes.
2700 pids.add(app.pid);
2701
2702 int parentPid = app.pid;
2703 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
2704 if (parentPid != app.pid) pids.add(parentPid);
2705
2706 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002707
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002708 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2709 ProcessRecord r = mLruProcesses.get(i);
2710 if (r != null && r.thread != null) {
2711 int pid = r.pid;
2712 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
2713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 }
2715 }
2716
Christopher Tate6ee412d2010-05-28 12:01:56 -07002717 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002718
2719 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002720 StringBuilder info = mStringBuilder;
2721 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002722 info.append("ANR in ").append(app.processName);
2723 if (activity != null && activity.shortComponentName != null) {
2724 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002725 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002726 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002728 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002730 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002731 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002733
Dan Egnor42471dd2010-01-07 17:25:22 -08002734 String cpuInfo = null;
2735 if (MONITOR_CPU_USAGE) {
2736 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002737 synchronized (mProcessStatsThread) {
2738 cpuInfo = mProcessStats.printCurrentState();
2739 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002740 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 }
2742
Joe Onorato8a9b2202010-02-26 18:56:32 -08002743 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002744 if (tracesFile == null) {
2745 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2746 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2747 }
2748
2749 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2750
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002751 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002753 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2754 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002756 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2757 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002758 }
2759 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002760 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 }
2762 }
2763
Dan Egnor42471dd2010-01-07 17:25:22 -08002764 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2765 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2766 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002767
2768 synchronized (this) {
2769 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2770 Process.killProcess(app.pid);
2771 return;
2772 }
2773
2774 // Set the app's notResponding state, and look up the errorReportReceiver
2775 makeAppNotRespondingLocked(app,
2776 activity != null ? activity.shortComponentName : null,
2777 annotation != null ? "ANR " + annotation : "ANR",
2778 info.toString());
2779
2780 // Bring up the infamous App Not Responding dialog
2781 Message msg = Message.obtain();
2782 HashMap map = new HashMap();
2783 msg.what = SHOW_NOT_RESPONDING_MSG;
2784 msg.obj = map;
2785 map.put("app", app);
2786 if (activity != null) {
2787 map.put("activity", activity);
2788 }
2789
2790 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 }
2793
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002794 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 app.persistentActivities--;
2796 if (app.persistentActivities > 0) {
2797 // Still more of 'em...
2798 return;
2799 }
2800 if (app.persistent) {
2801 // Ah, but the application itself is persistent. Whatever!
2802 return;
2803 }
2804
2805 // App is no longer persistent... make sure it and the ones
2806 // following it in the LRU list have the correc oom_adj.
2807 updateOomAdjLocked();
2808 }
2809
2810 public void setPersistent(IBinder token, boolean isPersistent) {
2811 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2812 != PackageManager.PERMISSION_GRANTED) {
2813 String msg = "Permission Denial: setPersistent() from pid="
2814 + Binder.getCallingPid()
2815 + ", uid=" + Binder.getCallingUid()
2816 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002817 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002818 throw new SecurityException(msg);
2819 }
2820
2821 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002822 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 if (index < 0) {
2824 return;
2825 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002826 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827 ProcessRecord app = r.app;
2828
Joe Onorato8a9b2202010-02-26 18:56:32 -08002829 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002830 TAG, "Setting persistence " + isPersistent + ": " + r);
2831
2832 if (isPersistent) {
2833 if (r.persistent) {
2834 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002835 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836 return;
2837 }
2838 r.persistent = true;
2839 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002840 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841 if (app.persistentActivities > 1) {
2842 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002843 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002844 return;
2845 }
2846 if (app.persistent) {
2847 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002848 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002849 return;
2850 }
2851
2852 // App is now persistent... make sure it and the ones
2853 // following it now have the correct oom_adj.
2854 final long origId = Binder.clearCallingIdentity();
2855 updateOomAdjLocked();
2856 Binder.restoreCallingIdentity(origId);
2857
2858 } else {
2859 if (!r.persistent) {
2860 // Okay okay, I heard you already!
2861 return;
2862 }
2863 r.persistent = false;
2864 final long origId = Binder.clearCallingIdentity();
2865 decPersistentCountLocked(app);
2866 Binder.restoreCallingIdentity(origId);
2867
2868 }
2869 }
2870 }
2871
2872 public boolean clearApplicationUserData(final String packageName,
2873 final IPackageDataObserver observer) {
2874 int uid = Binder.getCallingUid();
2875 int pid = Binder.getCallingPid();
2876 long callingId = Binder.clearCallingIdentity();
2877 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002878 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 int pkgUid = -1;
2880 synchronized(this) {
2881 try {
2882 pkgUid = pm.getPackageUid(packageName);
2883 } catch (RemoteException e) {
2884 }
2885 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002886 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 return false;
2888 }
2889 if (uid == pkgUid || checkComponentPermission(
2890 android.Manifest.permission.CLEAR_APP_USER_DATA,
2891 pid, uid, -1)
2892 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08002893 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 } else {
2895 throw new SecurityException(pid+" does not have permission:"+
2896 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
2897 "for process:"+packageName);
2898 }
2899 }
2900
2901 try {
2902 //clear application user data
2903 pm.clearApplicationUserData(packageName, observer);
2904 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
2905 Uri.fromParts("package", packageName, null));
2906 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06002907 synchronized (this) {
2908 broadcastIntentLocked(null, null, intent,
2909 null, null, 0, null, null, null,
2910 false, false, MY_PID, Process.SYSTEM_UID);
2911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 } catch (RemoteException e) {
2913 }
2914 } finally {
2915 Binder.restoreCallingIdentity(callingId);
2916 }
2917 return true;
2918 }
2919
Dianne Hackborn03abb812010-01-04 18:43:19 -08002920 public void killBackgroundProcesses(final String packageName) {
2921 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
2922 != PackageManager.PERMISSION_GRANTED &&
2923 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
2924 != PackageManager.PERMISSION_GRANTED) {
2925 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002926 + Binder.getCallingPid()
2927 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08002928 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002929 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 throw new SecurityException(msg);
2931 }
2932
2933 long callingId = Binder.clearCallingIdentity();
2934 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002935 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 int pkgUid = -1;
2937 synchronized(this) {
2938 try {
2939 pkgUid = pm.getPackageUid(packageName);
2940 } catch (RemoteException e) {
2941 }
2942 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002943 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 return;
2945 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08002946 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002947 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002948 }
2949 } finally {
2950 Binder.restoreCallingIdentity(callingId);
2951 }
2952 }
2953
2954 public void forceStopPackage(final String packageName) {
2955 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2956 != PackageManager.PERMISSION_GRANTED) {
2957 String msg = "Permission Denial: forceStopPackage() from pid="
2958 + Binder.getCallingPid()
2959 + ", uid=" + Binder.getCallingUid()
2960 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002961 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002962 throw new SecurityException(msg);
2963 }
2964
2965 long callingId = Binder.clearCallingIdentity();
2966 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002967 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08002968 int pkgUid = -1;
2969 synchronized(this) {
2970 try {
2971 pkgUid = pm.getPackageUid(packageName);
2972 } catch (RemoteException e) {
2973 }
2974 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002975 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002976 return;
2977 }
2978 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979 }
2980 } finally {
2981 Binder.restoreCallingIdentity(callingId);
2982 }
2983 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002984
2985 /*
2986 * The pkg name and uid have to be specified.
2987 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
2988 */
2989 public void killApplicationWithUid(String pkg, int uid) {
2990 if (pkg == null) {
2991 return;
2992 }
2993 // Make sure the uid is valid.
2994 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002995 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002996 return;
2997 }
2998 int callerUid = Binder.getCallingUid();
2999 // Only the system server can kill an application
3000 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003001 // Post an aysnc message to kill the application
3002 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3003 msg.arg1 = uid;
3004 msg.arg2 = 0;
3005 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003006 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003007 } else {
3008 throw new SecurityException(callerUid + " cannot kill pkg: " +
3009 pkg);
3010 }
3011 }
3012
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003013 public void closeSystemDialogs(String reason) {
3014 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3015 if (reason != null) {
3016 intent.putExtra("reason", reason);
3017 }
3018
3019 final int uid = Binder.getCallingUid();
3020 final long origId = Binder.clearCallingIdentity();
3021 synchronized (this) {
3022 int i = mWatchers.beginBroadcast();
3023 while (i > 0) {
3024 i--;
3025 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3026 if (w != null) {
3027 try {
3028 w.closingSystemDialogs(reason);
3029 } catch (RemoteException e) {
3030 }
3031 }
3032 }
3033 mWatchers.finishBroadcast();
3034
Dianne Hackbornffa42482009-09-23 22:20:11 -07003035 mWindowManager.closeSystemDialogs(reason);
3036
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003037 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3038 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003039 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003040 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003041 Activity.RESULT_CANCELED, null, "close-sys");
3042 }
3043 }
3044
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003045 broadcastIntentLocked(null, null, intent, null,
3046 null, 0, null, null, null, false, false, -1, uid);
3047 }
3048 Binder.restoreCallingIdentity(origId);
3049 }
3050
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003051 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003052 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003053 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3054 for (int i=pids.length-1; i>=0; i--) {
3055 infos[i] = new Debug.MemoryInfo();
3056 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003057 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003058 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003059 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003060
3061 public void killApplicationProcess(String processName, int uid) {
3062 if (processName == null) {
3063 return;
3064 }
3065
3066 int callerUid = Binder.getCallingUid();
3067 // Only the system server can kill an application
3068 if (callerUid == Process.SYSTEM_UID) {
3069 synchronized (this) {
3070 ProcessRecord app = getProcessRecordLocked(processName, uid);
3071 if (app != null) {
3072 try {
3073 app.thread.scheduleSuicide();
3074 } catch (RemoteException e) {
3075 // If the other end already died, then our work here is done.
3076 }
3077 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003078 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003079 + processName + " / " + uid);
3080 }
3081 }
3082 } else {
3083 throw new SecurityException(callerUid + " cannot kill app process: " +
3084 processName);
3085 }
3086 }
3087
Dianne Hackborn03abb812010-01-04 18:43:19 -08003088 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003089 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3091 Uri.fromParts("package", packageName, null));
3092 intent.putExtra(Intent.EXTRA_UID, uid);
3093 broadcastIntentLocked(null, null, intent,
3094 null, null, 0, null, null, null,
3095 false, false, MY_PID, Process.SYSTEM_UID);
3096 }
3097
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003098 private final boolean killPackageProcessesLocked(String packageName, int uid,
3099 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003100 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101
Dianne Hackborn03abb812010-01-04 18:43:19 -08003102 // Remove all processes this package may have touched: all with the
3103 // same UID (except for the system or root user), and all whose name
3104 // matches the package name.
3105 final String procNamePrefix = packageName + ":";
3106 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3107 final int NA = apps.size();
3108 for (int ia=0; ia<NA; ia++) {
3109 ProcessRecord app = apps.valueAt(ia);
3110 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003111 if (doit) {
3112 procs.add(app);
3113 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003114 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3115 || app.processName.equals(packageName)
3116 || app.processName.startsWith(procNamePrefix)) {
3117 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003118 if (!doit) {
3119 return true;
3120 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003121 app.removed = true;
3122 procs.add(app);
3123 }
3124 }
3125 }
3126 }
3127
3128 int N = procs.size();
3129 for (int i=0; i<N; i++) {
3130 removeProcessLocked(procs.get(i), callerWillRestart);
3131 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003132 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003133 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003134
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003135 private final boolean forceStopPackageLocked(String name, int uid,
3136 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 int i, N;
3138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003139 if (uid < 0) {
3140 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003141 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 } catch (RemoteException e) {
3143 }
3144 }
3145
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003146 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003147 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003148
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003149 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3150 while (badApps.hasNext()) {
3151 SparseArray<Long> ba = badApps.next();
3152 if (ba.get(uid) != null) {
3153 badApps.remove();
3154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003155 }
3156 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003157
3158 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3159 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003161 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3162 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003164 if (!doit) {
3165 return true;
3166 }
3167 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003168 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003169 if (r.app != null) {
3170 r.app.removed = true;
3171 }
3172 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003173 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003174 }
3175 }
3176
3177 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3178 for (ServiceRecord service : mServices.values()) {
3179 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003180 if (!doit) {
3181 return true;
3182 }
3183 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003184 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003185 if (service.app != null) {
3186 service.app.removed = true;
3187 }
3188 service.app = null;
3189 services.add(service);
3190 }
3191 }
3192
3193 N = services.size();
3194 for (i=0; i<N; i++) {
3195 bringDownServiceLocked(services.get(i), true);
3196 }
3197
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003198 if (doit) {
3199 if (purgeCache) {
3200 AttributeCache ac = AttributeCache.instance();
3201 if (ac != null) {
3202 ac.removePackage(name);
3203 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003204 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003205 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003206 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003207
3208 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003209 }
3210
3211 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3212 final String name = app.processName;
3213 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003214 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003215 TAG, "Force removing process " + app + " (" + name
3216 + "/" + uid + ")");
3217
3218 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003219 if (mHeavyWeightProcess == app) {
3220 mHeavyWeightProcess = null;
3221 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003223 boolean needRestart = false;
3224 if (app.pid > 0 && app.pid != MY_PID) {
3225 int pid = app.pid;
3226 synchronized (mPidsSelfLocked) {
3227 mPidsSelfLocked.remove(pid);
3228 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3229 }
3230 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003231 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 Process.killProcess(pid);
3233
3234 if (app.persistent) {
3235 if (!callerWillRestart) {
3236 addAppLocked(app.info);
3237 } else {
3238 needRestart = true;
3239 }
3240 }
3241 } else {
3242 mRemovedProcesses.add(app);
3243 }
3244
3245 return needRestart;
3246 }
3247
3248 private final void processStartTimedOutLocked(ProcessRecord app) {
3249 final int pid = app.pid;
3250 boolean gone = false;
3251 synchronized (mPidsSelfLocked) {
3252 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3253 if (knownApp != null && knownApp.thread == null) {
3254 mPidsSelfLocked.remove(pid);
3255 gone = true;
3256 }
3257 }
3258
3259 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003260 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003261 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003262 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003264 if (mHeavyWeightProcess == app) {
3265 mHeavyWeightProcess = null;
3266 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3267 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003268 // Take care of any launching providers waiting for this process.
3269 checkAppInLaunchingProvidersLocked(app, true);
3270 // Take care of any services that are waiting for the process.
3271 for (int i=0; i<mPendingServices.size(); i++) {
3272 ServiceRecord sr = mPendingServices.get(i);
3273 if (app.info.uid == sr.appInfo.uid
3274 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003275 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003276 mPendingServices.remove(i);
3277 i--;
3278 bringDownServiceLocked(sr, true);
3279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003280 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003281 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003282 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003283 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003284 try {
3285 IBackupManager bm = IBackupManager.Stub.asInterface(
3286 ServiceManager.getService(Context.BACKUP_SERVICE));
3287 bm.agentDisconnected(app.info.packageName);
3288 } catch (RemoteException e) {
3289 // Can't happen; the backup manager is local
3290 }
3291 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003292 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003293 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003294 mPendingBroadcast = null;
3295 scheduleBroadcastsLocked();
3296 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003297 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003298 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 }
3300 }
3301
3302 private final boolean attachApplicationLocked(IApplicationThread thread,
3303 int pid) {
3304
3305 // Find the application record that is being attached... either via
3306 // the pid if we are running in multiple processes, or just pull the
3307 // next app record if we are emulating process with anonymous threads.
3308 ProcessRecord app;
3309 if (pid != MY_PID && pid >= 0) {
3310 synchronized (mPidsSelfLocked) {
3311 app = mPidsSelfLocked.get(pid);
3312 }
3313 } else if (mStartingProcesses.size() > 0) {
3314 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003315 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 } else {
3317 app = null;
3318 }
3319
3320 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003321 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003322 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003323 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 if (pid > 0 && pid != MY_PID) {
3325 Process.killProcess(pid);
3326 } else {
3327 try {
3328 thread.scheduleExit();
3329 } catch (Exception e) {
3330 // Ignore exceptions.
3331 }
3332 }
3333 return false;
3334 }
3335
3336 // If this application record is still attached to a previous
3337 // process, clean it up now.
3338 if (app.thread != null) {
3339 handleAppDiedLocked(app, true);
3340 }
3341
3342 // Tell the process all about itself.
3343
Joe Onorato8a9b2202010-02-26 18:56:32 -08003344 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 TAG, "Binding process pid " + pid + " to record " + app);
3346
3347 String processName = app.processName;
3348 try {
3349 thread.asBinder().linkToDeath(new AppDeathRecipient(
3350 app, pid, thread), 0);
3351 } catch (RemoteException e) {
3352 app.resetPackageList();
3353 startProcessLocked(app, "link fail", processName);
3354 return false;
3355 }
3356
Doug Zongker2bec3d42009-12-04 12:52:44 -08003357 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358
3359 app.thread = thread;
3360 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003361 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3362 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 app.forcingToForeground = null;
3364 app.foregroundServices = false;
3365 app.debugging = false;
3366
3367 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3368
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003369 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3370 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003372 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003373 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003374 }
3375
Joe Onorato8a9b2202010-02-26 18:56:32 -08003376 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003377 TAG, "New app record " + app
3378 + " thread=" + thread.asBinder() + " pid=" + pid);
3379 try {
3380 int testMode = IApplicationThread.DEBUG_OFF;
3381 if (mDebugApp != null && mDebugApp.equals(processName)) {
3382 testMode = mWaitForDebugger
3383 ? IApplicationThread.DEBUG_WAIT
3384 : IApplicationThread.DEBUG_ON;
3385 app.debugging = true;
3386 if (mDebugTransient) {
3387 mDebugApp = mOrigDebugApp;
3388 mWaitForDebugger = mOrigWaitForDebugger;
3389 }
3390 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003391
Christopher Tate181fafa2009-05-14 11:12:14 -07003392 // If the app is being launched for restore or full backup, set it up specially
3393 boolean isRestrictedBackupMode = false;
3394 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3395 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3396 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3397 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003398
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003399 ensurePackageDexOpt(app.instrumentationInfo != null
3400 ? app.instrumentationInfo.packageName
3401 : app.info.packageName);
3402 if (app.instrumentationClass != null) {
3403 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003404 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003405 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003406 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003407 thread.bindApplication(processName, app.instrumentationInfo != null
3408 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 app.instrumentationClass, app.instrumentationProfileFile,
3410 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003411 isRestrictedBackupMode || !normalMode,
3412 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003413 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003414 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003415 } catch (Exception e) {
3416 // todo: Yikes! What should we do? For now we will try to
3417 // start another process, but that could easily get us in
3418 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003419 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420
3421 app.resetPackageList();
3422 startProcessLocked(app, "bind fail", processName);
3423 return false;
3424 }
3425
3426 // Remove this record from the list of starting applications.
3427 mPersistentStartingProcesses.remove(app);
3428 mProcessesOnHold.remove(app);
3429
3430 boolean badApp = false;
3431 boolean didSomething = false;
3432
3433 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003434 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003435 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3437 && processName.equals(hr.processName)) {
3438 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003439 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 didSomething = true;
3441 }
3442 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003443 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 + hr.intent.getComponent().flattenToShortString(), e);
3445 badApp = true;
3446 }
3447 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003448 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 }
3450 }
3451
3452 // Find any services that should be running in this process...
3453 if (!badApp && mPendingServices.size() > 0) {
3454 ServiceRecord sr = null;
3455 try {
3456 for (int i=0; i<mPendingServices.size(); i++) {
3457 sr = mPendingServices.get(i);
3458 if (app.info.uid != sr.appInfo.uid
3459 || !processName.equals(sr.processName)) {
3460 continue;
3461 }
3462
3463 mPendingServices.remove(i);
3464 i--;
3465 realStartServiceLocked(sr, app);
3466 didSomething = true;
3467 }
3468 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003469 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 + sr.shortName, e);
3471 badApp = true;
3472 }
3473 }
3474
3475 // Check if the next broadcast receiver is in this process...
3476 BroadcastRecord br = mPendingBroadcast;
3477 if (!badApp && br != null && br.curApp == app) {
3478 try {
3479 mPendingBroadcast = null;
3480 processCurBroadcastLocked(br, app);
3481 didSomething = true;
3482 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003483 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 + br.curComponent.flattenToShortString(), e);
3485 badApp = true;
3486 logBroadcastReceiverDiscard(br);
3487 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3488 br.resultExtras, br.resultAbort, true);
3489 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003490 // We need to reset the state if we fails to start the receiver.
3491 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 }
3493 }
3494
Christopher Tate181fafa2009-05-14 11:12:14 -07003495 // Check whether the next backup agent is in this process...
3496 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003497 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003498 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003499 try {
3500 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3501 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003502 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003503 e.printStackTrace();
3504 }
3505 }
3506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 if (badApp) {
3508 // todo: Also need to kill application to deal with all
3509 // kinds of exceptions.
3510 handleAppDiedLocked(app, false);
3511 return false;
3512 }
3513
3514 if (!didSomething) {
3515 updateOomAdjLocked();
3516 }
3517
3518 return true;
3519 }
3520
3521 public final void attachApplication(IApplicationThread thread) {
3522 synchronized (this) {
3523 int callingPid = Binder.getCallingPid();
3524 final long origId = Binder.clearCallingIdentity();
3525 attachApplicationLocked(thread, callingPid);
3526 Binder.restoreCallingIdentity(origId);
3527 }
3528 }
3529
Dianne Hackborne88846e2009-09-30 21:34:25 -07003530 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003532 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 Binder.restoreCallingIdentity(origId);
3534 }
3535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003537 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003538 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 mWindowManager.enableScreenAfterBoot();
3540 }
3541
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003542 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003543 IntentFilter pkgFilter = new IntentFilter();
3544 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3545 pkgFilter.addDataScheme("package");
3546 mContext.registerReceiver(new BroadcastReceiver() {
3547 @Override
3548 public void onReceive(Context context, Intent intent) {
3549 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3550 if (pkgs != null) {
3551 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003552 synchronized (ActivityManagerService.this) {
3553 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3554 setResultCode(Activity.RESULT_OK);
3555 return;
3556 }
3557 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003558 }
3559 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003560 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003561 }, pkgFilter);
3562
3563 synchronized (this) {
3564 // Ensure that any processes we had put on hold are now started
3565 // up.
3566 final int NP = mProcessesOnHold.size();
3567 if (NP > 0) {
3568 ArrayList<ProcessRecord> procs =
3569 new ArrayList<ProcessRecord>(mProcessesOnHold);
3570 for (int ip=0; ip<NP; ip++) {
3571 this.startProcessLocked(procs.get(ip), "on-hold", null);
3572 }
3573 }
3574
3575 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
3576 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003577 broadcastIntentLocked(null, null,
3578 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3579 null, null, 0, null, null,
3580 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3581 false, false, MY_PID, Process.SYSTEM_UID);
3582 }
3583 }
3584 }
3585
3586 final void ensureBootCompleted() {
3587 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003588 boolean enableScreen;
3589 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003590 booting = mBooting;
3591 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003592 enableScreen = !mBooted;
3593 mBooted = true;
3594 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003595
3596 if (booting) {
3597 finishBooting();
3598 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003599
3600 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003601 enableScreenAfterBoot();
3602 }
3603 }
3604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 public final void activityPaused(IBinder token, Bundle icicle) {
3606 // Refuse possible leaked file descriptors
3607 if (icicle != null && icicle.hasFileDescriptors()) {
3608 throw new IllegalArgumentException("File descriptors passed in Bundle");
3609 }
3610
3611 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003612 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 Binder.restoreCallingIdentity(origId);
3614 }
3615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 public final void activityStopped(IBinder token, Bitmap thumbnail,
3617 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003618 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619 TAG, "Activity stopped: token=" + token);
3620
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003621 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622
3623 final long origId = Binder.clearCallingIdentity();
3624
3625 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003626 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003628 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 r.thumbnail = thumbnail;
3630 r.description = description;
3631 r.stopped = true;
3632 r.state = ActivityState.STOPPED;
3633 if (!r.finishing) {
3634 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003635 r.stack.destroyActivityLocked(r, true);
3636 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 }
3638 }
3639 }
3640 }
3641
3642 if (r != null) {
3643 sendPendingThumbnail(r, null, null, null, false);
3644 }
3645
3646 trimApplications();
3647
3648 Binder.restoreCallingIdentity(origId);
3649 }
3650
3651 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003652 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003653 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654 }
3655
3656 public String getCallingPackage(IBinder token) {
3657 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003658 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003659 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 }
3661 }
3662
3663 public ComponentName getCallingActivity(IBinder token) {
3664 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003665 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 return r != null ? r.intent.getComponent() : null;
3667 }
3668 }
3669
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003670 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003671 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003673 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 if (r != null) {
3675 return r.resultTo;
3676 }
3677 }
3678 return null;
3679 }
3680
3681 public ComponentName getActivityClassForToken(IBinder token) {
3682 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003683 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003685 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 return r.intent.getComponent();
3687 }
3688 return null;
3689 }
3690 }
3691
3692 public String getPackageForToken(IBinder token) {
3693 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003694 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003696 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 return r.packageName;
3698 }
3699 return null;
3700 }
3701 }
3702
3703 public IIntentSender getIntentSender(int type,
3704 String packageName, IBinder token, String resultWho,
3705 int requestCode, Intent intent, String resolvedType, int flags) {
3706 // Refuse possible leaked file descriptors
3707 if (intent != null && intent.hasFileDescriptors() == true) {
3708 throw new IllegalArgumentException("File descriptors passed in Intent");
3709 }
3710
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003711 if (type == INTENT_SENDER_BROADCAST) {
3712 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3713 throw new IllegalArgumentException(
3714 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3715 }
3716 }
3717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 synchronized(this) {
3719 int callingUid = Binder.getCallingUid();
3720 try {
3721 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3722 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003723 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 .getPackageUid(packageName);
3725 if (uid != Binder.getCallingUid()) {
3726 String msg = "Permission Denial: getIntentSender() from pid="
3727 + Binder.getCallingPid()
3728 + ", uid=" + Binder.getCallingUid()
3729 + ", (need uid=" + uid + ")"
3730 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003731 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 throw new SecurityException(msg);
3733 }
3734 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003735
3736 return getIntentSenderLocked(type, packageName, callingUid,
3737 token, resultWho, requestCode, intent, resolvedType, flags);
3738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003739 } catch (RemoteException e) {
3740 throw new SecurityException(e);
3741 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003742 }
3743 }
3744
3745 IIntentSender getIntentSenderLocked(int type,
3746 String packageName, int callingUid, IBinder token, String resultWho,
3747 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003748 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003749 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003750 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003751 if (index < 0) {
3752 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003753 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003754 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003755 if (activity.finishing) {
3756 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003758 }
3759
3760 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3761 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3762 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3763 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3764 |PendingIntent.FLAG_UPDATE_CURRENT);
3765
3766 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3767 type, packageName, activity, resultWho,
3768 requestCode, intent, resolvedType, flags);
3769 WeakReference<PendingIntentRecord> ref;
3770 ref = mIntentSenderRecords.get(key);
3771 PendingIntentRecord rec = ref != null ? ref.get() : null;
3772 if (rec != null) {
3773 if (!cancelCurrent) {
3774 if (updateCurrent) {
3775 rec.key.requestIntent.replaceExtras(intent);
3776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003777 return rec;
3778 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003779 rec.canceled = true;
3780 mIntentSenderRecords.remove(key);
3781 }
3782 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 return rec;
3784 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003785 rec = new PendingIntentRecord(this, key, callingUid);
3786 mIntentSenderRecords.put(key, rec.ref);
3787 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3788 if (activity.pendingResults == null) {
3789 activity.pendingResults
3790 = new HashSet<WeakReference<PendingIntentRecord>>();
3791 }
3792 activity.pendingResults.add(rec.ref);
3793 }
3794 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795 }
3796
3797 public void cancelIntentSender(IIntentSender sender) {
3798 if (!(sender instanceof PendingIntentRecord)) {
3799 return;
3800 }
3801 synchronized(this) {
3802 PendingIntentRecord rec = (PendingIntentRecord)sender;
3803 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003804 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 .getPackageUid(rec.key.packageName);
3806 if (uid != Binder.getCallingUid()) {
3807 String msg = "Permission Denial: cancelIntentSender() from pid="
3808 + Binder.getCallingPid()
3809 + ", uid=" + Binder.getCallingUid()
3810 + " is not allowed to cancel packges "
3811 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003812 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 throw new SecurityException(msg);
3814 }
3815 } catch (RemoteException e) {
3816 throw new SecurityException(e);
3817 }
3818 cancelIntentSenderLocked(rec, true);
3819 }
3820 }
3821
3822 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3823 rec.canceled = true;
3824 mIntentSenderRecords.remove(rec.key);
3825 if (cleanActivity && rec.key.activity != null) {
3826 rec.key.activity.pendingResults.remove(rec.ref);
3827 }
3828 }
3829
3830 public String getPackageForIntentSender(IIntentSender pendingResult) {
3831 if (!(pendingResult instanceof PendingIntentRecord)) {
3832 return null;
3833 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003834 try {
3835 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3836 return res.key.packageName;
3837 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003838 }
3839 return null;
3840 }
3841
3842 public void setProcessLimit(int max) {
3843 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3844 "setProcessLimit()");
3845 mProcessLimit = max;
3846 }
3847
3848 public int getProcessLimit() {
3849 return mProcessLimit;
3850 }
3851
3852 void foregroundTokenDied(ForegroundToken token) {
3853 synchronized (ActivityManagerService.this) {
3854 synchronized (mPidsSelfLocked) {
3855 ForegroundToken cur
3856 = mForegroundProcesses.get(token.pid);
3857 if (cur != token) {
3858 return;
3859 }
3860 mForegroundProcesses.remove(token.pid);
3861 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3862 if (pr == null) {
3863 return;
3864 }
3865 pr.forcingToForeground = null;
3866 pr.foregroundServices = false;
3867 }
3868 updateOomAdjLocked();
3869 }
3870 }
3871
3872 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3873 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3874 "setProcessForeground()");
3875 synchronized(this) {
3876 boolean changed = false;
3877
3878 synchronized (mPidsSelfLocked) {
3879 ProcessRecord pr = mPidsSelfLocked.get(pid);
3880 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003881 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 return;
3883 }
3884 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3885 if (oldToken != null) {
3886 oldToken.token.unlinkToDeath(oldToken, 0);
3887 mForegroundProcesses.remove(pid);
3888 pr.forcingToForeground = null;
3889 changed = true;
3890 }
3891 if (isForeground && token != null) {
3892 ForegroundToken newToken = new ForegroundToken() {
3893 public void binderDied() {
3894 foregroundTokenDied(this);
3895 }
3896 };
3897 newToken.pid = pid;
3898 newToken.token = token;
3899 try {
3900 token.linkToDeath(newToken, 0);
3901 mForegroundProcesses.put(pid, newToken);
3902 pr.forcingToForeground = token;
3903 changed = true;
3904 } catch (RemoteException e) {
3905 // If the process died while doing this, we will later
3906 // do the cleanup with the process death link.
3907 }
3908 }
3909 }
3910
3911 if (changed) {
3912 updateOomAdjLocked();
3913 }
3914 }
3915 }
3916
3917 // =========================================================
3918 // PERMISSIONS
3919 // =========================================================
3920
3921 static class PermissionController extends IPermissionController.Stub {
3922 ActivityManagerService mActivityManagerService;
3923 PermissionController(ActivityManagerService activityManagerService) {
3924 mActivityManagerService = activityManagerService;
3925 }
3926
3927 public boolean checkPermission(String permission, int pid, int uid) {
3928 return mActivityManagerService.checkPermission(permission, pid,
3929 uid) == PackageManager.PERMISSION_GRANTED;
3930 }
3931 }
3932
3933 /**
3934 * This can be called with or without the global lock held.
3935 */
3936 int checkComponentPermission(String permission, int pid, int uid,
3937 int reqUid) {
3938 // We might be performing an operation on behalf of an indirect binder
3939 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
3940 // client identity accordingly before proceeding.
3941 Identity tlsIdentity = sCallerIdentity.get();
3942 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003943 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
3945 uid = tlsIdentity.uid;
3946 pid = tlsIdentity.pid;
3947 }
3948
3949 // Root, system server and our own process get to do everything.
3950 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
3951 !Process.supportsProcesses()) {
3952 return PackageManager.PERMISSION_GRANTED;
3953 }
3954 // If the target requires a specific UID, always fail for others.
3955 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003956 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 return PackageManager.PERMISSION_DENIED;
3958 }
3959 if (permission == null) {
3960 return PackageManager.PERMISSION_GRANTED;
3961 }
3962 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003963 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 .checkUidPermission(permission, uid);
3965 } catch (RemoteException e) {
3966 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003967 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 }
3969 return PackageManager.PERMISSION_DENIED;
3970 }
3971
3972 /**
3973 * As the only public entry point for permissions checking, this method
3974 * can enforce the semantic that requesting a check on a null global
3975 * permission is automatically denied. (Internally a null permission
3976 * string is used when calling {@link #checkComponentPermission} in cases
3977 * when only uid-based security is needed.)
3978 *
3979 * This can be called with or without the global lock held.
3980 */
3981 public int checkPermission(String permission, int pid, int uid) {
3982 if (permission == null) {
3983 return PackageManager.PERMISSION_DENIED;
3984 }
3985 return checkComponentPermission(permission, pid, uid, -1);
3986 }
3987
3988 /**
3989 * Binder IPC calls go through the public entry point.
3990 * This can be called with or without the global lock held.
3991 */
3992 int checkCallingPermission(String permission) {
3993 return checkPermission(permission,
3994 Binder.getCallingPid(),
3995 Binder.getCallingUid());
3996 }
3997
3998 /**
3999 * This can be called with or without the global lock held.
4000 */
4001 void enforceCallingPermission(String permission, String func) {
4002 if (checkCallingPermission(permission)
4003 == PackageManager.PERMISSION_GRANTED) {
4004 return;
4005 }
4006
4007 String msg = "Permission Denial: " + func + " from pid="
4008 + Binder.getCallingPid()
4009 + ", uid=" + Binder.getCallingUid()
4010 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004011 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 throw new SecurityException(msg);
4013 }
4014
4015 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4016 ProviderInfo pi, int uid, int modeFlags) {
4017 try {
4018 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4019 if ((pi.readPermission != null) &&
4020 (pm.checkUidPermission(pi.readPermission, uid)
4021 != PackageManager.PERMISSION_GRANTED)) {
4022 return false;
4023 }
4024 }
4025 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4026 if ((pi.writePermission != null) &&
4027 (pm.checkUidPermission(pi.writePermission, uid)
4028 != PackageManager.PERMISSION_GRANTED)) {
4029 return false;
4030 }
4031 }
4032 return true;
4033 } catch (RemoteException e) {
4034 return false;
4035 }
4036 }
4037
4038 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4039 int modeFlags) {
4040 // Root gets to do everything.
4041 if (uid == 0 || !Process.supportsProcesses()) {
4042 return true;
4043 }
4044 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4045 if (perms == null) return false;
4046 UriPermission perm = perms.get(uri);
4047 if (perm == null) return false;
4048 return (modeFlags&perm.modeFlags) == modeFlags;
4049 }
4050
4051 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4052 // Another redirected-binder-call permissions check as in
4053 // {@link checkComponentPermission}.
4054 Identity tlsIdentity = sCallerIdentity.get();
4055 if (tlsIdentity != null) {
4056 uid = tlsIdentity.uid;
4057 pid = tlsIdentity.pid;
4058 }
4059
4060 // Our own process gets to do everything.
4061 if (pid == MY_PID) {
4062 return PackageManager.PERMISSION_GRANTED;
4063 }
4064 synchronized(this) {
4065 return checkUriPermissionLocked(uri, uid, modeFlags)
4066 ? PackageManager.PERMISSION_GRANTED
4067 : PackageManager.PERMISSION_DENIED;
4068 }
4069 }
4070
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004071 void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004072 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4074 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4075 if (modeFlags == 0) {
4076 return;
4077 }
4078
Joe Onorato8a9b2202010-02-26 18:56:32 -08004079 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004080 "Requested grant " + targetPkg + " permission to " + uri);
4081
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004082 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004083
4084 // If this is not a content: uri, we can't do anything with it.
4085 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004086 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004087 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 return;
4089 }
4090
4091 String name = uri.getAuthority();
4092 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004093 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004094 if (cpr != null) {
4095 pi = cpr.info;
4096 } else {
4097 try {
4098 pi = pm.resolveContentProvider(name,
4099 PackageManager.GET_URI_PERMISSION_PATTERNS);
4100 } catch (RemoteException ex) {
4101 }
4102 }
4103 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004104 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004105 return;
4106 }
4107
4108 int targetUid;
4109 try {
4110 targetUid = pm.getPackageUid(targetPkg);
4111 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004112 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004113 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004114 return;
4115 }
4116 } catch (RemoteException ex) {
4117 return;
4118 }
4119
4120 // First... does the target actually need this permission?
4121 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4122 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004123 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004124 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 return;
4126 }
4127
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004128 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004129 if (!pi.grantUriPermissions) {
4130 throw new SecurityException("Provider " + pi.packageName
4131 + "/" + pi.name
4132 + " does not allow granting of Uri permissions (uri "
4133 + uri + ")");
4134 }
4135 if (pi.uriPermissionPatterns != null) {
4136 final int N = pi.uriPermissionPatterns.length;
4137 boolean allowed = false;
4138 for (int i=0; i<N; i++) {
4139 if (pi.uriPermissionPatterns[i] != null
4140 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4141 allowed = true;
4142 break;
4143 }
4144 }
4145 if (!allowed) {
4146 throw new SecurityException("Provider " + pi.packageName
4147 + "/" + pi.name
4148 + " does not allow granting of permission to path of Uri "
4149 + uri);
4150 }
4151 }
4152
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004153 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004154 // this uri?
4155 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4156 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4157 throw new SecurityException("Uid " + callingUid
4158 + " does not have permission to uri " + uri);
4159 }
4160 }
4161
4162 // Okay! So here we are: the caller has the assumed permission
4163 // to the uri, and the target doesn't. Let's now give this to
4164 // the target.
4165
Joe Onorato8a9b2202010-02-26 18:56:32 -08004166 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004167 "Granting " + targetPkg + " permission to " + uri);
4168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 HashMap<Uri, UriPermission> targetUris
4170 = mGrantedUriPermissions.get(targetUid);
4171 if (targetUris == null) {
4172 targetUris = new HashMap<Uri, UriPermission>();
4173 mGrantedUriPermissions.put(targetUid, targetUris);
4174 }
4175
4176 UriPermission perm = targetUris.get(uri);
4177 if (perm == null) {
4178 perm = new UriPermission(targetUid, uri);
4179 targetUris.put(uri, perm);
4180
4181 }
4182 perm.modeFlags |= modeFlags;
4183 if (activity == null) {
4184 perm.globalModeFlags |= modeFlags;
4185 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4186 perm.readActivities.add(activity);
4187 if (activity.readUriPermissions == null) {
4188 activity.readUriPermissions = new HashSet<UriPermission>();
4189 }
4190 activity.readUriPermissions.add(perm);
4191 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4192 perm.writeActivities.add(activity);
4193 if (activity.writeUriPermissions == null) {
4194 activity.writeUriPermissions = new HashSet<UriPermission>();
4195 }
4196 activity.writeUriPermissions.add(perm);
4197 }
4198 }
4199
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004200 void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004201 String targetPkg, Intent intent, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 if (intent == null) {
4203 return;
4204 }
4205 Uri data = intent.getData();
4206 if (data == null) {
4207 return;
4208 }
4209 grantUriPermissionLocked(callingUid, targetPkg, data,
4210 intent.getFlags(), activity);
4211 }
4212
4213 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4214 Uri uri, int modeFlags) {
4215 synchronized(this) {
4216 final ProcessRecord r = getRecordForAppLocked(caller);
4217 if (r == null) {
4218 throw new SecurityException("Unable to find app for caller "
4219 + caller
4220 + " when granting permission to uri " + uri);
4221 }
4222 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004223 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 return;
4225 }
4226 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004227 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 return;
4229 }
4230
4231 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4232 null);
4233 }
4234 }
4235
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004236 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4238 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4239 HashMap<Uri, UriPermission> perms
4240 = mGrantedUriPermissions.get(perm.uid);
4241 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004242 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004243 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004244 perms.remove(perm.uri);
4245 if (perms.size() == 0) {
4246 mGrantedUriPermissions.remove(perm.uid);
4247 }
4248 }
4249 }
4250 }
4251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004252 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4253 int modeFlags) {
4254 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4255 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4256 if (modeFlags == 0) {
4257 return;
4258 }
4259
Joe Onorato8a9b2202010-02-26 18:56:32 -08004260 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004261 "Revoking all granted permissions to " + uri);
4262
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004263 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264
4265 final String authority = uri.getAuthority();
4266 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004267 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004268 if (cpr != null) {
4269 pi = cpr.info;
4270 } else {
4271 try {
4272 pi = pm.resolveContentProvider(authority,
4273 PackageManager.GET_URI_PERMISSION_PATTERNS);
4274 } catch (RemoteException ex) {
4275 }
4276 }
4277 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004278 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004279 return;
4280 }
4281
4282 // Does the caller have this permission on the URI?
4283 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4284 // Right now, if you are not the original owner of the permission,
4285 // you are not allowed to revoke it.
4286 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4287 throw new SecurityException("Uid " + callingUid
4288 + " does not have permission to uri " + uri);
4289 //}
4290 }
4291
4292 // Go through all of the permissions and remove any that match.
4293 final List<String> SEGMENTS = uri.getPathSegments();
4294 if (SEGMENTS != null) {
4295 final int NS = SEGMENTS.size();
4296 int N = mGrantedUriPermissions.size();
4297 for (int i=0; i<N; i++) {
4298 HashMap<Uri, UriPermission> perms
4299 = mGrantedUriPermissions.valueAt(i);
4300 Iterator<UriPermission> it = perms.values().iterator();
4301 toploop:
4302 while (it.hasNext()) {
4303 UriPermission perm = it.next();
4304 Uri targetUri = perm.uri;
4305 if (!authority.equals(targetUri.getAuthority())) {
4306 continue;
4307 }
4308 List<String> targetSegments = targetUri.getPathSegments();
4309 if (targetSegments == null) {
4310 continue;
4311 }
4312 if (targetSegments.size() < NS) {
4313 continue;
4314 }
4315 for (int j=0; j<NS; j++) {
4316 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4317 continue toploop;
4318 }
4319 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004320 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004321 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004322 perm.clearModes(modeFlags);
4323 if (perm.modeFlags == 0) {
4324 it.remove();
4325 }
4326 }
4327 if (perms.size() == 0) {
4328 mGrantedUriPermissions.remove(
4329 mGrantedUriPermissions.keyAt(i));
4330 N--;
4331 i--;
4332 }
4333 }
4334 }
4335 }
4336
4337 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4338 int modeFlags) {
4339 synchronized(this) {
4340 final ProcessRecord r = getRecordForAppLocked(caller);
4341 if (r == null) {
4342 throw new SecurityException("Unable to find app for caller "
4343 + caller
4344 + " when revoking permission to uri " + uri);
4345 }
4346 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004347 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 return;
4349 }
4350
4351 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4352 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4353 if (modeFlags == 0) {
4354 return;
4355 }
4356
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004357 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358
4359 final String authority = uri.getAuthority();
4360 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004361 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362 if (cpr != null) {
4363 pi = cpr.info;
4364 } else {
4365 try {
4366 pi = pm.resolveContentProvider(authority,
4367 PackageManager.GET_URI_PERMISSION_PATTERNS);
4368 } catch (RemoteException ex) {
4369 }
4370 }
4371 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004372 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 return;
4374 }
4375
4376 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4377 }
4378 }
4379
4380 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4381 synchronized (this) {
4382 ProcessRecord app =
4383 who != null ? getRecordForAppLocked(who) : null;
4384 if (app == null) return;
4385
4386 Message msg = Message.obtain();
4387 msg.what = WAIT_FOR_DEBUGGER_MSG;
4388 msg.obj = app;
4389 msg.arg1 = waiting ? 1 : 0;
4390 mHandler.sendMessage(msg);
4391 }
4392 }
4393
4394 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4395 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004396 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004398 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399 }
4400
4401 // =========================================================
4402 // TASK MANAGEMENT
4403 // =========================================================
4404
4405 public List getTasks(int maxNum, int flags,
4406 IThumbnailReceiver receiver) {
4407 ArrayList list = new ArrayList();
4408
4409 PendingThumbnailsRecord pending = null;
4410 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004411 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412
4413 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004414 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4416 + ", receiver=" + receiver);
4417
4418 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4419 != PackageManager.PERMISSION_GRANTED) {
4420 if (receiver != null) {
4421 // If the caller wants to wait for pending thumbnails,
4422 // it ain't gonna get them.
4423 try {
4424 receiver.finished();
4425 } catch (RemoteException ex) {
4426 }
4427 }
4428 String msg = "Permission Denial: getTasks() from pid="
4429 + Binder.getCallingPid()
4430 + ", uid=" + Binder.getCallingUid()
4431 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004432 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004433 throw new SecurityException(msg);
4434 }
4435
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004436 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004437 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004438 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004439 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 CharSequence topDescription = null;
4441 TaskRecord curTask = null;
4442 int numActivities = 0;
4443 int numRunning = 0;
4444 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004445 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004446 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004447 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448
4449 // Initialize state for next task if needed.
4450 if (top == null ||
4451 (top.state == ActivityState.INITIALIZING
4452 && top.task == r.task)) {
4453 top = r;
4454 topDescription = r.description;
4455 curTask = r.task;
4456 numActivities = numRunning = 0;
4457 }
4458
4459 // Add 'r' into the current task.
4460 numActivities++;
4461 if (r.app != null && r.app.thread != null) {
4462 numRunning++;
4463 }
4464 if (topDescription == null) {
4465 topDescription = r.description;
4466 }
4467
Joe Onorato8a9b2202010-02-26 18:56:32 -08004468 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004469 TAG, r.intent.getComponent().flattenToShortString()
4470 + ": task=" + r.task);
4471
4472 // If the next one is a different task, generate a new
4473 // TaskInfo entry for what we have.
4474 if (next == null || next.task != curTask) {
4475 ActivityManager.RunningTaskInfo ci
4476 = new ActivityManager.RunningTaskInfo();
4477 ci.id = curTask.taskId;
4478 ci.baseActivity = r.intent.getComponent();
4479 ci.topActivity = top.intent.getComponent();
4480 ci.thumbnail = top.thumbnail;
4481 ci.description = topDescription;
4482 ci.numActivities = numActivities;
4483 ci.numRunning = numRunning;
4484 //System.out.println(
4485 // "#" + maxNum + ": " + " descr=" + ci.description);
4486 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004487 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 TAG, "State=" + top.state + "Idle=" + top.idle
4489 + " app=" + top.app
4490 + " thr=" + (top.app != null ? top.app.thread : null));
4491 if (top.state == ActivityState.RESUMED
4492 || top.state == ActivityState.PAUSING) {
4493 if (top.idle && top.app != null
4494 && top.app.thread != null) {
4495 topRecord = top;
4496 topThumbnail = top.app.thread;
4497 } else {
4498 top.thumbnailNeeded = true;
4499 }
4500 }
4501 if (pending == null) {
4502 pending = new PendingThumbnailsRecord(receiver);
4503 }
4504 pending.pendingRecords.add(top);
4505 }
4506 list.add(ci);
4507 maxNum--;
4508 top = null;
4509 }
4510 }
4511
4512 if (pending != null) {
4513 mPendingThumbnails.add(pending);
4514 }
4515 }
4516
Joe Onorato8a9b2202010-02-26 18:56:32 -08004517 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518
4519 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004520 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 try {
4522 topThumbnail.requestThumbnail(topRecord);
4523 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004524 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004525 sendPendingThumbnail(null, topRecord, null, null, true);
4526 }
4527 }
4528
4529 if (pending == null && receiver != null) {
4530 // In this case all thumbnails were available and the client
4531 // is being asked to be told when the remaining ones come in...
4532 // which is unusually, since the top-most currently running
4533 // activity should never have a canned thumbnail! Oh well.
4534 try {
4535 receiver.finished();
4536 } catch (RemoteException ex) {
4537 }
4538 }
4539
4540 return list;
4541 }
4542
4543 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4544 int flags) {
4545 synchronized (this) {
4546 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4547 "getRecentTasks()");
4548
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004549 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 final int N = mRecentTasks.size();
4552 ArrayList<ActivityManager.RecentTaskInfo> res
4553 = new ArrayList<ActivityManager.RecentTaskInfo>(
4554 maxNum < N ? maxNum : N);
4555 for (int i=0; i<N && maxNum > 0; i++) {
4556 TaskRecord tr = mRecentTasks.get(i);
4557 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4558 || (tr.intent == null)
4559 || ((tr.intent.getFlags()
4560 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4561 ActivityManager.RecentTaskInfo rti
4562 = new ActivityManager.RecentTaskInfo();
4563 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4564 rti.baseIntent = new Intent(
4565 tr.intent != null ? tr.intent : tr.affinityIntent);
4566 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004567
4568 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4569 // Check whether this activity is currently available.
4570 try {
4571 if (rti.origActivity != null) {
4572 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4573 continue;
4574 }
4575 } else if (rti.baseIntent != null) {
4576 if (pm.queryIntentActivities(rti.baseIntent,
4577 null, 0) == null) {
4578 continue;
4579 }
4580 }
4581 } catch (RemoteException e) {
4582 // Will never happen.
4583 }
4584 }
4585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 res.add(rti);
4587 maxNum--;
4588 }
4589 }
4590 return res;
4591 }
4592 }
4593
4594 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4595 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004596 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 TaskRecord jt = startTask;
4598
4599 // First look backwards
4600 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004601 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 if (r.task != jt) {
4603 jt = r.task;
4604 if (affinity.equals(jt.affinity)) {
4605 return j;
4606 }
4607 }
4608 }
4609
4610 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004611 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004612 jt = startTask;
4613 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004614 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004615 if (r.task != jt) {
4616 if (affinity.equals(jt.affinity)) {
4617 return j;
4618 }
4619 jt = r.task;
4620 }
4621 }
4622
4623 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004624 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 return N-1;
4626 }
4627
4628 return -1;
4629 }
4630
4631 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004632 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 */
4634 public void moveTaskToFront(int task) {
4635 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4636 "moveTaskToFront()");
4637
4638 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004639 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4640 Binder.getCallingUid(), "Task to front")) {
4641 return;
4642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 final long origId = Binder.clearCallingIdentity();
4644 try {
4645 int N = mRecentTasks.size();
4646 for (int i=0; i<N; i++) {
4647 TaskRecord tr = mRecentTasks.get(i);
4648 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004649 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 return;
4651 }
4652 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004653 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4654 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004656 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004657 return;
4658 }
4659 }
4660 } finally {
4661 Binder.restoreCallingIdentity(origId);
4662 }
4663 }
4664 }
4665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 public void moveTaskToBack(int task) {
4667 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4668 "moveTaskToBack()");
4669
4670 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004671 if (mMainStack.mResumedActivity != null
4672 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004673 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4674 Binder.getCallingUid(), "Task to back")) {
4675 return;
4676 }
4677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004679 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004680 Binder.restoreCallingIdentity(origId);
4681 }
4682 }
4683
4684 /**
4685 * Moves an activity, and all of the other activities within the same task, to the bottom
4686 * of the history stack. The activity's order within the task is unchanged.
4687 *
4688 * @param token A reference to the activity we wish to move
4689 * @param nonRoot If false then this only works if the activity is the root
4690 * of a task; if true it will work for any activity in a task.
4691 * @return Returns true if the move completed, false if not.
4692 */
4693 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4694 synchronized(this) {
4695 final long origId = Binder.clearCallingIdentity();
4696 int taskId = getTaskForActivityLocked(token, !nonRoot);
4697 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004698 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004699 }
4700 Binder.restoreCallingIdentity(origId);
4701 }
4702 return false;
4703 }
4704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 public void moveTaskBackwards(int task) {
4706 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4707 "moveTaskBackwards()");
4708
4709 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004710 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4711 Binder.getCallingUid(), "Task backwards")) {
4712 return;
4713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004714 final long origId = Binder.clearCallingIdentity();
4715 moveTaskBackwardsLocked(task);
4716 Binder.restoreCallingIdentity(origId);
4717 }
4718 }
4719
4720 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004721 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 }
4723
4724 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4725 synchronized(this) {
4726 return getTaskForActivityLocked(token, onlyRoot);
4727 }
4728 }
4729
4730 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004731 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 TaskRecord lastTask = null;
4733 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004734 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735 if (r == token) {
4736 if (!onlyRoot || lastTask != r.task) {
4737 return r.task.taskId;
4738 }
4739 return -1;
4740 }
4741 lastTask = r.task;
4742 }
4743
4744 return -1;
4745 }
4746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 public void finishOtherInstances(IBinder token, ComponentName className) {
4748 synchronized(this) {
4749 final long origId = Binder.clearCallingIdentity();
4750
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004751 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752 TaskRecord lastTask = null;
4753 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004754 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004755 if (r.realActivity.equals(className)
4756 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004757 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004758 null, "others")) {
4759 i--;
4760 N--;
4761 }
4762 }
4763 lastTask = r.task;
4764 }
4765
4766 Binder.restoreCallingIdentity(origId);
4767 }
4768 }
4769
4770 // =========================================================
4771 // THUMBNAILS
4772 // =========================================================
4773
4774 public void reportThumbnail(IBinder token,
4775 Bitmap thumbnail, CharSequence description) {
4776 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4777 final long origId = Binder.clearCallingIdentity();
4778 sendPendingThumbnail(null, token, thumbnail, description, true);
4779 Binder.restoreCallingIdentity(origId);
4780 }
4781
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004782 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 Bitmap thumbnail, CharSequence description, boolean always) {
4784 TaskRecord task = null;
4785 ArrayList receivers = null;
4786
4787 //System.out.println("Send pending thumbnail: " + r);
4788
4789 synchronized(this) {
4790 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004791 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 if (index < 0) {
4793 return;
4794 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004795 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 }
4797 if (thumbnail == null) {
4798 thumbnail = r.thumbnail;
4799 description = r.description;
4800 }
4801 if (thumbnail == null && !always) {
4802 // If there is no thumbnail, and this entry is not actually
4803 // going away, then abort for now and pick up the next
4804 // thumbnail we get.
4805 return;
4806 }
4807 task = r.task;
4808
4809 int N = mPendingThumbnails.size();
4810 int i=0;
4811 while (i<N) {
4812 PendingThumbnailsRecord pr =
4813 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4814 //System.out.println("Looking in " + pr.pendingRecords);
4815 if (pr.pendingRecords.remove(r)) {
4816 if (receivers == null) {
4817 receivers = new ArrayList();
4818 }
4819 receivers.add(pr);
4820 if (pr.pendingRecords.size() == 0) {
4821 pr.finished = true;
4822 mPendingThumbnails.remove(i);
4823 N--;
4824 continue;
4825 }
4826 }
4827 i++;
4828 }
4829 }
4830
4831 if (receivers != null) {
4832 final int N = receivers.size();
4833 for (int i=0; i<N; i++) {
4834 try {
4835 PendingThumbnailsRecord pr =
4836 (PendingThumbnailsRecord)receivers.get(i);
4837 pr.receiver.newThumbnail(
4838 task != null ? task.taskId : -1, thumbnail, description);
4839 if (pr.finished) {
4840 pr.receiver.finished();
4841 }
4842 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004843 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 }
4845 }
4846 }
4847 }
4848
4849 // =========================================================
4850 // CONTENT PROVIDERS
4851 // =========================================================
4852
4853 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4854 List providers = null;
4855 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004856 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004858 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004859 } catch (RemoteException ex) {
4860 }
4861 if (providers != null) {
4862 final int N = providers.size();
4863 for (int i=0; i<N; i++) {
4864 ProviderInfo cpi =
4865 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004866 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004867 if (cpr == null) {
4868 cpr = new ContentProviderRecord(cpi, app.info);
4869 mProvidersByClass.put(cpi.name, cpr);
4870 }
4871 app.pubProviders.put(cpi.name, cpr);
4872 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004873 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 }
4875 }
4876 return providers;
4877 }
4878
4879 private final String checkContentProviderPermissionLocked(
4880 ProviderInfo cpi, ProcessRecord r, int mode) {
4881 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
4882 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
4883 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
4884 cpi.exported ? -1 : cpi.applicationInfo.uid)
4885 == PackageManager.PERMISSION_GRANTED
4886 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4887 return null;
4888 }
4889 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
4890 cpi.exported ? -1 : cpi.applicationInfo.uid)
4891 == PackageManager.PERMISSION_GRANTED) {
4892 return null;
4893 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004894
4895 PathPermission[] pps = cpi.pathPermissions;
4896 if (pps != null) {
4897 int i = pps.length;
4898 while (i > 0) {
4899 i--;
4900 PathPermission pp = pps[i];
4901 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
4902 cpi.exported ? -1 : cpi.applicationInfo.uid)
4903 == PackageManager.PERMISSION_GRANTED
4904 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4905 return null;
4906 }
4907 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
4908 cpi.exported ? -1 : cpi.applicationInfo.uid)
4909 == PackageManager.PERMISSION_GRANTED) {
4910 return null;
4911 }
4912 }
4913 }
4914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 String msg = "Permission Denial: opening provider " + cpi.name
4916 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
4917 + ", uid=" + callingUid + ") requires "
4918 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004919 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004920 return msg;
4921 }
4922
4923 private final ContentProviderHolder getContentProviderImpl(
4924 IApplicationThread caller, String name) {
4925 ContentProviderRecord cpr;
4926 ProviderInfo cpi = null;
4927
4928 synchronized(this) {
4929 ProcessRecord r = null;
4930 if (caller != null) {
4931 r = getRecordForAppLocked(caller);
4932 if (r == null) {
4933 throw new SecurityException(
4934 "Unable to find app for caller " + caller
4935 + " (pid=" + Binder.getCallingPid()
4936 + ") when getting content provider " + name);
4937 }
4938 }
4939
4940 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07004941 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 if (cpr != null) {
4943 cpi = cpr.info;
4944 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
4945 return new ContentProviderHolder(cpi,
4946 cpi.readPermission != null
4947 ? cpi.readPermission : cpi.writePermission);
4948 }
4949
4950 if (r != null && cpr.canRunHere(r)) {
4951 // This provider has been published or is in the process
4952 // of being published... but it is also allowed to run
4953 // in the caller's process, so don't make a connection
4954 // and just let the caller instantiate its own instance.
4955 if (cpr.provider != null) {
4956 // don't give caller the provider object, it needs
4957 // to make its own.
4958 cpr = new ContentProviderRecord(cpr);
4959 }
4960 return cpr;
4961 }
4962
4963 final long origId = Binder.clearCallingIdentity();
4964
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004965 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004966 // return it right away.
4967 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004968 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004969 "Adding provider requested by "
4970 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004971 + cpr.info.processName);
4972 Integer cnt = r.conProviders.get(cpr);
4973 if (cnt == null) {
4974 r.conProviders.put(cpr, new Integer(1));
4975 } else {
4976 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
4977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07004979 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
4980 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07004981 // make sure to count it as being accessed and thus
4982 // back up on the LRU list. This is good because
4983 // content providers are often expensive to start.
4984 updateLruProcessLocked(cpr.app, false, true);
4985 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07004986 } else {
4987 cpr.externals++;
4988 }
4989
4990 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004991 updateOomAdjLocked(cpr.app);
4992 }
4993
4994 Binder.restoreCallingIdentity(origId);
4995
4996 } else {
4997 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004998 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07004999 resolveContentProvider(name,
5000 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 } catch (RemoteException ex) {
5002 }
5003 if (cpi == null) {
5004 return null;
5005 }
5006
5007 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
5008 return new ContentProviderHolder(cpi,
5009 cpi.readPermission != null
5010 ? cpi.readPermission : cpi.writePermission);
5011 }
5012
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005013 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5014 && !cpi.processName.equals("system")) {
5015 // If this content provider does not run in the system
5016 // process, and the system is not yet ready to run other
5017 // processes, then fail fast instead of hanging.
5018 throw new IllegalArgumentException(
5019 "Attempt to launch content provider before system ready");
5020 }
5021
Dianne Hackborn860755f2010-06-03 18:47:52 -07005022 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 final boolean firstClass = cpr == null;
5024 if (firstClass) {
5025 try {
5026 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005027 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005028 getApplicationInfo(
5029 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005030 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005031 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005032 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005033 + cpi.name);
5034 return null;
5035 }
5036 cpr = new ContentProviderRecord(cpi, ai);
5037 } catch (RemoteException ex) {
5038 // pm is in same process, this will never happen.
5039 }
5040 }
5041
5042 if (r != null && cpr.canRunHere(r)) {
5043 // If this is a multiprocess provider, then just return its
5044 // info and allow the caller to instantiate it. Only do
5045 // this if the provider is the same user as the caller's
5046 // process, or can run as root (so can be in any process).
5047 return cpr;
5048 }
5049
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005050 if (DEBUG_PROVIDER) {
5051 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005052 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005053 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005054 }
5055
5056 // This is single process, and our app is now connecting to it.
5057 // See if we are already in the process of launching this
5058 // provider.
5059 final int N = mLaunchingProviders.size();
5060 int i;
5061 for (i=0; i<N; i++) {
5062 if (mLaunchingProviders.get(i) == cpr) {
5063 break;
5064 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 }
5066
5067 // If the provider is not already being launched, then get it
5068 // started.
5069 if (i >= N) {
5070 final long origId = Binder.clearCallingIdentity();
5071 ProcessRecord proc = startProcessLocked(cpi.processName,
5072 cpr.appInfo, false, 0, "content provider",
5073 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005074 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005075 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005076 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 + cpi.applicationInfo.packageName + "/"
5078 + cpi.applicationInfo.uid + " for provider "
5079 + name + ": process is bad");
5080 return null;
5081 }
5082 cpr.launchingApp = proc;
5083 mLaunchingProviders.add(cpr);
5084 Binder.restoreCallingIdentity(origId);
5085 }
5086
5087 // Make sure the provider is published (the same provider class
5088 // may be published under multiple names).
5089 if (firstClass) {
5090 mProvidersByClass.put(cpi.name, cpr);
5091 }
5092 mProvidersByName.put(name, cpr);
5093
5094 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005095 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005096 "Adding provider requested by "
5097 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005098 + cpr.info.processName);
5099 Integer cnt = r.conProviders.get(cpr);
5100 if (cnt == null) {
5101 r.conProviders.put(cpr, new Integer(1));
5102 } else {
5103 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 cpr.clients.add(r);
5106 } else {
5107 cpr.externals++;
5108 }
5109 }
5110 }
5111
5112 // Wait for the provider to be published...
5113 synchronized (cpr) {
5114 while (cpr.provider == null) {
5115 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005116 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005117 + cpi.applicationInfo.packageName + "/"
5118 + cpi.applicationInfo.uid + " for provider "
5119 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005120 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 cpi.applicationInfo.packageName,
5122 cpi.applicationInfo.uid, name);
5123 return null;
5124 }
5125 try {
5126 cpr.wait();
5127 } catch (InterruptedException ex) {
5128 }
5129 }
5130 }
5131 return cpr;
5132 }
5133
5134 public final ContentProviderHolder getContentProvider(
5135 IApplicationThread caller, String name) {
5136 if (caller == null) {
5137 String msg = "null IApplicationThread when getting content provider "
5138 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005139 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 throw new SecurityException(msg);
5141 }
5142
5143 return getContentProviderImpl(caller, name);
5144 }
5145
5146 private ContentProviderHolder getContentProviderExternal(String name) {
5147 return getContentProviderImpl(null, name);
5148 }
5149
5150 /**
5151 * Drop a content provider from a ProcessRecord's bookkeeping
5152 * @param cpr
5153 */
5154 public void removeContentProvider(IApplicationThread caller, String name) {
5155 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005156 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005157 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005158 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005159 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005160 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005161 return;
5162 }
5163 final ProcessRecord r = getRecordForAppLocked(caller);
5164 if (r == null) {
5165 throw new SecurityException(
5166 "Unable to find app for caller " + caller +
5167 " when removing content provider " + name);
5168 }
5169 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005170 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005171 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005172 + r.info.processName + " from process "
5173 + localCpr.appInfo.processName);
5174 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005176 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005177 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005178 return;
5179 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005180 Integer cnt = r.conProviders.get(localCpr);
5181 if (cnt == null || cnt.intValue() <= 1) {
5182 localCpr.clients.remove(r);
5183 r.conProviders.remove(localCpr);
5184 } else {
5185 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005187 }
5188 updateOomAdjLocked();
5189 }
5190 }
5191
5192 private void removeContentProviderExternal(String name) {
5193 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005194 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 if(cpr == null) {
5196 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005197 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005198 return;
5199 }
5200
5201 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005202 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 localCpr.externals--;
5204 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005205 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 }
5207 updateOomAdjLocked();
5208 }
5209 }
5210
5211 public final void publishContentProviders(IApplicationThread caller,
5212 List<ContentProviderHolder> providers) {
5213 if (providers == null) {
5214 return;
5215 }
5216
5217 synchronized(this) {
5218 final ProcessRecord r = getRecordForAppLocked(caller);
5219 if (r == null) {
5220 throw new SecurityException(
5221 "Unable to find app for caller " + caller
5222 + " (pid=" + Binder.getCallingPid()
5223 + ") when publishing content providers");
5224 }
5225
5226 final long origId = Binder.clearCallingIdentity();
5227
5228 final int N = providers.size();
5229 for (int i=0; i<N; i++) {
5230 ContentProviderHolder src = providers.get(i);
5231 if (src == null || src.info == null || src.provider == null) {
5232 continue;
5233 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005234 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 if (dst != null) {
5236 mProvidersByClass.put(dst.info.name, dst);
5237 String names[] = dst.info.authority.split(";");
5238 for (int j = 0; j < names.length; j++) {
5239 mProvidersByName.put(names[j], dst);
5240 }
5241
5242 int NL = mLaunchingProviders.size();
5243 int j;
5244 for (j=0; j<NL; j++) {
5245 if (mLaunchingProviders.get(j) == dst) {
5246 mLaunchingProviders.remove(j);
5247 j--;
5248 NL--;
5249 }
5250 }
5251 synchronized (dst) {
5252 dst.provider = src.provider;
5253 dst.app = r;
5254 dst.notifyAll();
5255 }
5256 updateOomAdjLocked(r);
5257 }
5258 }
5259
5260 Binder.restoreCallingIdentity(origId);
5261 }
5262 }
5263
5264 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005265 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005266 synchronized (mSelf) {
5267 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5268 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005269 if (providers != null) {
5270 for (int i=providers.size()-1; i>=0; i--) {
5271 ProviderInfo pi = (ProviderInfo)providers.get(i);
5272 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5273 Slog.w(TAG, "Not installing system proc provider " + pi.name
5274 + ": not system .apk");
5275 providers.remove(i);
5276 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005277 }
5278 }
5279 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005280 if (providers != null) {
5281 mSystemThread.installSystemProviders(providers);
5282 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 }
5284
5285 // =========================================================
5286 // GLOBAL MANAGEMENT
5287 // =========================================================
5288
5289 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5290 ApplicationInfo info, String customProcess) {
5291 String proc = customProcess != null ? customProcess : info.processName;
5292 BatteryStatsImpl.Uid.Proc ps = null;
5293 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5294 synchronized (stats) {
5295 ps = stats.getProcessStatsLocked(info.uid, proc);
5296 }
5297 return new ProcessRecord(ps, thread, info, proc);
5298 }
5299
5300 final ProcessRecord addAppLocked(ApplicationInfo info) {
5301 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5302
5303 if (app == null) {
5304 app = newProcessRecordLocked(null, info, null);
5305 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005306 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 }
5308
5309 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5310 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5311 app.persistent = true;
5312 app.maxAdj = CORE_SERVER_ADJ;
5313 }
5314 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5315 mPersistentStartingProcesses.add(app);
5316 startProcessLocked(app, "added application", app.processName);
5317 }
5318
5319 return app;
5320 }
5321
5322 public void unhandledBack() {
5323 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5324 "unhandledBack()");
5325
5326 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005327 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005328 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 TAG, "Performing unhandledBack(): stack size = " + count);
5330 if (count > 1) {
5331 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005332 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005333 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5334 Binder.restoreCallingIdentity(origId);
5335 }
5336 }
5337 }
5338
5339 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5340 String name = uri.getAuthority();
5341 ContentProviderHolder cph = getContentProviderExternal(name);
5342 ParcelFileDescriptor pfd = null;
5343 if (cph != null) {
5344 // We record the binder invoker's uid in thread-local storage before
5345 // going to the content provider to open the file. Later, in the code
5346 // that handles all permissions checks, we look for this uid and use
5347 // that rather than the Activity Manager's own uid. The effect is that
5348 // we do the check against the caller's permissions even though it looks
5349 // to the content provider like the Activity Manager itself is making
5350 // the request.
5351 sCallerIdentity.set(new Identity(
5352 Binder.getCallingPid(), Binder.getCallingUid()));
5353 try {
5354 pfd = cph.provider.openFile(uri, "r");
5355 } catch (FileNotFoundException e) {
5356 // do nothing; pfd will be returned null
5357 } finally {
5358 // Ensure that whatever happens, we clean up the identity state
5359 sCallerIdentity.remove();
5360 }
5361
5362 // We've got the fd now, so we're done with the provider.
5363 removeContentProviderExternal(name);
5364 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005365 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366 }
5367 return pfd;
5368 }
5369
5370 public void goingToSleep() {
5371 synchronized(this) {
5372 mSleeping = true;
5373 mWindowManager.setEventDispatching(false);
5374
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005375 if (mMainStack.mResumedActivity != null) {
5376 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005378 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 }
5380 }
5381 }
5382
Dianne Hackborn55280a92009-05-07 15:53:46 -07005383 public boolean shutdown(int timeout) {
5384 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5385 != PackageManager.PERMISSION_GRANTED) {
5386 throw new SecurityException("Requires permission "
5387 + android.Manifest.permission.SHUTDOWN);
5388 }
5389
5390 boolean timedout = false;
5391
5392 synchronized(this) {
5393 mShuttingDown = true;
5394 mWindowManager.setEventDispatching(false);
5395
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005396 if (mMainStack.mResumedActivity != null) {
5397 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005398 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005399 while (mMainStack.mResumedActivity != null
5400 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005401 long delay = endTime - System.currentTimeMillis();
5402 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005403 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005404 timedout = true;
5405 break;
5406 }
5407 try {
5408 this.wait();
5409 } catch (InterruptedException e) {
5410 }
5411 }
5412 }
5413 }
5414
5415 mUsageStatsService.shutdown();
5416 mBatteryStatsService.shutdown();
5417
5418 return timedout;
5419 }
5420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 public void wakingUp() {
5422 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005423 if (mMainStack.mGoingToSleep.isHeld()) {
5424 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425 }
5426 mWindowManager.setEventDispatching(true);
5427 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005428 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 }
5430 }
5431
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005432 public void stopAppSwitches() {
5433 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5434 != PackageManager.PERMISSION_GRANTED) {
5435 throw new SecurityException("Requires permission "
5436 + android.Manifest.permission.STOP_APP_SWITCHES);
5437 }
5438
5439 synchronized(this) {
5440 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5441 + APP_SWITCH_DELAY_TIME;
5442 mDidAppSwitch = false;
5443 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5444 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5445 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5446 }
5447 }
5448
5449 public void resumeAppSwitches() {
5450 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5451 != PackageManager.PERMISSION_GRANTED) {
5452 throw new SecurityException("Requires permission "
5453 + android.Manifest.permission.STOP_APP_SWITCHES);
5454 }
5455
5456 synchronized(this) {
5457 // Note that we don't execute any pending app switches... we will
5458 // let those wait until either the timeout, or the next start
5459 // activity request.
5460 mAppSwitchesAllowedTime = 0;
5461 }
5462 }
5463
5464 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5465 String name) {
5466 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5467 return true;
5468 }
5469
5470 final int perm = checkComponentPermission(
5471 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5472 callingUid, -1);
5473 if (perm == PackageManager.PERMISSION_GRANTED) {
5474 return true;
5475 }
5476
Joe Onorato8a9b2202010-02-26 18:56:32 -08005477 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005478 return false;
5479 }
5480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005481 public void setDebugApp(String packageName, boolean waitForDebugger,
5482 boolean persistent) {
5483 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5484 "setDebugApp()");
5485
5486 // Note that this is not really thread safe if there are multiple
5487 // callers into it at the same time, but that's not a situation we
5488 // care about.
5489 if (persistent) {
5490 final ContentResolver resolver = mContext.getContentResolver();
5491 Settings.System.putString(
5492 resolver, Settings.System.DEBUG_APP,
5493 packageName);
5494 Settings.System.putInt(
5495 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5496 waitForDebugger ? 1 : 0);
5497 }
5498
5499 synchronized (this) {
5500 if (!persistent) {
5501 mOrigDebugApp = mDebugApp;
5502 mOrigWaitForDebugger = mWaitForDebugger;
5503 }
5504 mDebugApp = packageName;
5505 mWaitForDebugger = waitForDebugger;
5506 mDebugTransient = !persistent;
5507 if (packageName != null) {
5508 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005509 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 Binder.restoreCallingIdentity(origId);
5511 }
5512 }
5513 }
5514
5515 public void setAlwaysFinish(boolean enabled) {
5516 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5517 "setAlwaysFinish()");
5518
5519 Settings.System.putInt(
5520 mContext.getContentResolver(),
5521 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5522
5523 synchronized (this) {
5524 mAlwaysFinishActivities = enabled;
5525 }
5526 }
5527
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005528 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005529 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005530 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005531 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005532 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533 }
5534 }
5535
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005536 public boolean isUserAMonkey() {
5537 // For now the fact that there is a controller implies
5538 // we have a monkey.
5539 synchronized (this) {
5540 return mController != null;
5541 }
5542 }
5543
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005544 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005545 synchronized (this) {
5546 mWatchers.register(watcher);
5547 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005548 }
5549
5550 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005551 synchronized (this) {
5552 mWatchers.unregister(watcher);
5553 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005554 }
5555
Daniel Sandler69a48172010-06-23 16:29:36 -04005556 public void setImmersive(IBinder token, boolean immersive) {
5557 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005558 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005559 if (index < 0) {
5560 throw new IllegalArgumentException();
5561 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005562 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005563 r.immersive = immersive;
5564 }
5565 }
5566
5567 public boolean isImmersive(IBinder token) {
5568 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005569 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005570 if (index < 0) {
5571 throw new IllegalArgumentException();
5572 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005573 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005574 return r.immersive;
5575 }
5576 }
5577
5578 public boolean isTopActivityImmersive() {
5579 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005580 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005581 return (r != null) ? r.immersive : false;
5582 }
5583 }
5584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005585 public final void enterSafeMode() {
5586 synchronized(this) {
5587 // It only makes sense to do this before the system is ready
5588 // and started launching other packages.
5589 if (!mSystemReady) {
5590 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005591 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005592 } catch (RemoteException e) {
5593 }
5594
5595 View v = LayoutInflater.from(mContext).inflate(
5596 com.android.internal.R.layout.safe_mode, null);
5597 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5598 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5599 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5600 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5601 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5602 lp.format = v.getBackground().getOpacity();
5603 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5604 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5605 ((WindowManager)mContext.getSystemService(
5606 Context.WINDOW_SERVICE)).addView(v, lp);
5607 }
5608 }
5609 }
5610
5611 public void noteWakeupAlarm(IIntentSender sender) {
5612 if (!(sender instanceof PendingIntentRecord)) {
5613 return;
5614 }
5615 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5616 synchronized (stats) {
5617 if (mBatteryStatsService.isOnBattery()) {
5618 mBatteryStatsService.enforceCallingPermission();
5619 PendingIntentRecord rec = (PendingIntentRecord)sender;
5620 int MY_UID = Binder.getCallingUid();
5621 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5622 BatteryStatsImpl.Uid.Pkg pkg =
5623 stats.getPackageStatsLocked(uid, rec.key.packageName);
5624 pkg.incWakeupsLocked();
5625 }
5626 }
5627 }
5628
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005629 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005631 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005633 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005634 // XXX Note: don't acquire main activity lock here, because the window
5635 // manager calls in with its locks held.
5636
5637 boolean killed = false;
5638 synchronized (mPidsSelfLocked) {
5639 int[] types = new int[pids.length];
5640 int worstType = 0;
5641 for (int i=0; i<pids.length; i++) {
5642 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5643 if (proc != null) {
5644 int type = proc.setAdj;
5645 types[i] = type;
5646 if (type > worstType) {
5647 worstType = type;
5648 }
5649 }
5650 }
5651
5652 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5653 // then constrain it so we will kill all hidden procs.
5654 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5655 worstType = HIDDEN_APP_MIN_ADJ;
5656 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005657 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 for (int i=0; i<pids.length; i++) {
5659 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5660 if (proc == null) {
5661 continue;
5662 }
5663 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005664 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005665 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005666 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5667 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005669 proc.killedBackground = true;
5670 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 }
5672 }
5673 }
5674 return killed;
5675 }
5676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005677 public final void startRunning(String pkg, String cls, String action,
5678 String data) {
5679 synchronized(this) {
5680 if (mStartRunning) {
5681 return;
5682 }
5683 mStartRunning = true;
5684 mTopComponent = pkg != null && cls != null
5685 ? new ComponentName(pkg, cls) : null;
5686 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5687 mTopData = data;
5688 if (!mSystemReady) {
5689 return;
5690 }
5691 }
5692
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005693 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694 }
5695
5696 private void retrieveSettings() {
5697 final ContentResolver resolver = mContext.getContentResolver();
5698 String debugApp = Settings.System.getString(
5699 resolver, Settings.System.DEBUG_APP);
5700 boolean waitForDebugger = Settings.System.getInt(
5701 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5702 boolean alwaysFinishActivities = Settings.System.getInt(
5703 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5704
5705 Configuration configuration = new Configuration();
5706 Settings.System.getConfiguration(resolver, configuration);
5707
5708 synchronized (this) {
5709 mDebugApp = mOrigDebugApp = debugApp;
5710 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5711 mAlwaysFinishActivities = alwaysFinishActivities;
5712 // This happens before any activities are started, so we can
5713 // change mConfiguration in-place.
5714 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005715 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005716 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 }
5718 }
5719
5720 public boolean testIsSystemReady() {
5721 // no need to synchronize(this) just to read & return the value
5722 return mSystemReady;
5723 }
5724
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005725 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 // In the simulator, startRunning will never have been called, which
5727 // normally sets a few crucial variables. Do it here instead.
5728 if (!Process.supportsProcesses()) {
5729 mStartRunning = true;
5730 mTopAction = Intent.ACTION_MAIN;
5731 }
5732
5733 synchronized(this) {
5734 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005735 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005736 return;
5737 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005738
5739 // Check to see if there are any update receivers to run.
5740 if (!mDidUpdate) {
5741 if (mWaitingUpdate) {
5742 return;
5743 }
5744 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5745 List<ResolveInfo> ris = null;
5746 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005747 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005748 intent, null, 0);
5749 } catch (RemoteException e) {
5750 }
5751 if (ris != null) {
5752 for (int i=ris.size()-1; i>=0; i--) {
5753 if ((ris.get(i).activityInfo.applicationInfo.flags
5754 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5755 ris.remove(i);
5756 }
5757 }
5758 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5759 for (int i=0; i<ris.size(); i++) {
5760 ActivityInfo ai = ris.get(i).activityInfo;
5761 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5762 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005763 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005764 finisher = new IIntentReceiver.Stub() {
5765 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005766 String data, Bundle extras, boolean ordered,
5767 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005768 throws RemoteException {
5769 synchronized (ActivityManagerService.this) {
5770 mDidUpdate = true;
5771 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005772 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005773 }
5774 };
5775 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005776 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005777 broadcastIntentLocked(null, null, intent, null, finisher,
5778 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005779 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005780 mWaitingUpdate = true;
5781 }
5782 }
5783 }
5784 if (mWaitingUpdate) {
5785 return;
5786 }
5787 mDidUpdate = true;
5788 }
5789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005790 mSystemReady = true;
5791 if (!mStartRunning) {
5792 return;
5793 }
5794 }
5795
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005796 ArrayList<ProcessRecord> procsToKill = null;
5797 synchronized(mPidsSelfLocked) {
5798 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5799 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5800 if (!isAllowedWhileBooting(proc.info)){
5801 if (procsToKill == null) {
5802 procsToKill = new ArrayList<ProcessRecord>();
5803 }
5804 procsToKill.add(proc);
5805 }
5806 }
5807 }
5808
5809 if (procsToKill != null) {
5810 synchronized(this) {
5811 for (int i=procsToKill.size()-1; i>=0; i--) {
5812 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005813 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005814 removeProcessLocked(proc, true);
5815 }
5816 }
5817 }
5818
Joe Onorato8a9b2202010-02-26 18:56:32 -08005819 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005820 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821 SystemClock.uptimeMillis());
5822
5823 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005824 // Make sure we have no pre-ready processes sitting around.
5825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005826 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5827 ResolveInfo ri = mContext.getPackageManager()
5828 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005829 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 CharSequence errorMsg = null;
5831 if (ri != null) {
5832 ActivityInfo ai = ri.activityInfo;
5833 ApplicationInfo app = ai.applicationInfo;
5834 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5835 mTopAction = Intent.ACTION_FACTORY_TEST;
5836 mTopData = null;
5837 mTopComponent = new ComponentName(app.packageName,
5838 ai.name);
5839 } else {
5840 errorMsg = mContext.getResources().getText(
5841 com.android.internal.R.string.factorytest_not_system);
5842 }
5843 } else {
5844 errorMsg = mContext.getResources().getText(
5845 com.android.internal.R.string.factorytest_no_action);
5846 }
5847 if (errorMsg != null) {
5848 mTopAction = null;
5849 mTopData = null;
5850 mTopComponent = null;
5851 Message msg = Message.obtain();
5852 msg.what = SHOW_FACTORY_ERROR_MSG;
5853 msg.getData().putCharSequence("msg", errorMsg);
5854 mHandler.sendMessage(msg);
5855 }
5856 }
5857 }
5858
5859 retrieveSettings();
5860
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005861 if (goingCallback != null) goingCallback.run();
5862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 synchronized (this) {
5864 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5865 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005866 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005867 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 if (apps != null) {
5869 int N = apps.size();
5870 int i;
5871 for (i=0; i<N; i++) {
5872 ApplicationInfo info
5873 = (ApplicationInfo)apps.get(i);
5874 if (info != null &&
5875 !info.packageName.equals("android")) {
5876 addAppLocked(info);
5877 }
5878 }
5879 }
5880 } catch (RemoteException ex) {
5881 // pm is in same process, this will never happen.
5882 }
5883 }
5884
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005885 // Start up initial activity.
5886 mBooting = true;
5887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005889 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005890 Message msg = Message.obtain();
5891 msg.what = SHOW_UID_ERROR_MSG;
5892 mHandler.sendMessage(msg);
5893 }
5894 } catch (RemoteException e) {
5895 }
5896
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005897 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005898 }
5899 }
5900
Dan Egnorb7f03672009-12-09 16:22:32 -08005901 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005902 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005904 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005905 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005906 startAppProblemLocked(app);
5907 app.stopFreezingAllLocked();
5908 return handleAppCrashLocked(app);
5909 }
5910
Dan Egnorb7f03672009-12-09 16:22:32 -08005911 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005912 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005913 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08005914 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08005915 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
5916 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005917 startAppProblemLocked(app);
5918 app.stopFreezingAllLocked();
5919 }
5920
5921 /**
5922 * Generate a process error record, suitable for attachment to a ProcessRecord.
5923 *
5924 * @param app The ProcessRecord in which the error occurred.
5925 * @param condition Crashing, Application Not Responding, etc. Values are defined in
5926 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08005927 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005928 * @param shortMsg Short message describing the crash.
5929 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08005930 * @param stackTrace Full crash stack trace, may be null.
5931 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 * @return Returns a fully-formed AppErrorStateInfo record.
5933 */
5934 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08005935 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005936 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08005937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 report.condition = condition;
5939 report.processName = app.processName;
5940 report.pid = app.pid;
5941 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08005942 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 report.shortMsg = shortMsg;
5944 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08005945 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005946
5947 return report;
5948 }
5949
Dan Egnor42471dd2010-01-07 17:25:22 -08005950 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005951 synchronized (this) {
5952 app.crashing = false;
5953 app.crashingReport = null;
5954 app.notResponding = false;
5955 app.notRespondingReport = null;
5956 if (app.anrDialog == fromDialog) {
5957 app.anrDialog = null;
5958 }
5959 if (app.waitDialog == fromDialog) {
5960 app.waitDialog = null;
5961 }
5962 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08005963 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07005964 Slog.i(ActivityManagerService.TAG, "Killing "
5965 + app.processName + " (pid=" + app.pid + "): user's request");
5966 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
5967 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 Process.killProcess(app.pid);
5969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 }
5971 }
Dan Egnor42471dd2010-01-07 17:25:22 -08005972
Dan Egnorb7f03672009-12-09 16:22:32 -08005973 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005974 long now = SystemClock.uptimeMillis();
5975
5976 Long crashTime = mProcessCrashTimes.get(app.info.processName,
5977 app.info.uid);
5978 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
5979 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08005980 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005981 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005982 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005983 app.info.processName, app.info.uid);
5984 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005985 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5986 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005988 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005990 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005991 }
5992 }
5993 if (!app.persistent) {
5994 // We don't want to start this process again until the user
5995 // explicitly does so... but for persistent process, we really
5996 // need to keep it running. If a persistent process is actually
5997 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08005998 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005999 app.info.processName);
6000 mBadProcesses.put(app.info.processName, app.info.uid, now);
6001 app.bad = true;
6002 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6003 app.removed = true;
6004 removeProcessLocked(app, false);
6005 return false;
6006 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006007 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006008 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006009 if (r.app == app) {
6010 // If the top running activity is from this crashing
6011 // process, then terminate it to avoid getting in a loop.
6012 Slog.w(TAG, " Force finishing activity "
6013 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006014 int index = mMainStack.indexOfTokenLocked(r);
6015 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006016 Activity.RESULT_CANCELED, null, "crashed");
6017 // Also terminate an activities below it that aren't yet
6018 // stopped, to avoid a situation where one will get
6019 // re-start our crashing activity once it gets resumed again.
6020 index--;
6021 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006022 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006023 if (r.state == ActivityState.RESUMED
6024 || r.state == ActivityState.PAUSING
6025 || r.state == ActivityState.PAUSED) {
6026 if (!r.isHomeActivity) {
6027 Slog.w(TAG, " Force finishing activity "
6028 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006029 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006030 Activity.RESULT_CANCELED, null, "crashed");
6031 }
6032 }
6033 }
6034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006035 }
6036
6037 // Bump up the crash count of any services currently running in the proc.
6038 if (app.services.size() != 0) {
6039 // Any services running in the application need to be placed
6040 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006041 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006043 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006044 sr.crashCount++;
6045 }
6046 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006047
6048 // If the crashing process is what we consider to be the "home process" and it has been
6049 // replaced by a third-party app, clear the package preferred activities from packages
6050 // with a home activity running in the process to prevent a repeatedly crashing app
6051 // from blocking the user to manually clear the list.
6052 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6053 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6054 Iterator it = mHomeProcess.activities.iterator();
6055 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006056 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006057 if (r.isHomeActivity) {
6058 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6059 try {
6060 ActivityThread.getPackageManager()
6061 .clearPackagePreferredActivities(r.packageName);
6062 } catch (RemoteException c) {
6063 // pm is in same process, this will never happen.
6064 }
6065 }
6066 }
6067 }
6068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006069 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6070 return true;
6071 }
6072
6073 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006074 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6075 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006076 skipCurrentReceiverLocked(app);
6077 }
6078
6079 void skipCurrentReceiverLocked(ProcessRecord app) {
6080 boolean reschedule = false;
6081 BroadcastRecord r = app.curReceiver;
6082 if (r != null) {
6083 // The current broadcast is waiting for this app's receiver
6084 // to be finished. Looks like that's not going to happen, so
6085 // let the broadcast continue.
6086 logBroadcastReceiverDiscard(r);
6087 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6088 r.resultExtras, r.resultAbort, true);
6089 reschedule = true;
6090 }
6091 r = mPendingBroadcast;
6092 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006093 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006094 "skip & discard pending app " + r);
6095 logBroadcastReceiverDiscard(r);
6096 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6097 r.resultExtras, r.resultAbort, true);
6098 reschedule = true;
6099 }
6100 if (reschedule) {
6101 scheduleBroadcastsLocked();
6102 }
6103 }
6104
Dan Egnor60d87622009-12-16 16:32:58 -08006105 /**
6106 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6107 * The application process will exit immediately after this call returns.
6108 * @param app object of the crashing app, null for the system server
6109 * @param crashInfo describing the exception
6110 */
6111 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6112 ProcessRecord r = findAppProcess(app);
6113
6114 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6115 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006116 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006117 crashInfo.exceptionClassName,
6118 crashInfo.exceptionMessage,
6119 crashInfo.throwFileName,
6120 crashInfo.throwLineNumber);
6121
Dan Egnor42471dd2010-01-07 17:25:22 -08006122 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006123
6124 crashApplication(r, crashInfo);
6125 }
6126
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006127 public void handleApplicationStrictModeViolation(
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006128 IBinder app, int violationMask, ApplicationErrorReport.CrashInfo crashInfo) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006129 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006130
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006131 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006132 Integer stackFingerprint = crashInfo.stackTrace.hashCode();
6133 boolean logIt = true;
6134 synchronized (mAlreadyLoggedViolatedStacks) {
6135 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6136 logIt = false;
6137 // TODO: sub-sample into EventLog for these, with
6138 // the crashInfo.durationMillis? Then we'd get
6139 // the relative pain numbers, without logging all
6140 // the stack traces repeatedly. We'd want to do
6141 // likewise in the client code, which also does
6142 // dup suppression, before the Binder call.
6143 } else {
6144 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6145 mAlreadyLoggedViolatedStacks.clear();
6146 }
6147 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6148 }
6149 }
6150 if (logIt) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006151 logStrictModeViolationToDropBox(r, crashInfo);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006152 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006153 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006154
6155 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6156 AppErrorResult result = new AppErrorResult();
6157 synchronized (this) {
6158 final long origId = Binder.clearCallingIdentity();
6159
6160 Message msg = Message.obtain();
6161 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6162 HashMap<String, Object> data = new HashMap<String, Object>();
6163 data.put("result", result);
6164 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006165 data.put("violationMask", violationMask);
6166 data.put("crashInfo", crashInfo);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006167 msg.obj = data;
6168 mHandler.sendMessage(msg);
6169
6170 Binder.restoreCallingIdentity(origId);
6171 }
6172 int res = result.get();
6173 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
6174 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006175 }
6176
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006177 // Depending on the policy in effect, there could be a bunch of
6178 // these in quick succession so we try to batch these together to
6179 // minimize disk writes, number of dropbox entries, and maximize
6180 // compression, by having more fewer, larger records.
6181 private void logStrictModeViolationToDropBox(ProcessRecord process,
6182 ApplicationErrorReport.CrashInfo crashInfo) {
6183 if (crashInfo == null) {
6184 return;
6185 }
6186 final boolean isSystemApp = process == null ||
6187 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6188 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6189 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6190 final DropBoxManager dbox = (DropBoxManager)
6191 mContext.getSystemService(Context.DROPBOX_SERVICE);
6192
6193 // Exit early if the dropbox isn't configured to accept this report type.
6194 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6195
6196 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006197 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006198 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6199 synchronized (sb) {
6200 bufferWasEmpty = sb.length() == 0;
6201 appendDropBoxProcessHeaders(process, sb);
6202 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6203 sb.append("System-App: ").append(isSystemApp).append("\n");
6204 if (crashInfo != null && crashInfo.durationMillis != -1) {
6205 sb.append("Duration-Millis: ").append(crashInfo.durationMillis).append("\n");
6206 }
6207 sb.append("\n");
6208 if (crashInfo != null && crashInfo.stackTrace != null) {
6209 sb.append(crashInfo.stackTrace);
6210 }
6211 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006212
6213 // Only buffer up to ~64k. Various logging bits truncate
6214 // things at 128k.
6215 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006216 }
6217
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006218 // Flush immediately if the buffer's grown too large, or this
6219 // is a non-system app. Non-system apps are isolated with a
6220 // different tag & policy and not batched.
6221 //
6222 // Batching is useful during internal testing with
6223 // StrictMode settings turned up high. Without batching,
6224 // thousands of separate files could be created on boot.
6225 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006226 new Thread("Error dump: " + dropboxTag) {
6227 @Override
6228 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006229 String report;
6230 synchronized (sb) {
6231 report = sb.toString();
6232 sb.delete(0, sb.length());
6233 sb.trimToSize();
6234 }
6235 if (report.length() != 0) {
6236 dbox.addText(dropboxTag, report);
6237 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006238 }
6239 }.start();
6240 return;
6241 }
6242
6243 // System app batching:
6244 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006245 // An existing dropbox-writing thread is outstanding, so
6246 // we don't need to start it up. The existing thread will
6247 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006248 return;
6249 }
6250
6251 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6252 // (After this point, we shouldn't access AMS internal data structures.)
6253 new Thread("Error dump: " + dropboxTag) {
6254 @Override
6255 public void run() {
6256 // 5 second sleep to let stacks arrive and be batched together
6257 try {
6258 Thread.sleep(5000); // 5 seconds
6259 } catch (InterruptedException e) {}
6260
6261 String errorReport;
6262 synchronized (mStrictModeBuffer) {
6263 errorReport = mStrictModeBuffer.toString();
6264 if (errorReport.length() == 0) {
6265 return;
6266 }
6267 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6268 mStrictModeBuffer.trimToSize();
6269 }
6270 dbox.addText(dropboxTag, errorReport);
6271 }
6272 }.start();
6273 }
6274
Dan Egnor60d87622009-12-16 16:32:58 -08006275 /**
6276 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6277 * @param app object of the crashing app, null for the system server
6278 * @param tag reported by the caller
6279 * @param crashInfo describing the context of the error
6280 * @return true if the process should exit immediately (WTF is fatal)
6281 */
6282 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006283 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006284 ProcessRecord r = findAppProcess(app);
6285
6286 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6287 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006288 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006289 tag, crashInfo.exceptionMessage);
6290
Dan Egnor42471dd2010-01-07 17:25:22 -08006291 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006292
Doug Zongker43866e02010-01-07 12:09:54 -08006293 if (Settings.Secure.getInt(mContext.getContentResolver(),
6294 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006295 crashApplication(r, crashInfo);
6296 return true;
6297 } else {
6298 return false;
6299 }
6300 }
6301
6302 /**
6303 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6304 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6305 */
6306 private ProcessRecord findAppProcess(IBinder app) {
6307 if (app == null) {
6308 return null;
6309 }
6310
6311 synchronized (this) {
6312 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6313 final int NA = apps.size();
6314 for (int ia=0; ia<NA; ia++) {
6315 ProcessRecord p = apps.valueAt(ia);
6316 if (p.thread != null && p.thread.asBinder() == app) {
6317 return p;
6318 }
6319 }
6320 }
6321
Joe Onorato8a9b2202010-02-26 18:56:32 -08006322 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006323 return null;
6324 }
6325 }
6326
6327 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006328 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6329 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006330 */
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006331 private static void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Dan Egnora455d192010-03-12 08:52:28 -08006332 if (process == null || process.pid == MY_PID) {
6333 sb.append("Process: system_server\n");
6334 } else {
6335 sb.append("Process: ").append(process.processName).append("\n");
6336 }
6337 if (process != null) {
6338 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006339 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006340 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6341 for (String pkg : process.pkgList) {
6342 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006343 try {
Dan Egnora455d192010-03-12 08:52:28 -08006344 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6345 if (pi != null) {
6346 sb.append(" v").append(pi.versionCode);
6347 if (pi.versionName != null) {
6348 sb.append(" (").append(pi.versionName).append(")");
6349 }
6350 }
6351 } catch (RemoteException e) {
6352 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006353 }
Dan Egnora455d192010-03-12 08:52:28 -08006354 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006355 }
Dan Egnora455d192010-03-12 08:52:28 -08006356 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006357 }
6358
6359 private static String processClass(ProcessRecord process) {
6360 if (process == null || process.pid == MY_PID) {
6361 return "system_server";
6362 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6363 return "system_app";
6364 } else {
6365 return "data_app";
6366 }
6367 }
6368
6369 /**
6370 * Write a description of an error (crash, WTF, ANR) to the drop box.
6371 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6372 * @param process which caused the error, null means the system server
6373 * @param activity which triggered the error, null if unknown
6374 * @param parent activity related to the error, null if unknown
6375 * @param subject line related to the error, null if absent
6376 * @param report in long form describing the error, null if absent
6377 * @param logFile to include in the report, null if none
6378 * @param crashInfo giving an application stack trace, null if absent
6379 */
6380 public void addErrorToDropBox(String eventType,
6381 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6382 final String report, final File logFile,
6383 final ApplicationErrorReport.CrashInfo crashInfo) {
6384 // NOTE -- this must never acquire the ActivityManagerService lock,
6385 // otherwise the watchdog may be prevented from resetting the system.
6386
6387 final String dropboxTag = processClass(process) + "_" + eventType;
6388 final DropBoxManager dbox = (DropBoxManager)
6389 mContext.getSystemService(Context.DROPBOX_SERVICE);
6390
6391 // Exit early if the dropbox isn't configured to accept this report type.
6392 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6393
6394 final StringBuilder sb = new StringBuilder(1024);
6395 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006396 if (activity != null) {
6397 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6398 }
6399 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6400 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6401 }
6402 if (parent != null && parent != activity) {
6403 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6404 }
6405 if (subject != null) {
6406 sb.append("Subject: ").append(subject).append("\n");
6407 }
6408 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6409 sb.append("\n");
6410
6411 // Do the rest in a worker thread to avoid blocking the caller on I/O
6412 // (After this point, we shouldn't access AMS internal data structures.)
6413 Thread worker = new Thread("Error dump: " + dropboxTag) {
6414 @Override
6415 public void run() {
6416 if (report != null) {
6417 sb.append(report);
6418 }
6419 if (logFile != null) {
6420 try {
6421 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6422 } catch (IOException e) {
6423 Slog.e(TAG, "Error reading " + logFile, e);
6424 }
6425 }
6426 if (crashInfo != null && crashInfo.stackTrace != null) {
6427 sb.append(crashInfo.stackTrace);
6428 }
6429
6430 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6431 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6432 if (lines > 0) {
6433 sb.append("\n");
6434
6435 // Merge several logcat streams, and take the last N lines
6436 InputStreamReader input = null;
6437 try {
6438 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6439 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6440 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6441
6442 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6443 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6444 input = new InputStreamReader(logcat.getInputStream());
6445
6446 int num;
6447 char[] buf = new char[8192];
6448 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6449 } catch (IOException e) {
6450 Slog.e(TAG, "Error running logcat", e);
6451 } finally {
6452 if (input != null) try { input.close(); } catch (IOException e) {}
6453 }
6454 }
6455
6456 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006457 }
Dan Egnora455d192010-03-12 08:52:28 -08006458 };
6459
6460 if (process == null || process.pid == MY_PID) {
6461 worker.run(); // We may be about to die -- need to run this synchronously
6462 } else {
6463 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006464 }
6465 }
6466
6467 /**
6468 * Bring up the "unexpected error" dialog box for a crashing app.
6469 * Deal with edge cases (intercepts from instrumented applications,
6470 * ActivityController, error intent receivers, that sort of thing).
6471 * @param r the application crashing
6472 * @param crashInfo describing the failure
6473 */
6474 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006475 long timeMillis = System.currentTimeMillis();
6476 String shortMsg = crashInfo.exceptionClassName;
6477 String longMsg = crashInfo.exceptionMessage;
6478 String stackTrace = crashInfo.stackTrace;
6479 if (shortMsg != null && longMsg != null) {
6480 longMsg = shortMsg + ": " + longMsg;
6481 } else if (shortMsg != null) {
6482 longMsg = shortMsg;
6483 }
6484
Dan Egnor60d87622009-12-16 16:32:58 -08006485 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006487 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006488 try {
6489 String name = r != null ? r.processName : null;
6490 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006491 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006492 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006493 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006494 + " at watcher's request");
6495 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006496 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006497 }
6498 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006499 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006500 }
6501 }
6502
6503 final long origId = Binder.clearCallingIdentity();
6504
6505 // If this process is running instrumentation, finish it.
6506 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006507 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006508 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006509 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6510 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006511 Bundle info = new Bundle();
6512 info.putString("shortMsg", shortMsg);
6513 info.putString("longMsg", longMsg);
6514 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6515 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006516 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006517 }
6518
Dan Egnor60d87622009-12-16 16:32:58 -08006519 // If we can't identify the process or it's already exceeded its crash quota,
6520 // quit right away without showing a crash dialog.
6521 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006523 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006524 }
6525
6526 Message msg = Message.obtain();
6527 msg.what = SHOW_ERROR_MSG;
6528 HashMap data = new HashMap();
6529 data.put("result", result);
6530 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006531 msg.obj = data;
6532 mHandler.sendMessage(msg);
6533
6534 Binder.restoreCallingIdentity(origId);
6535 }
6536
6537 int res = result.get();
6538
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006539 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 synchronized (this) {
6541 if (r != null) {
6542 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6543 SystemClock.uptimeMillis());
6544 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006545 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006546 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006547 }
6548 }
6549
6550 if (appErrorIntent != null) {
6551 try {
6552 mContext.startActivity(appErrorIntent);
6553 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006554 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006557 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006558
6559 Intent createAppErrorIntentLocked(ProcessRecord r,
6560 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6561 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006562 if (report == null) {
6563 return null;
6564 }
6565 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6566 result.setComponent(r.errorReportReceiver);
6567 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6568 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6569 return result;
6570 }
6571
Dan Egnorb7f03672009-12-09 16:22:32 -08006572 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6573 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006574 if (r.errorReportReceiver == null) {
6575 return null;
6576 }
6577
6578 if (!r.crashing && !r.notResponding) {
6579 return null;
6580 }
6581
Dan Egnorb7f03672009-12-09 16:22:32 -08006582 ApplicationErrorReport report = new ApplicationErrorReport();
6583 report.packageName = r.info.packageName;
6584 report.installerPackageName = r.errorReportReceiver.getPackageName();
6585 report.processName = r.processName;
6586 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006587 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006588
Dan Egnorb7f03672009-12-09 16:22:32 -08006589 if (r.crashing) {
6590 report.type = ApplicationErrorReport.TYPE_CRASH;
6591 report.crashInfo = crashInfo;
6592 } else if (r.notResponding) {
6593 report.type = ApplicationErrorReport.TYPE_ANR;
6594 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006595
Dan Egnorb7f03672009-12-09 16:22:32 -08006596 report.anrInfo.activity = r.notRespondingReport.tag;
6597 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6598 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006599 }
6600
Dan Egnorb7f03672009-12-09 16:22:32 -08006601 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006602 }
6603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006604 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6605 // assume our apps are happy - lazy create the list
6606 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6607
6608 synchronized (this) {
6609
6610 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006611 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6612 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006613 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6614 // This one's in trouble, so we'll generate a report for it
6615 // crashes are higher priority (in case there's a crash *and* an anr)
6616 ActivityManager.ProcessErrorStateInfo report = null;
6617 if (app.crashing) {
6618 report = app.crashingReport;
6619 } else if (app.notResponding) {
6620 report = app.notRespondingReport;
6621 }
6622
6623 if (report != null) {
6624 if (errList == null) {
6625 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6626 }
6627 errList.add(report);
6628 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006629 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006630 " crashing = " + app.crashing +
6631 " notResponding = " + app.notResponding);
6632 }
6633 }
6634 }
6635 }
6636
6637 return errList;
6638 }
6639
6640 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6641 // Lazy instantiation of list
6642 List<ActivityManager.RunningAppProcessInfo> runList = null;
6643 synchronized (this) {
6644 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006645 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6646 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006647 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6648 // Generate process state info for running application
6649 ActivityManager.RunningAppProcessInfo currApp =
6650 new ActivityManager.RunningAppProcessInfo(app.processName,
6651 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006652 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006653 if (mHeavyWeightProcess == app) {
6654 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6655 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006656 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006657 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6659 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6660 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006661 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6662 } else if (adj >= HOME_APP_ADJ) {
6663 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6664 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 } else if (adj >= SECONDARY_SERVER_ADJ) {
6666 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006667 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6668 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6669 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6670 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006671 } else if (adj >= VISIBLE_APP_ADJ) {
6672 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6673 } else {
6674 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6675 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006676 currApp.importanceReasonCode = app.adjTypeCode;
6677 if (app.adjSource instanceof ProcessRecord) {
6678 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006679 } else if (app.adjSource instanceof ActivityRecord) {
6680 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006681 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6682 }
6683 if (app.adjTarget instanceof ComponentName) {
6684 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6685 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006686 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006687 // + " lru=" + currApp.lru);
6688 if (runList == null) {
6689 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6690 }
6691 runList.add(currApp);
6692 }
6693 }
6694 }
6695 return runList;
6696 }
6697
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006698 public List<ApplicationInfo> getRunningExternalApplications() {
6699 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6700 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6701 if (runningApps != null && runningApps.size() > 0) {
6702 Set<String> extList = new HashSet<String>();
6703 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6704 if (app.pkgList != null) {
6705 for (String pkg : app.pkgList) {
6706 extList.add(pkg);
6707 }
6708 }
6709 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006710 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006711 for (String pkg : extList) {
6712 try {
6713 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6714 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6715 retList.add(info);
6716 }
6717 } catch (RemoteException e) {
6718 }
6719 }
6720 }
6721 return retList;
6722 }
6723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006724 @Override
6725 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006726 if (checkCallingPermission(android.Manifest.permission.DUMP)
6727 != PackageManager.PERMISSION_GRANTED) {
6728 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6729 + Binder.getCallingPid()
6730 + ", uid=" + Binder.getCallingUid()
6731 + " without permission "
6732 + android.Manifest.permission.DUMP);
6733 return;
6734 }
6735
6736 boolean dumpAll = false;
6737
6738 int opti = 0;
6739 while (opti < args.length) {
6740 String opt = args[opti];
6741 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6742 break;
6743 }
6744 opti++;
6745 if ("-a".equals(opt)) {
6746 dumpAll = true;
6747 } else if ("-h".equals(opt)) {
6748 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006749 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006750 pw.println(" cmd may be one of:");
6751 pw.println(" activities: activity stack state");
6752 pw.println(" broadcasts: broadcast state");
6753 pw.println(" intents: pending intent state");
6754 pw.println(" processes: process state");
6755 pw.println(" providers: content provider state");
6756 pw.println(" services: service state");
6757 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006758 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006759 } else {
6760 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006761 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006762 }
6763
6764 // Is the caller requesting to dump a particular piece of data?
6765 if (opti < args.length) {
6766 String cmd = args[opti];
6767 opti++;
6768 if ("activities".equals(cmd) || "a".equals(cmd)) {
6769 synchronized (this) {
6770 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006772 return;
6773 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6774 synchronized (this) {
6775 dumpBroadcastsLocked(fd, pw, args, opti, true);
6776 }
6777 return;
6778 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6779 synchronized (this) {
6780 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6781 }
6782 return;
6783 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6784 synchronized (this) {
6785 dumpProcessesLocked(fd, pw, args, opti, true);
6786 }
6787 return;
6788 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6789 synchronized (this) {
6790 dumpProvidersLocked(fd, pw, args, opti, true);
6791 }
6792 return;
6793 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07006794 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006795 return;
6796 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6797 synchronized (this) {
6798 dumpServicesLocked(fd, pw, args, opti, true);
6799 }
6800 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006802 }
6803
6804 // No piece of data specified, dump everything.
6805 synchronized (this) {
6806 boolean needSep;
6807 if (dumpAll) {
6808 pw.println("Providers in Current Activity Manager State:");
6809 }
6810 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6811 if (needSep) {
6812 pw.println(" ");
6813 }
6814 if (dumpAll) {
6815 pw.println("-------------------------------------------------------------------------------");
6816 pw.println("Broadcasts in Current Activity Manager State:");
6817 }
6818 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6819 if (needSep) {
6820 pw.println(" ");
6821 }
6822 if (dumpAll) {
6823 pw.println("-------------------------------------------------------------------------------");
6824 pw.println("Services in Current Activity Manager State:");
6825 }
6826 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6827 if (needSep) {
6828 pw.println(" ");
6829 }
6830 if (dumpAll) {
6831 pw.println("-------------------------------------------------------------------------------");
6832 pw.println("PendingIntents in Current Activity Manager State:");
6833 }
6834 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6835 if (needSep) {
6836 pw.println(" ");
6837 }
6838 if (dumpAll) {
6839 pw.println("-------------------------------------------------------------------------------");
6840 pw.println("Activities in Current Activity Manager State:");
6841 }
6842 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6843 if (needSep) {
6844 pw.println(" ");
6845 }
6846 if (dumpAll) {
6847 pw.println("-------------------------------------------------------------------------------");
6848 pw.println("Processes in Current Activity Manager State:");
6849 }
6850 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6851 }
6852 }
6853
6854 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6855 int opti, boolean dumpAll, boolean needHeader) {
6856 if (needHeader) {
6857 pw.println(" Activity stack:");
6858 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006859 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006860 pw.println(" ");
6861 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006862 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6863 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006864 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006865 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006866 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006867 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006868 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006869 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006870 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006871 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006872 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006873 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006874 pw.println(" ");
6875 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006876 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006877 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006878
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006879 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006880 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
6881 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006882 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006883 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006884
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006885 if (dumpAll && mRecentTasks.size() > 0) {
6886 pw.println(" ");
6887 pw.println("Recent tasks in Current Activity Manager State:");
6888
6889 final int N = mRecentTasks.size();
6890 for (int i=0; i<N; i++) {
6891 TaskRecord tr = mRecentTasks.get(i);
6892 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
6893 pw.println(tr);
6894 mRecentTasks.get(i).dump(pw, " ");
6895 }
6896 }
6897
6898 pw.println(" ");
6899 pw.println(" mCurTask: " + mCurTask);
6900
6901 return true;
6902 }
6903
6904 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6905 int opti, boolean dumpAll) {
6906 boolean needSep = false;
6907 int numPers = 0;
6908
6909 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006910 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
6911 final int NA = procs.size();
6912 for (int ia=0; ia<NA; ia++) {
6913 if (!needSep) {
6914 pw.println(" All known processes:");
6915 needSep = true;
6916 }
6917 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006918 pw.print(r.persistent ? " *PERS*" : " *APP*");
6919 pw.print(" UID "); pw.print(procs.keyAt(ia));
6920 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006921 r.dump(pw, " ");
6922 if (r.persistent) {
6923 numPers++;
6924 }
6925 }
6926 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006927 }
6928
6929 if (mLruProcesses.size() > 0) {
6930 if (needSep) pw.println(" ");
6931 needSep = true;
6932 pw.println(" Running processes (most recent first):");
6933 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006934 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006935 needSep = true;
6936 }
6937
6938 synchronized (mPidsSelfLocked) {
6939 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006940 if (needSep) pw.println(" ");
6941 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006942 pw.println(" PID mappings:");
6943 for (int i=0; i<mPidsSelfLocked.size(); i++) {
6944 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
6945 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006946 }
6947 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006948 }
6949
6950 if (mForegroundProcesses.size() > 0) {
6951 if (needSep) pw.println(" ");
6952 needSep = true;
6953 pw.println(" Foreground Processes:");
6954 for (int i=0; i<mForegroundProcesses.size(); i++) {
6955 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
6956 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006957 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006958 }
6959
6960 if (mPersistentStartingProcesses.size() > 0) {
6961 if (needSep) pw.println(" ");
6962 needSep = true;
6963 pw.println(" Persisent processes that are starting:");
6964 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
6965 "Starting Norm", "Restarting PERS", false);
6966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006967
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006968 if (mStartingProcesses.size() > 0) {
6969 if (needSep) pw.println(" ");
6970 needSep = true;
6971 pw.println(" Processes that are starting:");
6972 dumpProcessList(pw, this, mStartingProcesses, " ",
6973 "Starting Norm", "Starting PERS", false);
6974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006975
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006976 if (mRemovedProcesses.size() > 0) {
6977 if (needSep) pw.println(" ");
6978 needSep = true;
6979 pw.println(" Processes that are being removed:");
6980 dumpProcessList(pw, this, mRemovedProcesses, " ",
6981 "Removed Norm", "Removed PERS", false);
6982 }
6983
6984 if (mProcessesOnHold.size() > 0) {
6985 if (needSep) pw.println(" ");
6986 needSep = true;
6987 pw.println(" Processes that are on old until the system is ready:");
6988 dumpProcessList(pw, this, mProcessesOnHold, " ",
6989 "OnHold Norm", "OnHold PERS", false);
6990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006991
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006992 if (mProcessesToGc.size() > 0) {
6993 if (needSep) pw.println(" ");
6994 needSep = true;
6995 pw.println(" Processes that are waiting to GC:");
6996 long now = SystemClock.uptimeMillis();
6997 for (int i=0; i<mProcessesToGc.size(); i++) {
6998 ProcessRecord proc = mProcessesToGc.get(i);
6999 pw.print(" Process "); pw.println(proc);
7000 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7001 pw.print(", last gced=");
7002 pw.print(now-proc.lastRequestedGc);
7003 pw.print(" ms ago, last lowMem=");
7004 pw.print(now-proc.lastLowMemory);
7005 pw.println(" ms ago");
7006
7007 }
7008 }
7009
7010 if (mProcessCrashTimes.getMap().size() > 0) {
7011 if (needSep) pw.println(" ");
7012 needSep = true;
7013 pw.println(" Time since processes crashed:");
7014 long now = SystemClock.uptimeMillis();
7015 for (Map.Entry<String, SparseArray<Long>> procs
7016 : mProcessCrashTimes.getMap().entrySet()) {
7017 SparseArray<Long> uids = procs.getValue();
7018 final int N = uids.size();
7019 for (int i=0; i<N; i++) {
7020 pw.print(" Process "); pw.print(procs.getKey());
7021 pw.print(" uid "); pw.print(uids.keyAt(i));
7022 pw.print(": last crashed ");
7023 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007024 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007025 }
7026 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007028
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007029 if (mBadProcesses.getMap().size() > 0) {
7030 if (needSep) pw.println(" ");
7031 needSep = true;
7032 pw.println(" Bad processes:");
7033 for (Map.Entry<String, SparseArray<Long>> procs
7034 : mBadProcesses.getMap().entrySet()) {
7035 SparseArray<Long> uids = procs.getValue();
7036 final int N = uids.size();
7037 for (int i=0; i<N; i++) {
7038 pw.print(" Bad process "); pw.print(procs.getKey());
7039 pw.print(" uid "); pw.print(uids.keyAt(i));
7040 pw.print(": crashed at time ");
7041 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007042 }
7043 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007045
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007046 pw.println(" ");
7047 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007048 if (mHeavyWeightProcess != null) {
7049 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7050 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007051 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007052 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007053 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7054 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7055 || mOrigWaitForDebugger) {
7056 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7057 + " mDebugTransient=" + mDebugTransient
7058 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7059 }
7060 if (mAlwaysFinishActivities || mController != null) {
7061 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7062 + " mController=" + mController);
7063 }
7064 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066 pw.println(" mStartRunning=" + mStartRunning
7067 + " mSystemReady=" + mSystemReady
7068 + " mBooting=" + mBooting
7069 + " mBooted=" + mBooted
7070 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007071 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7072 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007073 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007074 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007075
7076 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007077 }
7078
7079 /**
7080 * There are three ways to call this:
7081 * - no service specified: dump all the services
7082 * - a flattened component name that matched an existing service was specified as the
7083 * first arg: dump that one service
7084 * - the first arg isn't the flattened component name of an existing service:
7085 * dump all services whose component contains the first arg as a substring
7086 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007087 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7088 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 String[] newArgs;
7090 String componentNameString;
7091 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007092 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007093 componentNameString = null;
7094 newArgs = EMPTY_STRING_ARRAY;
7095 r = null;
7096 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007097 componentNameString = args[opti];
7098 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007099 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007100 synchronized (this) {
7101 r = componentName != null ? mServices.get(componentName) : null;
7102 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007103 newArgs = new String[args.length - opti];
7104 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007105 }
7106
7107 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007108 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007109 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007110 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7111 synchronized (this) {
7112 for (ServiceRecord r1 : mServices.values()) {
7113 if (componentNameString == null
7114 || r1.name.flattenToString().contains(componentNameString)) {
7115 services.add(r1);
7116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 }
7118 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007119 for (int i=0; i<services.size(); i++) {
7120 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007122 }
7123 }
7124
7125 /**
7126 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7127 * there is a thread associated with the service.
7128 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007129 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7130 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007131 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007132 if (dumpAll) {
7133 synchronized (this) {
7134 pw.print(" * "); pw.println(r);
7135 r.dump(pw, " ");
7136 }
7137 pw.println("");
7138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007139 if (r.app != null && r.app.thread != null) {
7140 try {
7141 // flush anything that is already in the PrintWriter since the thread is going
7142 // to write to the file descriptor directly
7143 pw.flush();
7144 r.app.thread.dumpService(fd, r, args);
7145 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007146 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 } catch (RemoteException e) {
7148 pw.println("got a RemoteException while dumping the service");
7149 }
7150 }
7151 }
7152
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007153 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7154 int opti, boolean dumpAll) {
7155 boolean needSep = false;
7156
7157 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 if (mRegisteredReceivers.size() > 0) {
7159 pw.println(" ");
7160 pw.println(" Registered Receivers:");
7161 Iterator it = mRegisteredReceivers.values().iterator();
7162 while (it.hasNext()) {
7163 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007164 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 r.dump(pw, " ");
7166 }
7167 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007169 pw.println(" ");
7170 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007171 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007172 needSep = true;
7173 }
7174
7175 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7176 || mPendingBroadcast != null) {
7177 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007179 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007181 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7182 pw.println(" Broadcast #" + i + ":");
7183 mParallelBroadcasts.get(i).dump(pw, " ");
7184 }
7185 if (mOrderedBroadcasts.size() > 0) {
7186 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007187 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007188 }
7189 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7190 pw.println(" Serialized Broadcast #" + i + ":");
7191 mOrderedBroadcasts.get(i).dump(pw, " ");
7192 }
7193 pw.println(" ");
7194 pw.println(" Pending broadcast:");
7195 if (mPendingBroadcast != null) {
7196 mPendingBroadcast.dump(pw, " ");
7197 } else {
7198 pw.println(" (null)");
7199 }
7200 needSep = true;
7201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007202
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007203 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007204 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007205 pw.println(" Historical broadcasts:");
7206 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7207 BroadcastRecord r = mBroadcastHistory[i];
7208 if (r == null) {
7209 break;
7210 }
7211 pw.println(" Historical Broadcast #" + i + ":");
7212 r.dump(pw, " ");
7213 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007214 needSep = true;
7215 }
7216
7217 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007218 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007219 pw.println(" Sticky broadcasts:");
7220 StringBuilder sb = new StringBuilder(128);
7221 for (Map.Entry<String, ArrayList<Intent>> ent
7222 : mStickyBroadcasts.entrySet()) {
7223 pw.print(" * Sticky action "); pw.print(ent.getKey());
7224 pw.println(":");
7225 ArrayList<Intent> intents = ent.getValue();
7226 final int N = intents.size();
7227 for (int i=0; i<N; i++) {
7228 sb.setLength(0);
7229 sb.append(" Intent: ");
7230 intents.get(i).toShortString(sb, true, false);
7231 pw.println(sb.toString());
7232 Bundle bundle = intents.get(i).getExtras();
7233 if (bundle != null) {
7234 pw.print(" ");
7235 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236 }
7237 }
7238 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007239 needSep = true;
7240 }
7241
7242 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007243 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007244 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007245 pw.println(" mHandler:");
7246 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007247 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007248 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007249
7250 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 }
7252
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007253 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7254 int opti, boolean dumpAll) {
7255 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007256
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007257 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007258 if (mServices.size() > 0) {
7259 pw.println(" Active services:");
7260 Iterator<ServiceRecord> it = mServices.values().iterator();
7261 while (it.hasNext()) {
7262 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007263 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007264 r.dump(pw, " ");
7265 }
7266 needSep = true;
7267 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007269
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007270 if (mPendingServices.size() > 0) {
7271 if (needSep) pw.println(" ");
7272 pw.println(" Pending services:");
7273 for (int i=0; i<mPendingServices.size(); i++) {
7274 ServiceRecord r = mPendingServices.get(i);
7275 pw.print(" * Pending "); pw.println(r);
7276 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007277 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007278 needSep = true;
7279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007280
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007281 if (mRestartingServices.size() > 0) {
7282 if (needSep) pw.println(" ");
7283 pw.println(" Restarting services:");
7284 for (int i=0; i<mRestartingServices.size(); i++) {
7285 ServiceRecord r = mRestartingServices.get(i);
7286 pw.print(" * Restarting "); pw.println(r);
7287 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007288 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007289 needSep = true;
7290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007291
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007292 if (mStoppingServices.size() > 0) {
7293 if (needSep) pw.println(" ");
7294 pw.println(" Stopping services:");
7295 for (int i=0; i<mStoppingServices.size(); i++) {
7296 ServiceRecord r = mStoppingServices.get(i);
7297 pw.print(" * Stopping "); pw.println(r);
7298 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007300 needSep = true;
7301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007303 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007304 if (mServiceConnections.size() > 0) {
7305 if (needSep) pw.println(" ");
7306 pw.println(" Connection bindings to services:");
7307 Iterator<ConnectionRecord> it
7308 = mServiceConnections.values().iterator();
7309 while (it.hasNext()) {
7310 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007311 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007312 r.dump(pw, " ");
7313 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007314 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 }
7316 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007317
7318 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319 }
7320
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007321 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7322 int opti, boolean dumpAll) {
7323 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007325 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007326 if (mProvidersByClass.size() > 0) {
7327 if (needSep) pw.println(" ");
7328 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007329 Iterator<Map.Entry<String, ContentProviderRecord>> it
7330 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007331 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007332 Map.Entry<String, ContentProviderRecord> e = it.next();
7333 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007334 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007335 r.dump(pw, " ");
7336 }
7337 needSep = true;
7338 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007339
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007340 if (mProvidersByName.size() > 0) {
7341 pw.println(" ");
7342 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007343 Iterator<Map.Entry<String, ContentProviderRecord>> it
7344 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007345 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007346 Map.Entry<String, ContentProviderRecord> e = it.next();
7347 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007348 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7349 pw.println(r);
7350 }
7351 needSep = true;
7352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007354
7355 if (mLaunchingProviders.size() > 0) {
7356 if (needSep) pw.println(" ");
7357 pw.println(" Launching content providers:");
7358 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7359 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7360 pw.println(mLaunchingProviders.get(i));
7361 }
7362 needSep = true;
7363 }
7364
7365 if (mGrantedUriPermissions.size() > 0) {
7366 pw.println();
7367 pw.println("Granted Uri Permissions:");
7368 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7369 int uid = mGrantedUriPermissions.keyAt(i);
7370 HashMap<Uri, UriPermission> perms
7371 = mGrantedUriPermissions.valueAt(i);
7372 pw.print(" * UID "); pw.print(uid);
7373 pw.println(" holds:");
7374 for (UriPermission perm : perms.values()) {
7375 pw.print(" "); pw.println(perm);
7376 perm.dump(pw, " ");
7377 }
7378 }
7379 needSep = true;
7380 }
7381
7382 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383 }
7384
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007385 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7386 int opti, boolean dumpAll) {
7387 boolean needSep = false;
7388
7389 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 if (this.mIntentSenderRecords.size() > 0) {
7391 Iterator<WeakReference<PendingIntentRecord>> it
7392 = mIntentSenderRecords.values().iterator();
7393 while (it.hasNext()) {
7394 WeakReference<PendingIntentRecord> ref = it.next();
7395 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007396 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007397 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007398 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007399 rec.dump(pw, " ");
7400 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007401 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007402 }
7403 }
7404 }
7405 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007406
7407 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007408 }
7409
7410 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007411 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007412 TaskRecord lastTask = null;
7413 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007414 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007415 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007416 if (lastTask != r.task) {
7417 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007418 pw.print(prefix);
7419 pw.print(full ? "* " : " ");
7420 pw.println(lastTask);
7421 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007422 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007425 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7426 pw.print(" #"); pw.print(i); pw.print(": ");
7427 pw.println(r);
7428 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007429 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 }
7432 }
7433
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007434 private static String buildOomTag(String prefix, String space, int val, int base) {
7435 if (val == base) {
7436 if (space == null) return prefix;
7437 return prefix + " ";
7438 }
7439 return prefix + "+" + Integer.toString(val-base);
7440 }
7441
7442 private static final int dumpProcessList(PrintWriter pw,
7443 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007444 String prefix, String normalLabel, String persistentLabel,
7445 boolean inclOomAdj) {
7446 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007447 final int N = list.size()-1;
7448 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007449 ProcessRecord r = (ProcessRecord)list.get(i);
7450 if (false) {
7451 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7452 + " #" + i + ":");
7453 r.dump(pw, prefix + " ");
7454 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007455 String oomAdj;
7456 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007457 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007458 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007459 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7460 } else if (r.setAdj >= HOME_APP_ADJ) {
7461 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7462 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7463 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7464 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7465 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007466 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7467 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7468 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7469 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007470 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7471 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7472 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7473 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007474 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007475 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007476 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007477 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007478 } else {
7479 oomAdj = Integer.toString(r.setAdj);
7480 }
7481 String schedGroup;
7482 switch (r.setSchedGroup) {
7483 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7484 schedGroup = "B";
7485 break;
7486 case Process.THREAD_GROUP_DEFAULT:
7487 schedGroup = "F";
7488 break;
7489 default:
7490 schedGroup = Integer.toString(r.setSchedGroup);
7491 break;
7492 }
7493 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007495 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007496 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007497 pw.print(prefix);
7498 pw.print(" ");
7499 if (r.adjTarget instanceof ComponentName) {
7500 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7501 } else if (r.adjTarget != null) {
7502 pw.print(r.adjTarget.toString());
7503 } else {
7504 pw.print("{null}");
7505 }
7506 pw.print("<=");
7507 if (r.adjSource instanceof ProcessRecord) {
7508 pw.print("Proc{");
7509 pw.print(((ProcessRecord)r.adjSource).toShortString());
7510 pw.println("}");
7511 } else if (r.adjSource != null) {
7512 pw.println(r.adjSource.toString());
7513 } else {
7514 pw.println("{null}");
7515 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517 } else {
7518 pw.println(String.format("%s%s #%2d: %s",
7519 prefix, (r.persistent ? persistentLabel : normalLabel),
7520 i, r.toString()));
7521 }
7522 if (r.persistent) {
7523 numPers++;
7524 }
7525 }
7526 return numPers;
7527 }
7528
Dianne Hackborn472ad872010-04-07 17:31:48 -07007529 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007530 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007531 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007532 long uptime = SystemClock.uptimeMillis();
7533 long realtime = SystemClock.elapsedRealtime();
7534
7535 if (isCheckinRequest) {
7536 // short checkin version
7537 pw.println(uptime + "," + realtime);
7538 pw.flush();
7539 } else {
7540 pw.println("Applications Memory Usage (kB):");
7541 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7542 }
7543 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7544 ProcessRecord r = (ProcessRecord)list.get(i);
7545 if (r.thread != null) {
7546 if (!isCheckinRequest) {
7547 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7548 pw.flush();
7549 }
7550 try {
7551 r.thread.asBinder().dump(fd, args);
7552 } catch (RemoteException e) {
7553 if (!isCheckinRequest) {
7554 pw.println("Got RemoteException!");
7555 pw.flush();
7556 }
7557 }
7558 }
7559 }
7560 }
7561
7562 /**
7563 * Searches array of arguments for the specified string
7564 * @param args array of argument strings
7565 * @param value value to search for
7566 * @return true if the value is contained in the array
7567 */
7568 private static boolean scanArgs(String[] args, String value) {
7569 if (args != null) {
7570 for (String arg : args) {
7571 if (value.equals(arg)) {
7572 return true;
7573 }
7574 }
7575 }
7576 return false;
7577 }
7578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 private final void killServicesLocked(ProcessRecord app,
7580 boolean allowRestart) {
7581 // Report disconnected services.
7582 if (false) {
7583 // XXX we are letting the client link to the service for
7584 // death notifications.
7585 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007586 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007587 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007588 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007589 if (r.connections.size() > 0) {
7590 Iterator<ConnectionRecord> jt
7591 = r.connections.values().iterator();
7592 while (jt.hasNext()) {
7593 ConnectionRecord c = jt.next();
7594 if (c.binding.client != app) {
7595 try {
7596 //c.conn.connected(r.className, null);
7597 } catch (Exception e) {
7598 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007599 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007600 + r.shortName
7601 + " from app " + app.processName, e);
7602 }
7603 }
7604 }
7605 }
7606 }
7607 }
7608 }
7609
7610 // Clean up any connections this application has to other services.
7611 if (app.connections.size() > 0) {
7612 Iterator<ConnectionRecord> it = app.connections.iterator();
7613 while (it.hasNext()) {
7614 ConnectionRecord r = it.next();
7615 removeConnectionLocked(r, app, null);
7616 }
7617 }
7618 app.connections.clear();
7619
7620 if (app.services.size() != 0) {
7621 // Any services running in the application need to be placed
7622 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007623 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007624 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007625 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 synchronized (sr.stats.getBatteryStats()) {
7627 sr.stats.stopLaunchedLocked();
7628 }
7629 sr.app = null;
7630 sr.executeNesting = 0;
7631 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007632
7633 boolean hasClients = sr.bindings.size() > 0;
7634 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 Iterator<IntentBindRecord> bindings
7636 = sr.bindings.values().iterator();
7637 while (bindings.hasNext()) {
7638 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007639 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007640 + ": shouldUnbind=" + b.hasBound);
7641 b.binder = null;
7642 b.requested = b.received = b.hasBound = false;
7643 }
7644 }
7645
7646 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007647 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007648 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007649 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 sr.crashCount, sr.shortName, app.pid);
7651 bringDownServiceLocked(sr, true);
7652 } else if (!allowRestart) {
7653 bringDownServiceLocked(sr, true);
7654 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007655 boolean canceled = scheduleServiceRestartLocked(sr, true);
7656
7657 // Should the service remain running? Note that in the
7658 // extreme case of so many attempts to deliver a command
7659 // that it failed, that we also will stop it here.
7660 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7661 if (sr.pendingStarts.size() == 0) {
7662 sr.startRequested = false;
7663 if (!hasClients) {
7664 // Whoops, no reason to restart!
7665 bringDownServiceLocked(sr, true);
7666 }
7667 }
7668 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 }
7670 }
7671
7672 if (!allowRestart) {
7673 app.services.clear();
7674 }
7675 }
7676
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007677 // Make sure we have no more records on the stopping list.
7678 int i = mStoppingServices.size();
7679 while (i > 0) {
7680 i--;
7681 ServiceRecord sr = mStoppingServices.get(i);
7682 if (sr.app == app) {
7683 mStoppingServices.remove(i);
7684 }
7685 }
7686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687 app.executingServices.clear();
7688 }
7689
7690 private final void removeDyingProviderLocked(ProcessRecord proc,
7691 ContentProviderRecord cpr) {
7692 synchronized (cpr) {
7693 cpr.launchingApp = null;
7694 cpr.notifyAll();
7695 }
7696
7697 mProvidersByClass.remove(cpr.info.name);
7698 String names[] = cpr.info.authority.split(";");
7699 for (int j = 0; j < names.length; j++) {
7700 mProvidersByName.remove(names[j]);
7701 }
7702
7703 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7704 while (cit.hasNext()) {
7705 ProcessRecord capp = cit.next();
7706 if (!capp.persistent && capp.thread != null
7707 && capp.pid != 0
7708 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007709 Slog.i(TAG, "Kill " + capp.processName
7710 + " (pid " + capp.pid + "): provider " + cpr.info.name
7711 + " in dying process " + proc.processName);
7712 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7713 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714 Process.killProcess(capp.pid);
7715 }
7716 }
7717
7718 mLaunchingProviders.remove(cpr);
7719 }
7720
7721 /**
7722 * Main code for cleaning up a process when it has gone away. This is
7723 * called both as a result of the process dying, or directly when stopping
7724 * a process when running in single process mode.
7725 */
7726 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7727 boolean restarting, int index) {
7728 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007729 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 }
7731
Dianne Hackborn36124872009-10-08 16:22:03 -07007732 mProcessesToGc.remove(app);
7733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 // Dismiss any open dialogs.
7735 if (app.crashDialog != null) {
7736 app.crashDialog.dismiss();
7737 app.crashDialog = null;
7738 }
7739 if (app.anrDialog != null) {
7740 app.anrDialog.dismiss();
7741 app.anrDialog = null;
7742 }
7743 if (app.waitDialog != null) {
7744 app.waitDialog.dismiss();
7745 app.waitDialog = null;
7746 }
7747
7748 app.crashing = false;
7749 app.notResponding = false;
7750
7751 app.resetPackageList();
7752 app.thread = null;
7753 app.forcingToForeground = null;
7754 app.foregroundServices = false;
7755
7756 killServicesLocked(app, true);
7757
7758 boolean restart = false;
7759
7760 int NL = mLaunchingProviders.size();
7761
7762 // Remove published content providers.
7763 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007764 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007765 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007766 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007767 cpr.provider = null;
7768 cpr.app = null;
7769
7770 // See if someone is waiting for this provider... in which
7771 // case we don't remove it, but just let it restart.
7772 int i = 0;
7773 if (!app.bad) {
7774 for (; i<NL; i++) {
7775 if (mLaunchingProviders.get(i) == cpr) {
7776 restart = true;
7777 break;
7778 }
7779 }
7780 } else {
7781 i = NL;
7782 }
7783
7784 if (i >= NL) {
7785 removeDyingProviderLocked(app, cpr);
7786 NL = mLaunchingProviders.size();
7787 }
7788 }
7789 app.pubProviders.clear();
7790 }
7791
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007792 // Take care of any launching providers waiting for this process.
7793 if (checkAppInLaunchingProvidersLocked(app, false)) {
7794 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 // Unregister from connected content providers.
7798 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007799 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 while (it.hasNext()) {
7801 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7802 cpr.clients.remove(app);
7803 }
7804 app.conProviders.clear();
7805 }
7806
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007807 // At this point there may be remaining entries in mLaunchingProviders
7808 // where we were the only one waiting, so they are no longer of use.
7809 // Look for these and clean up if found.
7810 // XXX Commented out for now. Trying to figure out a way to reproduce
7811 // the actual situation to identify what is actually going on.
7812 if (false) {
7813 for (int i=0; i<NL; i++) {
7814 ContentProviderRecord cpr = (ContentProviderRecord)
7815 mLaunchingProviders.get(i);
7816 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7817 synchronized (cpr) {
7818 cpr.launchingApp = null;
7819 cpr.notifyAll();
7820 }
7821 }
7822 }
7823 }
7824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 skipCurrentReceiverLocked(app);
7826
7827 // Unregister any receivers.
7828 if (app.receivers.size() > 0) {
7829 Iterator<ReceiverList> it = app.receivers.iterator();
7830 while (it.hasNext()) {
7831 removeReceiverLocked(it.next());
7832 }
7833 app.receivers.clear();
7834 }
7835
Christopher Tate181fafa2009-05-14 11:12:14 -07007836 // If the app is undergoing backup, tell the backup manager about it
7837 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007838 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007839 try {
7840 IBackupManager bm = IBackupManager.Stub.asInterface(
7841 ServiceManager.getService(Context.BACKUP_SERVICE));
7842 bm.agentDisconnected(app.info.packageName);
7843 } catch (RemoteException e) {
7844 // can't happen; backup manager is local
7845 }
7846 }
7847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007848 // If the caller is restarting this app, then leave it in its
7849 // current lists and let the caller take care of it.
7850 if (restarting) {
7851 return;
7852 }
7853
7854 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007855 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856 "Removing non-persistent process during cleanup: " + app);
7857 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007858 if (mHeavyWeightProcess == app) {
7859 mHeavyWeightProcess = null;
7860 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 } else if (!app.removed) {
7863 // This app is persistent, so we need to keep its record around.
7864 // If it is not already on the pending app list, add it there
7865 // and start a new process for it.
7866 app.thread = null;
7867 app.forcingToForeground = null;
7868 app.foregroundServices = false;
7869 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7870 mPersistentStartingProcesses.add(app);
7871 restart = true;
7872 }
7873 }
7874 mProcessesOnHold.remove(app);
7875
The Android Open Source Project4df24232009-03-05 14:34:35 -08007876 if (app == mHomeProcess) {
7877 mHomeProcess = null;
7878 }
7879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 if (restart) {
7881 // We have components that still need to be running in the
7882 // process, so re-launch it.
7883 mProcessNames.put(app.processName, app.info.uid, app);
7884 startProcessLocked(app, "restart", app.processName);
7885 } else if (app.pid > 0 && app.pid != MY_PID) {
7886 // Goodbye!
7887 synchronized (mPidsSelfLocked) {
7888 mPidsSelfLocked.remove(app.pid);
7889 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
7890 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007891 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 }
7893 }
7894
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007895 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
7896 // Look through the content providers we are waiting to have launched,
7897 // and if any run in this process then either schedule a restart of
7898 // the process or kill the client waiting for it if this process has
7899 // gone bad.
7900 int NL = mLaunchingProviders.size();
7901 boolean restart = false;
7902 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007903 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007904 if (cpr.launchingApp == app) {
7905 if (!alwaysBad && !app.bad) {
7906 restart = true;
7907 } else {
7908 removeDyingProviderLocked(app, cpr);
7909 NL = mLaunchingProviders.size();
7910 }
7911 }
7912 }
7913 return restart;
7914 }
7915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007916 // =========================================================
7917 // SERVICES
7918 // =========================================================
7919
7920 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
7921 ActivityManager.RunningServiceInfo info =
7922 new ActivityManager.RunningServiceInfo();
7923 info.service = r.name;
7924 if (r.app != null) {
7925 info.pid = r.app.pid;
7926 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007927 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007928 info.process = r.processName;
7929 info.foreground = r.isForeground;
7930 info.activeSince = r.createTime;
7931 info.started = r.startRequested;
7932 info.clientCount = r.connections.size();
7933 info.crashCount = r.crashCount;
7934 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007935 if (r.isForeground) {
7936 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
7937 }
7938 if (r.startRequested) {
7939 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
7940 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007941 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007942 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
7943 }
7944 if (r.app != null && r.app.persistent) {
7945 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
7946 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007947 for (ConnectionRecord conn : r.connections.values()) {
7948 if (conn.clientLabel != 0) {
7949 info.clientPackage = conn.binding.client.info.packageName;
7950 info.clientLabel = conn.clientLabel;
7951 break;
7952 }
7953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007954 return info;
7955 }
7956
7957 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
7958 int flags) {
7959 synchronized (this) {
7960 ArrayList<ActivityManager.RunningServiceInfo> res
7961 = new ArrayList<ActivityManager.RunningServiceInfo>();
7962
7963 if (mServices.size() > 0) {
7964 Iterator<ServiceRecord> it = mServices.values().iterator();
7965 while (it.hasNext() && res.size() < maxNum) {
7966 res.add(makeRunningServiceInfoLocked(it.next()));
7967 }
7968 }
7969
7970 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
7971 ServiceRecord r = mRestartingServices.get(i);
7972 ActivityManager.RunningServiceInfo info =
7973 makeRunningServiceInfoLocked(r);
7974 info.restarting = r.nextRestartTime;
7975 res.add(info);
7976 }
7977
7978 return res;
7979 }
7980 }
7981
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007982 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
7983 synchronized (this) {
7984 ServiceRecord r = mServices.get(name);
7985 if (r != null) {
7986 for (ConnectionRecord conn : r.connections.values()) {
7987 if (conn.clientIntent != null) {
7988 return conn.clientIntent;
7989 }
7990 }
7991 }
7992 }
7993 return null;
7994 }
7995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007996 private final ServiceRecord findServiceLocked(ComponentName name,
7997 IBinder token) {
7998 ServiceRecord r = mServices.get(name);
7999 return r == token ? r : null;
8000 }
8001
8002 private final class ServiceLookupResult {
8003 final ServiceRecord record;
8004 final String permission;
8005
8006 ServiceLookupResult(ServiceRecord _record, String _permission) {
8007 record = _record;
8008 permission = _permission;
8009 }
8010 };
8011
8012 private ServiceLookupResult findServiceLocked(Intent service,
8013 String resolvedType) {
8014 ServiceRecord r = null;
8015 if (service.getComponent() != null) {
8016 r = mServices.get(service.getComponent());
8017 }
8018 if (r == null) {
8019 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8020 r = mServicesByIntent.get(filter);
8021 }
8022
8023 if (r == null) {
8024 try {
8025 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008026 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008027 service, resolvedType, 0);
8028 ServiceInfo sInfo =
8029 rInfo != null ? rInfo.serviceInfo : null;
8030 if (sInfo == null) {
8031 return null;
8032 }
8033
8034 ComponentName name = new ComponentName(
8035 sInfo.applicationInfo.packageName, sInfo.name);
8036 r = mServices.get(name);
8037 } catch (RemoteException ex) {
8038 // pm is in same process, this will never happen.
8039 }
8040 }
8041 if (r != null) {
8042 int callingPid = Binder.getCallingPid();
8043 int callingUid = Binder.getCallingUid();
8044 if (checkComponentPermission(r.permission,
8045 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8046 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008047 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 + " from pid=" + callingPid
8049 + ", uid=" + callingUid
8050 + " requires " + r.permission);
8051 return new ServiceLookupResult(null, r.permission);
8052 }
8053 return new ServiceLookupResult(r, null);
8054 }
8055 return null;
8056 }
8057
8058 private class ServiceRestarter implements Runnable {
8059 private ServiceRecord mService;
8060
8061 void setService(ServiceRecord service) {
8062 mService = service;
8063 }
8064
8065 public void run() {
8066 synchronized(ActivityManagerService.this) {
8067 performServiceRestartLocked(mService);
8068 }
8069 }
8070 }
8071
8072 private ServiceLookupResult retrieveServiceLocked(Intent service,
8073 String resolvedType, int callingPid, int callingUid) {
8074 ServiceRecord r = null;
8075 if (service.getComponent() != null) {
8076 r = mServices.get(service.getComponent());
8077 }
8078 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8079 r = mServicesByIntent.get(filter);
8080 if (r == null) {
8081 try {
8082 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008083 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008084 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008085 ServiceInfo sInfo =
8086 rInfo != null ? rInfo.serviceInfo : null;
8087 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008088 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008089 ": not found");
8090 return null;
8091 }
8092
8093 ComponentName name = new ComponentName(
8094 sInfo.applicationInfo.packageName, sInfo.name);
8095 r = mServices.get(name);
8096 if (r == null) {
8097 filter = new Intent.FilterComparison(service.cloneFilter());
8098 ServiceRestarter res = new ServiceRestarter();
8099 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8100 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8101 synchronized (stats) {
8102 ss = stats.getServiceStatsLocked(
8103 sInfo.applicationInfo.uid, sInfo.packageName,
8104 sInfo.name);
8105 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008106 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008107 res.setService(r);
8108 mServices.put(name, r);
8109 mServicesByIntent.put(filter, r);
8110
8111 // Make sure this component isn't in the pending list.
8112 int N = mPendingServices.size();
8113 for (int i=0; i<N; i++) {
8114 ServiceRecord pr = mPendingServices.get(i);
8115 if (pr.name.equals(name)) {
8116 mPendingServices.remove(i);
8117 i--;
8118 N--;
8119 }
8120 }
8121 }
8122 } catch (RemoteException ex) {
8123 // pm is in same process, this will never happen.
8124 }
8125 }
8126 if (r != null) {
8127 if (checkComponentPermission(r.permission,
8128 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8129 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008130 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008131 + " from pid=" + Binder.getCallingPid()
8132 + ", uid=" + Binder.getCallingUid()
8133 + " requires " + r.permission);
8134 return new ServiceLookupResult(null, r.permission);
8135 }
8136 return new ServiceLookupResult(r, null);
8137 }
8138 return null;
8139 }
8140
8141 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8142 long now = SystemClock.uptimeMillis();
8143 if (r.executeNesting == 0 && r.app != null) {
8144 if (r.app.executingServices.size() == 0) {
8145 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8146 msg.obj = r.app;
8147 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8148 }
8149 r.app.executingServices.add(r);
8150 }
8151 r.executeNesting++;
8152 r.executingStart = now;
8153 }
8154
8155 private final void sendServiceArgsLocked(ServiceRecord r,
8156 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008157 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008158 if (N == 0) {
8159 return;
8160 }
8161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 int i = 0;
8163 while (i < N) {
8164 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008165 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008166 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008167 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -07008168 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008169 // If somehow we got a dummy start at the front, then
8170 // just drop it here.
8171 i++;
8172 continue;
8173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 bumpServiceExecutingLocked(r);
8175 if (!oomAdjusted) {
8176 oomAdjusted = true;
8177 updateOomAdjLocked(r.app);
8178 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008179 int flags = 0;
8180 if (si.deliveryCount > 0) {
8181 flags |= Service.START_FLAG_RETRY;
8182 }
8183 if (si.doneExecutingCount > 0) {
8184 flags |= Service.START_FLAG_REDELIVERY;
8185 }
8186 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
8187 si.deliveredTime = SystemClock.uptimeMillis();
8188 r.deliveredStarts.add(si);
8189 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008191 } catch (RemoteException e) {
8192 // Remote process gone... we'll let the normal cleanup take
8193 // care of this.
8194 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008195 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008196 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008197 break;
8198 }
8199 }
8200 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008201 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 } else {
8203 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008205 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008206 }
8207 }
8208 }
8209
8210 private final boolean requestServiceBindingLocked(ServiceRecord r,
8211 IntentBindRecord i, boolean rebind) {
8212 if (r.app == null || r.app.thread == null) {
8213 // If service is not currently running, can't yet bind.
8214 return false;
8215 }
8216 if ((!i.requested || rebind) && i.apps.size() > 0) {
8217 try {
8218 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008219 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008220 + ": shouldUnbind=" + i.hasBound);
8221 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8222 if (!rebind) {
8223 i.requested = true;
8224 }
8225 i.hasBound = true;
8226 i.doRebind = false;
8227 } catch (RemoteException e) {
8228 return false;
8229 }
8230 }
8231 return true;
8232 }
8233
8234 private final void requestServiceBindingsLocked(ServiceRecord r) {
8235 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8236 while (bindings.hasNext()) {
8237 IntentBindRecord i = bindings.next();
8238 if (!requestServiceBindingLocked(r, i, false)) {
8239 break;
8240 }
8241 }
8242 }
8243
8244 private final void realStartServiceLocked(ServiceRecord r,
8245 ProcessRecord app) throws RemoteException {
8246 if (app.thread == null) {
8247 throw new RemoteException();
8248 }
8249
8250 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008251 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008252
8253 app.services.add(r);
8254 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008255 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256
8257 boolean created = false;
8258 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008259 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008261 mStringBuilder.setLength(0);
8262 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008263 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008264 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008265 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 synchronized (r.stats.getBatteryStats()) {
8267 r.stats.startLaunchedLocked();
8268 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008269 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008271 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008272 created = true;
8273 } finally {
8274 if (!created) {
8275 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008276 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008277 }
8278 }
8279
8280 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008281
8282 // If the service is in the started state, and there are no
8283 // pending arguments, then fake up one so its onStartCommand() will
8284 // be called.
8285 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8286 r.lastStartId++;
8287 if (r.lastStartId < 1) {
8288 r.lastStartId = 1;
8289 }
8290 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
8291 }
8292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008293 sendServiceArgsLocked(r, true);
8294 }
8295
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008296 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8297 boolean allowCancel) {
8298 boolean canceled = false;
8299
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008300 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008301 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008302 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008303
8304 // Any delivered but not yet finished starts should be put back
8305 // on the pending list.
8306 final int N = r.deliveredStarts.size();
8307 if (N > 0) {
8308 for (int i=N-1; i>=0; i--) {
8309 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
8310 if (si.intent == null) {
8311 // We'll generate this again if needed.
8312 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8313 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8314 r.pendingStarts.add(0, si);
8315 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8316 dur *= 2;
8317 if (minDuration < dur) minDuration = dur;
8318 if (resetTime < dur) resetTime = dur;
8319 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008320 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008321 + r.name);
8322 canceled = true;
8323 }
8324 }
8325 r.deliveredStarts.clear();
8326 }
8327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 r.totalRestartCount++;
8329 if (r.restartDelay == 0) {
8330 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008331 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008332 } else {
8333 // If it has been a "reasonably long time" since the service
8334 // was started, then reset our restart duration back to
8335 // the beginning, so we don't infinitely increase the duration
8336 // on a service that just occasionally gets killed (which is
8337 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008338 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008340 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008342 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008343 if (r.restartDelay < minDuration) {
8344 r.restartDelay = minDuration;
8345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 }
8347 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008348
8349 r.nextRestartTime = now + r.restartDelay;
8350
8351 // Make sure that we don't end up restarting a bunch of services
8352 // all at the same time.
8353 boolean repeat;
8354 do {
8355 repeat = false;
8356 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8357 ServiceRecord r2 = mRestartingServices.get(i);
8358 if (r2 != r && r.nextRestartTime
8359 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8360 && r.nextRestartTime
8361 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8362 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8363 r.restartDelay = r.nextRestartTime - now;
8364 repeat = true;
8365 break;
8366 }
8367 }
8368 } while (repeat);
8369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008370 if (!mRestartingServices.contains(r)) {
8371 mRestartingServices.add(r);
8372 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008373
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008374 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008376 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008377 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008378 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008379 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008380 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008381 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008382 r.shortName, r.restartDelay);
8383
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008384 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 }
8386
8387 final void performServiceRestartLocked(ServiceRecord r) {
8388 if (!mRestartingServices.contains(r)) {
8389 return;
8390 }
8391 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8392 }
8393
8394 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8395 if (r.restartDelay == 0) {
8396 return false;
8397 }
8398 r.resetRestartCounter();
8399 mRestartingServices.remove(r);
8400 mHandler.removeCallbacks(r.restarter);
8401 return true;
8402 }
8403
8404 private final boolean bringUpServiceLocked(ServiceRecord r,
8405 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008406 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 //r.dump(" ");
8408
Dianne Hackborn36124872009-10-08 16:22:03 -07008409 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410 sendServiceArgsLocked(r, false);
8411 return true;
8412 }
8413
8414 if (!whileRestarting && r.restartDelay > 0) {
8415 // If waiting for a restart, then do nothing.
8416 return true;
8417 }
8418
Joe Onorato8a9b2202010-02-26 18:56:32 -08008419 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008420 + " " + r.intent);
8421
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008422 // We are now bringing the service up, so no longer in the
8423 // restarting state.
8424 mRestartingServices.remove(r);
8425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008426 final String appName = r.processName;
8427 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8428 if (app != null && app.thread != null) {
8429 try {
8430 realStartServiceLocked(r, app);
8431 return true;
8432 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008433 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008434 }
8435
8436 // If a dead object exception was thrown -- fall through to
8437 // restart the application.
8438 }
8439
Dianne Hackborn36124872009-10-08 16:22:03 -07008440 // Not running -- get it started, and enqueue this service record
8441 // to be executed when the app comes up.
8442 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8443 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008444 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008445 + r.appInfo.packageName + "/"
8446 + r.appInfo.uid + " for service "
8447 + r.intent.getIntent() + ": process is bad");
8448 bringDownServiceLocked(r, true);
8449 return false;
8450 }
8451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008453 mPendingServices.add(r);
8454 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008456 return true;
8457 }
8458
8459 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008460 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 //r.dump(" ");
8462
8463 // Does it still need to run?
8464 if (!force && r.startRequested) {
8465 return;
8466 }
8467 if (r.connections.size() > 0) {
8468 if (!force) {
8469 // XXX should probably keep a count of the number of auto-create
8470 // connections directly in the service.
8471 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8472 while (it.hasNext()) {
8473 ConnectionRecord cr = it.next();
8474 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
8475 return;
8476 }
8477 }
8478 }
8479
8480 // Report to all of the connections that the service is no longer
8481 // available.
8482 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8483 while (it.hasNext()) {
8484 ConnectionRecord c = it.next();
8485 try {
8486 // todo: shouldn't be a synchronous call!
8487 c.conn.connected(r.name, null);
8488 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008489 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008490 " to connection " + c.conn.asBinder() +
8491 " (in " + c.binding.client.processName + ")", e);
8492 }
8493 }
8494 }
8495
8496 // Tell the service that it has been unbound.
8497 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8498 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8499 while (it.hasNext()) {
8500 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008501 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 + ": hasBound=" + ibr.hasBound);
8503 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8504 try {
8505 bumpServiceExecutingLocked(r);
8506 updateOomAdjLocked(r.app);
8507 ibr.hasBound = false;
8508 r.app.thread.scheduleUnbindService(r,
8509 ibr.intent.getIntent());
8510 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008511 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008512 + r.shortName, e);
8513 serviceDoneExecutingLocked(r, true);
8514 }
8515 }
8516 }
8517 }
8518
Joe Onorato8a9b2202010-02-26 18:56:32 -08008519 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008521 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 System.identityHashCode(r), r.shortName,
8523 (r.app != null) ? r.app.pid : -1);
8524
8525 mServices.remove(r.name);
8526 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008527 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 r.totalRestartCount = 0;
8529 unscheduleServiceRestartLocked(r);
8530
8531 // Also make sure it is not on the pending list.
8532 int N = mPendingServices.size();
8533 for (int i=0; i<N; i++) {
8534 if (mPendingServices.get(i) == r) {
8535 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008536 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 TAG, "Removed pending service: " + r.shortName);
8538 i--;
8539 N--;
8540 }
8541 }
8542
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008543 r.cancelNotification();
8544 r.isForeground = false;
8545 r.foregroundId = 0;
8546 r.foregroundNoti = null;
8547
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008548 // Clear start entries.
8549 r.deliveredStarts.clear();
8550 r.pendingStarts.clear();
8551
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008552 if (r.app != null) {
8553 synchronized (r.stats.getBatteryStats()) {
8554 r.stats.stopLaunchedLocked();
8555 }
8556 r.app.services.remove(r);
8557 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008558 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008559 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008560 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008561 bumpServiceExecutingLocked(r);
8562 mStoppingServices.add(r);
8563 updateOomAdjLocked(r.app);
8564 r.app.thread.scheduleStopService(r);
8565 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008566 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008567 + r.shortName, e);
8568 serviceDoneExecutingLocked(r, true);
8569 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008570 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008571 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008572 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008573 TAG, "Removed service that has no process: " + r.shortName);
8574 }
8575 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008576 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008577 TAG, "Removed service that is not running: " + r.shortName);
8578 }
8579 }
8580
8581 ComponentName startServiceLocked(IApplicationThread caller,
8582 Intent service, String resolvedType,
8583 int callingPid, int callingUid) {
8584 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008585 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 + " type=" + resolvedType + " args=" + service.getExtras());
8587
8588 if (caller != null) {
8589 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8590 if (callerApp == null) {
8591 throw new SecurityException(
8592 "Unable to find app for caller " + caller
8593 + " (pid=" + Binder.getCallingPid()
8594 + ") when starting service " + service);
8595 }
8596 }
8597
8598 ServiceLookupResult res =
8599 retrieveServiceLocked(service, resolvedType,
8600 callingPid, callingUid);
8601 if (res == null) {
8602 return null;
8603 }
8604 if (res.record == null) {
8605 return new ComponentName("!", res.permission != null
8606 ? res.permission : "private to package");
8607 }
8608 ServiceRecord r = res.record;
8609 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008610 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008611 + r.shortName);
8612 }
8613 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008614 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008615 r.lastStartId++;
8616 if (r.lastStartId < 1) {
8617 r.lastStartId = 1;
8618 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008619 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008620 r.lastActivity = SystemClock.uptimeMillis();
8621 synchronized (r.stats.getBatteryStats()) {
8622 r.stats.startRunningLocked();
8623 }
8624 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8625 return new ComponentName("!", "Service process is bad");
8626 }
8627 return r.name;
8628 }
8629 }
8630
8631 public ComponentName startService(IApplicationThread caller, Intent service,
8632 String resolvedType) {
8633 // Refuse possible leaked file descriptors
8634 if (service != null && service.hasFileDescriptors() == true) {
8635 throw new IllegalArgumentException("File descriptors passed in Intent");
8636 }
8637
8638 synchronized(this) {
8639 final int callingPid = Binder.getCallingPid();
8640 final int callingUid = Binder.getCallingUid();
8641 final long origId = Binder.clearCallingIdentity();
8642 ComponentName res = startServiceLocked(caller, service,
8643 resolvedType, callingPid, callingUid);
8644 Binder.restoreCallingIdentity(origId);
8645 return res;
8646 }
8647 }
8648
8649 ComponentName startServiceInPackage(int uid,
8650 Intent service, String resolvedType) {
8651 synchronized(this) {
8652 final long origId = Binder.clearCallingIdentity();
8653 ComponentName res = startServiceLocked(null, service,
8654 resolvedType, -1, uid);
8655 Binder.restoreCallingIdentity(origId);
8656 return res;
8657 }
8658 }
8659
8660 public int stopService(IApplicationThread caller, Intent service,
8661 String resolvedType) {
8662 // Refuse possible leaked file descriptors
8663 if (service != null && service.hasFileDescriptors() == true) {
8664 throw new IllegalArgumentException("File descriptors passed in Intent");
8665 }
8666
8667 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008668 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 + " type=" + resolvedType);
8670
8671 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8672 if (caller != null && callerApp == null) {
8673 throw new SecurityException(
8674 "Unable to find app for caller " + caller
8675 + " (pid=" + Binder.getCallingPid()
8676 + ") when stopping service " + service);
8677 }
8678
8679 // If this service is active, make sure it is stopped.
8680 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8681 if (r != null) {
8682 if (r.record != null) {
8683 synchronized (r.record.stats.getBatteryStats()) {
8684 r.record.stats.stopRunningLocked();
8685 }
8686 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008687 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008688 final long origId = Binder.clearCallingIdentity();
8689 bringDownServiceLocked(r.record, false);
8690 Binder.restoreCallingIdentity(origId);
8691 return 1;
8692 }
8693 return -1;
8694 }
8695 }
8696
8697 return 0;
8698 }
8699
8700 public IBinder peekService(Intent service, String resolvedType) {
8701 // Refuse possible leaked file descriptors
8702 if (service != null && service.hasFileDescriptors() == true) {
8703 throw new IllegalArgumentException("File descriptors passed in Intent");
8704 }
8705
8706 IBinder ret = null;
8707
8708 synchronized(this) {
8709 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8710
8711 if (r != null) {
8712 // r.record is null if findServiceLocked() failed the caller permission check
8713 if (r.record == null) {
8714 throw new SecurityException(
8715 "Permission Denial: Accessing service " + r.record.name
8716 + " from pid=" + Binder.getCallingPid()
8717 + ", uid=" + Binder.getCallingUid()
8718 + " requires " + r.permission);
8719 }
8720 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8721 if (ib != null) {
8722 ret = ib.binder;
8723 }
8724 }
8725 }
8726
8727 return ret;
8728 }
8729
8730 public boolean stopServiceToken(ComponentName className, IBinder token,
8731 int startId) {
8732 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008733 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008734 + " " + token + " startId=" + startId);
8735 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008736 if (r != null) {
8737 if (startId >= 0) {
8738 // Asked to only stop if done with all work. Note that
8739 // to avoid leaks, we will take this as dropping all
8740 // start items up to and including this one.
8741 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8742 if (si != null) {
8743 while (r.deliveredStarts.size() > 0) {
8744 if (r.deliveredStarts.remove(0) == si) {
8745 break;
8746 }
8747 }
8748 }
8749
8750 if (r.lastStartId != startId) {
8751 return false;
8752 }
8753
8754 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008755 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008756 + " is last, but have " + r.deliveredStarts.size()
8757 + " remaining args");
8758 }
8759 }
8760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008761 synchronized (r.stats.getBatteryStats()) {
8762 r.stats.stopRunningLocked();
8763 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008764 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008765 }
8766 final long origId = Binder.clearCallingIdentity();
8767 bringDownServiceLocked(r, false);
8768 Binder.restoreCallingIdentity(origId);
8769 return true;
8770 }
8771 }
8772 return false;
8773 }
8774
8775 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008776 int id, Notification notification, boolean removeNotification) {
8777 final long origId = Binder.clearCallingIdentity();
8778 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008779 synchronized(this) {
8780 ServiceRecord r = findServiceLocked(className, token);
8781 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008782 if (id != 0) {
8783 if (notification == null) {
8784 throw new IllegalArgumentException("null notification");
8785 }
8786 if (r.foregroundId != id) {
8787 r.cancelNotification();
8788 r.foregroundId = id;
8789 }
8790 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8791 r.foregroundNoti = notification;
8792 r.isForeground = true;
8793 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 if (r.app != null) {
8795 updateServiceForegroundLocked(r.app, true);
8796 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008797 } else {
8798 if (r.isForeground) {
8799 r.isForeground = false;
8800 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008801 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008802 updateServiceForegroundLocked(r.app, true);
8803 }
8804 }
8805 if (removeNotification) {
8806 r.cancelNotification();
8807 r.foregroundId = 0;
8808 r.foregroundNoti = null;
8809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008810 }
8811 }
8812 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008813 } finally {
8814 Binder.restoreCallingIdentity(origId);
8815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 }
8817
8818 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8819 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008820 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008821 if (sr.isForeground) {
8822 anyForeground = true;
8823 break;
8824 }
8825 }
8826 if (anyForeground != proc.foregroundServices) {
8827 proc.foregroundServices = anyForeground;
8828 if (oomAdj) {
8829 updateOomAdjLocked();
8830 }
8831 }
8832 }
8833
8834 public int bindService(IApplicationThread caller, IBinder token,
8835 Intent service, String resolvedType,
8836 IServiceConnection connection, int flags) {
8837 // Refuse possible leaked file descriptors
8838 if (service != null && service.hasFileDescriptors() == true) {
8839 throw new IllegalArgumentException("File descriptors passed in Intent");
8840 }
8841
8842 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008843 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 + " type=" + resolvedType + " conn=" + connection.asBinder()
8845 + " flags=0x" + Integer.toHexString(flags));
8846 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8847 if (callerApp == null) {
8848 throw new SecurityException(
8849 "Unable to find app for caller " + caller
8850 + " (pid=" + Binder.getCallingPid()
8851 + ") when binding service " + service);
8852 }
8853
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008854 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008855 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008856 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008857 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008858 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008859 return 0;
8860 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008861 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 }
8863
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008864 int clientLabel = 0;
8865 PendingIntent clientIntent = null;
8866
8867 if (callerApp.info.uid == Process.SYSTEM_UID) {
8868 // Hacky kind of thing -- allow system stuff to tell us
8869 // what they are, so we can report this elsewhere for
8870 // others to know why certain services are running.
8871 try {
8872 clientIntent = (PendingIntent)service.getParcelableExtra(
8873 Intent.EXTRA_CLIENT_INTENT);
8874 } catch (RuntimeException e) {
8875 }
8876 if (clientIntent != null) {
8877 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
8878 if (clientLabel != 0) {
8879 // There are no useful extras in the intent, trash them.
8880 // System code calling with this stuff just needs to know
8881 // this will happen.
8882 service = service.cloneFilter();
8883 }
8884 }
8885 }
8886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 ServiceLookupResult res =
8888 retrieveServiceLocked(service, resolvedType,
8889 Binder.getCallingPid(), Binder.getCallingUid());
8890 if (res == null) {
8891 return 0;
8892 }
8893 if (res.record == null) {
8894 return -1;
8895 }
8896 ServiceRecord s = res.record;
8897
8898 final long origId = Binder.clearCallingIdentity();
8899
8900 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008901 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008902 + s.shortName);
8903 }
8904
8905 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
8906 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008907 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008908
8909 IBinder binder = connection.asBinder();
8910 s.connections.put(binder, c);
8911 b.connections.add(c);
8912 if (activity != null) {
8913 if (activity.connections == null) {
8914 activity.connections = new HashSet<ConnectionRecord>();
8915 }
8916 activity.connections.add(c);
8917 }
8918 b.client.connections.add(c);
8919 mServiceConnections.put(binder, c);
8920
8921 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
8922 s.lastActivity = SystemClock.uptimeMillis();
8923 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
8924 return 0;
8925 }
8926 }
8927
8928 if (s.app != null) {
8929 // This could have made the service more important.
8930 updateOomAdjLocked(s.app);
8931 }
8932
Joe Onorato8a9b2202010-02-26 18:56:32 -08008933 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008934 + ": received=" + b.intent.received
8935 + " apps=" + b.intent.apps.size()
8936 + " doRebind=" + b.intent.doRebind);
8937
8938 if (s.app != null && b.intent.received) {
8939 // Service is already running, so we can immediately
8940 // publish the connection.
8941 try {
8942 c.conn.connected(s.name, b.intent.binder);
8943 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008944 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008945 + " to connection " + c.conn.asBinder()
8946 + " (in " + c.binding.client.processName + ")", e);
8947 }
8948
8949 // If this is the first app connected back to this binding,
8950 // and the service had previously asked to be told when
8951 // rebound, then do so.
8952 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
8953 requestServiceBindingLocked(s, b.intent, true);
8954 }
8955 } else if (!b.intent.requested) {
8956 requestServiceBindingLocked(s, b.intent, false);
8957 }
8958
8959 Binder.restoreCallingIdentity(origId);
8960 }
8961
8962 return 1;
8963 }
8964
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008965 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008966 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008967 IBinder binder = c.conn.asBinder();
8968 AppBindRecord b = c.binding;
8969 ServiceRecord s = b.service;
8970 s.connections.remove(binder);
8971 b.connections.remove(c);
8972 if (c.activity != null && c.activity != skipAct) {
8973 if (c.activity.connections != null) {
8974 c.activity.connections.remove(c);
8975 }
8976 }
8977 if (b.client != skipApp) {
8978 b.client.connections.remove(c);
8979 }
8980 mServiceConnections.remove(binder);
8981
8982 if (b.connections.size() == 0) {
8983 b.intent.apps.remove(b.client);
8984 }
8985
Joe Onorato8a9b2202010-02-26 18:56:32 -08008986 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008987 + ": shouldUnbind=" + b.intent.hasBound);
8988 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
8989 && b.intent.hasBound) {
8990 try {
8991 bumpServiceExecutingLocked(s);
8992 updateOomAdjLocked(s.app);
8993 b.intent.hasBound = false;
8994 // Assume the client doesn't want to know about a rebind;
8995 // we will deal with that later if it asks for one.
8996 b.intent.doRebind = false;
8997 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
8998 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008999 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000 serviceDoneExecutingLocked(s, true);
9001 }
9002 }
9003
9004 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9005 bringDownServiceLocked(s, false);
9006 }
9007 }
9008
9009 public boolean unbindService(IServiceConnection connection) {
9010 synchronized (this) {
9011 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009012 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009013 ConnectionRecord r = mServiceConnections.get(binder);
9014 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009015 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009016 + connection.asBinder());
9017 return false;
9018 }
9019
9020 final long origId = Binder.clearCallingIdentity();
9021
9022 removeConnectionLocked(r, null, null);
9023
9024 if (r.binding.service.app != null) {
9025 // This could have made the service less important.
9026 updateOomAdjLocked(r.binding.service.app);
9027 }
9028
9029 Binder.restoreCallingIdentity(origId);
9030 }
9031
9032 return true;
9033 }
9034
9035 public void publishService(IBinder token, Intent intent, IBinder service) {
9036 // Refuse possible leaked file descriptors
9037 if (intent != null && intent.hasFileDescriptors() == true) {
9038 throw new IllegalArgumentException("File descriptors passed in Intent");
9039 }
9040
9041 synchronized(this) {
9042 if (!(token instanceof ServiceRecord)) {
9043 throw new IllegalArgumentException("Invalid service token");
9044 }
9045 ServiceRecord r = (ServiceRecord)token;
9046
9047 final long origId = Binder.clearCallingIdentity();
9048
Joe Onorato8a9b2202010-02-26 18:56:32 -08009049 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 + " " + intent + ": " + service);
9051 if (r != null) {
9052 Intent.FilterComparison filter
9053 = new Intent.FilterComparison(intent);
9054 IntentBindRecord b = r.bindings.get(filter);
9055 if (b != null && !b.received) {
9056 b.binder = service;
9057 b.requested = true;
9058 b.received = true;
9059 if (r.connections.size() > 0) {
9060 Iterator<ConnectionRecord> it
9061 = r.connections.values().iterator();
9062 while (it.hasNext()) {
9063 ConnectionRecord c = it.next();
9064 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009065 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009066 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009067 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009069 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009070 TAG, "Published intent: " + intent);
9071 continue;
9072 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009073 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 try {
9075 c.conn.connected(r.name, service);
9076 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009077 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009078 " to connection " + c.conn.asBinder() +
9079 " (in " + c.binding.client.processName + ")", e);
9080 }
9081 }
9082 }
9083 }
9084
9085 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9086
9087 Binder.restoreCallingIdentity(origId);
9088 }
9089 }
9090 }
9091
9092 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9093 // Refuse possible leaked file descriptors
9094 if (intent != null && intent.hasFileDescriptors() == true) {
9095 throw new IllegalArgumentException("File descriptors passed in Intent");
9096 }
9097
9098 synchronized(this) {
9099 if (!(token instanceof ServiceRecord)) {
9100 throw new IllegalArgumentException("Invalid service token");
9101 }
9102 ServiceRecord r = (ServiceRecord)token;
9103
9104 final long origId = Binder.clearCallingIdentity();
9105
9106 if (r != null) {
9107 Intent.FilterComparison filter
9108 = new Intent.FilterComparison(intent);
9109 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009110 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009111 + " at " + b + ": apps="
9112 + (b != null ? b.apps.size() : 0));
9113 if (b != null) {
9114 if (b.apps.size() > 0) {
9115 // Applications have already bound since the last
9116 // unbind, so just rebind right here.
9117 requestServiceBindingLocked(r, b, true);
9118 } else {
9119 // Note to tell the service the next time there is
9120 // a new client.
9121 b.doRebind = true;
9122 }
9123 }
9124
9125 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9126
9127 Binder.restoreCallingIdentity(origId);
9128 }
9129 }
9130 }
9131
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009132 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009133 synchronized(this) {
9134 if (!(token instanceof ServiceRecord)) {
9135 throw new IllegalArgumentException("Invalid service token");
9136 }
9137 ServiceRecord r = (ServiceRecord)token;
9138 boolean inStopping = mStoppingServices.contains(token);
9139 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009140 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009141 + ": nesting=" + r.executeNesting
9142 + ", inStopping=" + inStopping);
9143 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009144 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009145 + " with incorrect token: given " + token
9146 + ", expected " + r);
9147 return;
9148 }
9149
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009150 if (type == 1) {
9151 // This is a call from a service start... take care of
9152 // book-keeping.
9153 r.callStart = true;
9154 switch (res) {
9155 case Service.START_STICKY_COMPATIBILITY:
9156 case Service.START_STICKY: {
9157 // We are done with the associated start arguments.
9158 r.findDeliveredStart(startId, true);
9159 // Don't stop if killed.
9160 r.stopIfKilled = false;
9161 break;
9162 }
9163 case Service.START_NOT_STICKY: {
9164 // We are done with the associated start arguments.
9165 r.findDeliveredStart(startId, true);
9166 if (r.lastStartId == startId) {
9167 // There is no more work, and this service
9168 // doesn't want to hang around if killed.
9169 r.stopIfKilled = true;
9170 }
9171 break;
9172 }
9173 case Service.START_REDELIVER_INTENT: {
9174 // We'll keep this item until they explicitly
9175 // call stop for it, but keep track of the fact
9176 // that it was delivered.
9177 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9178 if (si != null) {
9179 si.deliveryCount = 0;
9180 si.doneExecutingCount++;
9181 // Don't stop if killed.
9182 r.stopIfKilled = true;
9183 }
9184 break;
9185 }
9186 default:
9187 throw new IllegalArgumentException(
9188 "Unknown service start result: " + res);
9189 }
9190 if (res == Service.START_STICKY_COMPATIBILITY) {
9191 r.callStart = false;
9192 }
9193 }
9194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195 final long origId = Binder.clearCallingIdentity();
9196 serviceDoneExecutingLocked(r, inStopping);
9197 Binder.restoreCallingIdentity(origId);
9198 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009199 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009200 + " with token " + token);
9201 }
9202 }
9203 }
9204
9205 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9206 r.executeNesting--;
9207 if (r.executeNesting <= 0 && r.app != null) {
9208 r.app.executingServices.remove(r);
9209 if (r.app.executingServices.size() == 0) {
9210 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9211 }
9212 if (inStopping) {
9213 mStoppingServices.remove(r);
9214 }
9215 updateOomAdjLocked(r.app);
9216 }
9217 }
9218
9219 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009220 String anrMessage = null;
9221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 synchronized(this) {
9223 if (proc.executingServices.size() == 0 || proc.thread == null) {
9224 return;
9225 }
9226 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9227 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9228 ServiceRecord timeout = null;
9229 long nextTime = 0;
9230 while (it.hasNext()) {
9231 ServiceRecord sr = it.next();
9232 if (sr.executingStart < maxTime) {
9233 timeout = sr;
9234 break;
9235 }
9236 if (sr.executingStart > nextTime) {
9237 nextTime = sr.executingStart;
9238 }
9239 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009240 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009241 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009242 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009243 } else {
9244 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9245 msg.obj = proc;
9246 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9247 }
9248 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009249
9250 if (anrMessage != null) {
9251 appNotResponding(proc, null, null, anrMessage);
9252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009253 }
9254
9255 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009256 // BACKUP AND RESTORE
9257 // =========================================================
9258
9259 // Cause the target app to be launched if necessary and its backup agent
9260 // instantiated. The backup agent will invoke backupAgentCreated() on the
9261 // activity manager to announce its creation.
9262 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009263 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009264 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9265
9266 synchronized(this) {
9267 // !!! TODO: currently no check here that we're already bound
9268 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9269 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9270 synchronized (stats) {
9271 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9272 }
9273
9274 BackupRecord r = new BackupRecord(ss, app, backupMode);
9275 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9276 // startProcessLocked() returns existing proc's record if it's already running
9277 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009278 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009279 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009280 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009281 return false;
9282 }
9283
9284 r.app = proc;
9285 mBackupTarget = r;
9286 mBackupAppName = app.packageName;
9287
Christopher Tate6fa95972009-06-05 18:43:55 -07009288 // Try not to kill the process during backup
9289 updateOomAdjLocked(proc);
9290
Christopher Tate181fafa2009-05-14 11:12:14 -07009291 // If the process is already attached, schedule the creation of the backup agent now.
9292 // If it is not yet live, this will be done when it attaches to the framework.
9293 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009294 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009295 try {
9296 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9297 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009298 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009299 }
9300 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009301 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009302 }
9303 // Invariants: at this point, the target app process exists and the application
9304 // is either already running or in the process of coming up. mBackupTarget and
9305 // mBackupAppName describe the app, so that when it binds back to the AM we
9306 // know that it's scheduled for a backup-agent operation.
9307 }
9308
9309 return true;
9310 }
9311
9312 // A backup agent has just come up
9313 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009314 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009315 + " = " + agent);
9316
9317 synchronized(this) {
9318 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009319 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009320 return;
9321 }
9322
Christopher Tate043dadc2009-06-02 16:11:00 -07009323 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009324 try {
9325 IBackupManager bm = IBackupManager.Stub.asInterface(
9326 ServiceManager.getService(Context.BACKUP_SERVICE));
9327 bm.agentConnected(agentPackageName, agent);
9328 } catch (RemoteException e) {
9329 // can't happen; the backup manager service is local
9330 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009331 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009332 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009333 } finally {
9334 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009335 }
9336 }
9337 }
9338
9339 // done with this agent
9340 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009341 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009342 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009343 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009344 return;
9345 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009346
9347 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009348 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009349 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009350 return;
9351 }
9352
Christopher Tate181fafa2009-05-14 11:12:14 -07009353 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009354 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009355 return;
9356 }
9357
Christopher Tate6fa95972009-06-05 18:43:55 -07009358 ProcessRecord proc = mBackupTarget.app;
9359 mBackupTarget = null;
9360 mBackupAppName = null;
9361
9362 // Not backing this app up any more; reset its OOM adjustment
9363 updateOomAdjLocked(proc);
9364
Christopher Tatec7b31e32009-06-10 15:49:30 -07009365 // If the app crashed during backup, 'thread' will be null here
9366 if (proc.thread != null) {
9367 try {
9368 proc.thread.scheduleDestroyBackupAgent(appInfo);
9369 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009370 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009371 e.printStackTrace();
9372 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009373 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009374 }
9375 }
9376 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009377 // BROADCASTS
9378 // =========================================================
9379
Josh Bartel7f208742010-02-25 11:01:44 -06009380 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009381 List cur) {
9382 final ContentResolver resolver = mContext.getContentResolver();
9383 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9384 if (list == null) {
9385 return cur;
9386 }
9387 int N = list.size();
9388 for (int i=0; i<N; i++) {
9389 Intent intent = list.get(i);
9390 if (filter.match(resolver, intent, true, TAG) >= 0) {
9391 if (cur == null) {
9392 cur = new ArrayList<Intent>();
9393 }
9394 cur.add(intent);
9395 }
9396 }
9397 return cur;
9398 }
9399
9400 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009401 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009402 + mBroadcastsScheduled);
9403
9404 if (mBroadcastsScheduled) {
9405 return;
9406 }
9407 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9408 mBroadcastsScheduled = true;
9409 }
9410
9411 public Intent registerReceiver(IApplicationThread caller,
9412 IIntentReceiver receiver, IntentFilter filter, String permission) {
9413 synchronized(this) {
9414 ProcessRecord callerApp = null;
9415 if (caller != null) {
9416 callerApp = getRecordForAppLocked(caller);
9417 if (callerApp == null) {
9418 throw new SecurityException(
9419 "Unable to find app for caller " + caller
9420 + " (pid=" + Binder.getCallingPid()
9421 + ") when registering receiver " + receiver);
9422 }
9423 }
9424
9425 List allSticky = null;
9426
9427 // Look for any matching sticky broadcasts...
9428 Iterator actions = filter.actionsIterator();
9429 if (actions != null) {
9430 while (actions.hasNext()) {
9431 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009432 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009433 }
9434 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009435 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009436 }
9437
9438 // The first sticky in the list is returned directly back to
9439 // the client.
9440 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9441
Joe Onorato8a9b2202010-02-26 18:56:32 -08009442 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009443 + ": " + sticky);
9444
9445 if (receiver == null) {
9446 return sticky;
9447 }
9448
9449 ReceiverList rl
9450 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9451 if (rl == null) {
9452 rl = new ReceiverList(this, callerApp,
9453 Binder.getCallingPid(),
9454 Binder.getCallingUid(), receiver);
9455 if (rl.app != null) {
9456 rl.app.receivers.add(rl);
9457 } else {
9458 try {
9459 receiver.asBinder().linkToDeath(rl, 0);
9460 } catch (RemoteException e) {
9461 return sticky;
9462 }
9463 rl.linkedToDeath = true;
9464 }
9465 mRegisteredReceivers.put(receiver.asBinder(), rl);
9466 }
9467 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9468 rl.add(bf);
9469 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009470 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 }
9472 mReceiverResolver.addFilter(bf);
9473
9474 // Enqueue broadcasts for all existing stickies that match
9475 // this filter.
9476 if (allSticky != null) {
9477 ArrayList receivers = new ArrayList();
9478 receivers.add(bf);
9479
9480 int N = allSticky.size();
9481 for (int i=0; i<N; i++) {
9482 Intent intent = (Intent)allSticky.get(i);
9483 BroadcastRecord r = new BroadcastRecord(intent, null,
9484 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009485 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009486 if (mParallelBroadcasts.size() == 0) {
9487 scheduleBroadcastsLocked();
9488 }
9489 mParallelBroadcasts.add(r);
9490 }
9491 }
9492
9493 return sticky;
9494 }
9495 }
9496
9497 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009498 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009499
9500 boolean doNext = false;
9501
9502 synchronized(this) {
9503 ReceiverList rl
9504 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9505 if (rl != null) {
9506 if (rl.curBroadcast != null) {
9507 BroadcastRecord r = rl.curBroadcast;
9508 doNext = finishReceiverLocked(
9509 receiver.asBinder(), r.resultCode, r.resultData,
9510 r.resultExtras, r.resultAbort, true);
9511 }
9512
9513 if (rl.app != null) {
9514 rl.app.receivers.remove(rl);
9515 }
9516 removeReceiverLocked(rl);
9517 if (rl.linkedToDeath) {
9518 rl.linkedToDeath = false;
9519 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9520 }
9521 }
9522 }
9523
9524 if (!doNext) {
9525 return;
9526 }
9527
9528 final long origId = Binder.clearCallingIdentity();
9529 processNextBroadcast(false);
9530 trimApplications();
9531 Binder.restoreCallingIdentity(origId);
9532 }
9533
9534 void removeReceiverLocked(ReceiverList rl) {
9535 mRegisteredReceivers.remove(rl.receiver.asBinder());
9536 int N = rl.size();
9537 for (int i=0; i<N; i++) {
9538 mReceiverResolver.removeFilter(rl.get(i));
9539 }
9540 }
9541
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009542 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9543 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9544 ProcessRecord r = mLruProcesses.get(i);
9545 if (r.thread != null) {
9546 try {
9547 r.thread.dispatchPackageBroadcast(cmd, packages);
9548 } catch (RemoteException ex) {
9549 }
9550 }
9551 }
9552 }
9553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554 private final int broadcastIntentLocked(ProcessRecord callerApp,
9555 String callerPackage, Intent intent, String resolvedType,
9556 IIntentReceiver resultTo, int resultCode, String resultData,
9557 Bundle map, String requiredPermission,
9558 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9559 intent = new Intent(intent);
9560
Joe Onorato8a9b2202010-02-26 18:56:32 -08009561 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009562 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9563 + " ordered=" + ordered);
9564 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009565 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009566 }
9567
9568 // Handle special intents: if this broadcast is from the package
9569 // manager about a package being removed, we need to remove all of
9570 // its activities from the history stack.
9571 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9572 intent.getAction());
9573 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9574 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009575 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009576 || uidRemoved) {
9577 if (checkComponentPermission(
9578 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9579 callingPid, callingUid, -1)
9580 == PackageManager.PERMISSION_GRANTED) {
9581 if (uidRemoved) {
9582 final Bundle intentExtras = intent.getExtras();
9583 final int uid = intentExtras != null
9584 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9585 if (uid >= 0) {
9586 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9587 synchronized (bs) {
9588 bs.removeUidStatsLocked(uid);
9589 }
9590 }
9591 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009592 // If resources are unvailble just force stop all
9593 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009594 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009595 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9596 if (list != null && (list.length > 0)) {
9597 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009598 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009599 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009600 sendPackageBroadcastLocked(
9601 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009602 }
9603 } else {
9604 Uri data = intent.getData();
9605 String ssp;
9606 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9607 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9608 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009609 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009610 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009611 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9612 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9613 new String[] {ssp});
9614 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 }
9616 }
9617 }
9618 } else {
9619 String msg = "Permission Denial: " + intent.getAction()
9620 + " broadcast from " + callerPackage + " (pid=" + callingPid
9621 + ", uid=" + callingUid + ")"
9622 + " requires "
9623 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009624 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009625 throw new SecurityException(msg);
9626 }
9627 }
9628
9629 /*
9630 * If this is the time zone changed action, queue up a message that will reset the timezone
9631 * of all currently running processes. This message will get queued up before the broadcast
9632 * happens.
9633 */
9634 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9635 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9636 }
9637
Dianne Hackborn854060af2009-07-09 18:14:31 -07009638 /*
9639 * Prevent non-system code (defined here to be non-persistent
9640 * processes) from sending protected broadcasts.
9641 */
9642 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9643 || callingUid == Process.SHELL_UID || callingUid == 0) {
9644 // Always okay.
9645 } else if (callerApp == null || !callerApp.persistent) {
9646 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009647 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009648 intent.getAction())) {
9649 String msg = "Permission Denial: not allowed to send broadcast "
9650 + intent.getAction() + " from pid="
9651 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009652 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009653 throw new SecurityException(msg);
9654 }
9655 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009656 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009657 return BROADCAST_SUCCESS;
9658 }
9659 }
9660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009661 // Add to the sticky list if requested.
9662 if (sticky) {
9663 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9664 callingPid, callingUid)
9665 != PackageManager.PERMISSION_GRANTED) {
9666 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9667 + callingPid + ", uid=" + callingUid
9668 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009669 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009670 throw new SecurityException(msg);
9671 }
9672 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009673 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009674 + " and enforce permission " + requiredPermission);
9675 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9676 }
9677 if (intent.getComponent() != null) {
9678 throw new SecurityException(
9679 "Sticky broadcasts can't target a specific component");
9680 }
9681 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9682 if (list == null) {
9683 list = new ArrayList<Intent>();
9684 mStickyBroadcasts.put(intent.getAction(), list);
9685 }
9686 int N = list.size();
9687 int i;
9688 for (i=0; i<N; i++) {
9689 if (intent.filterEquals(list.get(i))) {
9690 // This sticky already exists, replace it.
9691 list.set(i, new Intent(intent));
9692 break;
9693 }
9694 }
9695 if (i >= N) {
9696 list.add(new Intent(intent));
9697 }
9698 }
9699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 // Figure out who all will receive this broadcast.
9701 List receivers = null;
9702 List<BroadcastFilter> registeredReceivers = null;
9703 try {
9704 if (intent.getComponent() != null) {
9705 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009706 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009707 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009708 if (ai != null) {
9709 receivers = new ArrayList();
9710 ResolveInfo ri = new ResolveInfo();
9711 ri.activityInfo = ai;
9712 receivers.add(ri);
9713 }
9714 } else {
9715 // Need to resolve the intent to interested receivers...
9716 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9717 == 0) {
9718 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009719 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009720 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009721 }
Mihai Preda074edef2009-05-18 17:13:31 +02009722 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009723 }
9724 } catch (RemoteException ex) {
9725 // pm is in same process, this will never happen.
9726 }
9727
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009728 final boolean replacePending =
9729 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9730
Joe Onorato8a9b2202010-02-26 18:56:32 -08009731 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009732 + " replacePending=" + replacePending);
9733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009734 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9735 if (!ordered && NR > 0) {
9736 // If we are not serializing this broadcast, then send the
9737 // registered receivers separately so they don't wait for the
9738 // components to be launched.
9739 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9740 callerPackage, callingPid, callingUid, requiredPermission,
9741 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009742 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009743 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009744 TAG, "Enqueueing parallel broadcast " + r
9745 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009746 boolean replaced = false;
9747 if (replacePending) {
9748 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9749 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009750 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009751 "***** DROPPING PARALLEL: " + intent);
9752 mParallelBroadcasts.set(i, r);
9753 replaced = true;
9754 break;
9755 }
9756 }
9757 }
9758 if (!replaced) {
9759 mParallelBroadcasts.add(r);
9760 scheduleBroadcastsLocked();
9761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 registeredReceivers = null;
9763 NR = 0;
9764 }
9765
9766 // Merge into one list.
9767 int ir = 0;
9768 if (receivers != null) {
9769 // A special case for PACKAGE_ADDED: do not allow the package
9770 // being added to see this broadcast. This prevents them from
9771 // using this as a back door to get run as soon as they are
9772 // installed. Maybe in the future we want to have a special install
9773 // broadcast or such for apps, but we'd like to deliberately make
9774 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009775 String skipPackages[] = null;
9776 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9777 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9778 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9779 Uri data = intent.getData();
9780 if (data != null) {
9781 String pkgName = data.getSchemeSpecificPart();
9782 if (pkgName != null) {
9783 skipPackages = new String[] { pkgName };
9784 }
9785 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009786 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009787 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009788 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009789 if (skipPackages != null && (skipPackages.length > 0)) {
9790 for (String skipPackage : skipPackages) {
9791 if (skipPackage != null) {
9792 int NT = receivers.size();
9793 for (int it=0; it<NT; it++) {
9794 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9795 if (curt.activityInfo.packageName.equals(skipPackage)) {
9796 receivers.remove(it);
9797 it--;
9798 NT--;
9799 }
9800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009801 }
9802 }
9803 }
9804
9805 int NT = receivers != null ? receivers.size() : 0;
9806 int it = 0;
9807 ResolveInfo curt = null;
9808 BroadcastFilter curr = null;
9809 while (it < NT && ir < NR) {
9810 if (curt == null) {
9811 curt = (ResolveInfo)receivers.get(it);
9812 }
9813 if (curr == null) {
9814 curr = registeredReceivers.get(ir);
9815 }
9816 if (curr.getPriority() >= curt.priority) {
9817 // Insert this broadcast record into the final list.
9818 receivers.add(it, curr);
9819 ir++;
9820 curr = null;
9821 it++;
9822 NT++;
9823 } else {
9824 // Skip to the next ResolveInfo in the final list.
9825 it++;
9826 curt = null;
9827 }
9828 }
9829 }
9830 while (ir < NR) {
9831 if (receivers == null) {
9832 receivers = new ArrayList();
9833 }
9834 receivers.add(registeredReceivers.get(ir));
9835 ir++;
9836 }
9837
9838 if ((receivers != null && receivers.size() > 0)
9839 || resultTo != null) {
9840 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9841 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009842 receivers, resultTo, resultCode, resultData, map, ordered,
9843 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009844 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009845 TAG, "Enqueueing ordered broadcast " + r
9846 + ": prev had " + mOrderedBroadcasts.size());
9847 if (DEBUG_BROADCAST) {
9848 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009849 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009850 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009851 boolean replaced = false;
9852 if (replacePending) {
9853 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9854 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009855 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009856 "***** DROPPING ORDERED: " + intent);
9857 mOrderedBroadcasts.set(i, r);
9858 replaced = true;
9859 break;
9860 }
9861 }
9862 }
9863 if (!replaced) {
9864 mOrderedBroadcasts.add(r);
9865 scheduleBroadcastsLocked();
9866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009867 }
9868
9869 return BROADCAST_SUCCESS;
9870 }
9871
9872 public final int broadcastIntent(IApplicationThread caller,
9873 Intent intent, String resolvedType, IIntentReceiver resultTo,
9874 int resultCode, String resultData, Bundle map,
9875 String requiredPermission, boolean serialized, boolean sticky) {
9876 // Refuse possible leaked file descriptors
9877 if (intent != null && intent.hasFileDescriptors() == true) {
9878 throw new IllegalArgumentException("File descriptors passed in Intent");
9879 }
9880
9881 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009882 int flags = intent.getFlags();
9883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 if (!mSystemReady) {
9885 // if the caller really truly claims to know what they're doing, go
9886 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009887 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
9888 intent = new Intent(intent);
9889 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
9890 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -08009891 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 + " before boot completion");
9893 throw new IllegalStateException("Cannot broadcast before boot completed");
9894 }
9895 }
9896
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009897 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
9898 throw new IllegalArgumentException(
9899 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
9900 }
9901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009902 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9903 final int callingPid = Binder.getCallingPid();
9904 final int callingUid = Binder.getCallingUid();
9905 final long origId = Binder.clearCallingIdentity();
9906 int res = broadcastIntentLocked(callerApp,
9907 callerApp != null ? callerApp.info.packageName : null,
9908 intent, resolvedType, resultTo,
9909 resultCode, resultData, map, requiredPermission, serialized,
9910 sticky, callingPid, callingUid);
9911 Binder.restoreCallingIdentity(origId);
9912 return res;
9913 }
9914 }
9915
9916 int broadcastIntentInPackage(String packageName, int uid,
9917 Intent intent, String resolvedType, IIntentReceiver resultTo,
9918 int resultCode, String resultData, Bundle map,
9919 String requiredPermission, boolean serialized, boolean sticky) {
9920 synchronized(this) {
9921 final long origId = Binder.clearCallingIdentity();
9922 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
9923 resultTo, resultCode, resultData, map, requiredPermission,
9924 serialized, sticky, -1, uid);
9925 Binder.restoreCallingIdentity(origId);
9926 return res;
9927 }
9928 }
9929
9930 public final void unbroadcastIntent(IApplicationThread caller,
9931 Intent intent) {
9932 // Refuse possible leaked file descriptors
9933 if (intent != null && intent.hasFileDescriptors() == true) {
9934 throw new IllegalArgumentException("File descriptors passed in Intent");
9935 }
9936
9937 synchronized(this) {
9938 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
9939 != PackageManager.PERMISSION_GRANTED) {
9940 String msg = "Permission Denial: unbroadcastIntent() from pid="
9941 + Binder.getCallingPid()
9942 + ", uid=" + Binder.getCallingUid()
9943 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009944 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009945 throw new SecurityException(msg);
9946 }
9947 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9948 if (list != null) {
9949 int N = list.size();
9950 int i;
9951 for (i=0; i<N; i++) {
9952 if (intent.filterEquals(list.get(i))) {
9953 list.remove(i);
9954 break;
9955 }
9956 }
9957 }
9958 }
9959 }
9960
9961 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
9962 String resultData, Bundle resultExtras, boolean resultAbort,
9963 boolean explicit) {
9964 if (mOrderedBroadcasts.size() == 0) {
9965 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009966 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009967 }
9968 return false;
9969 }
9970 BroadcastRecord r = mOrderedBroadcasts.get(0);
9971 if (r.receiver == null) {
9972 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009973 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009974 }
9975 return false;
9976 }
9977 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009978 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009979 return false;
9980 }
9981 int state = r.state;
9982 r.state = r.IDLE;
9983 if (state == r.IDLE) {
9984 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009985 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009986 }
9987 }
9988 r.receiver = null;
9989 r.intent.setComponent(null);
9990 if (r.curApp != null) {
9991 r.curApp.curReceiver = null;
9992 }
9993 if (r.curFilter != null) {
9994 r.curFilter.receiverList.curBroadcast = null;
9995 }
9996 r.curFilter = null;
9997 r.curApp = null;
9998 r.curComponent = null;
9999 r.curReceiver = null;
10000 mPendingBroadcast = null;
10001
10002 r.resultCode = resultCode;
10003 r.resultData = resultData;
10004 r.resultExtras = resultExtras;
10005 r.resultAbort = resultAbort;
10006
10007 // We will process the next receiver right now if this is finishing
10008 // an app receiver (which is always asynchronous) or after we have
10009 // come back from calling a receiver.
10010 return state == BroadcastRecord.APP_RECEIVE
10011 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10012 }
10013
10014 public void finishReceiver(IBinder who, int resultCode, String resultData,
10015 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010016 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017
10018 // Refuse possible leaked file descriptors
10019 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10020 throw new IllegalArgumentException("File descriptors passed in Bundle");
10021 }
10022
10023 boolean doNext;
10024
10025 final long origId = Binder.clearCallingIdentity();
10026
10027 synchronized(this) {
10028 doNext = finishReceiverLocked(
10029 who, resultCode, resultData, resultExtras, resultAbort, true);
10030 }
10031
10032 if (doNext) {
10033 processNextBroadcast(false);
10034 }
10035 trimApplications();
10036
10037 Binder.restoreCallingIdentity(origId);
10038 }
10039
10040 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10041 if (r.nextReceiver > 0) {
10042 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10043 if (curReceiver instanceof BroadcastFilter) {
10044 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010045 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010046 System.identityHashCode(r),
10047 r.intent.getAction(),
10048 r.nextReceiver - 1,
10049 System.identityHashCode(bf));
10050 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010051 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010052 System.identityHashCode(r),
10053 r.intent.getAction(),
10054 r.nextReceiver - 1,
10055 ((ResolveInfo)curReceiver).toString());
10056 }
10057 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010058 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010059 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010060 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010061 System.identityHashCode(r),
10062 r.intent.getAction(),
10063 r.nextReceiver,
10064 "NONE");
10065 }
10066 }
10067
10068 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010069 ProcessRecord app = null;
10070 String anrMessage = null;
10071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010072 synchronized (this) {
10073 if (mOrderedBroadcasts.size() == 0) {
10074 return;
10075 }
10076 long now = SystemClock.uptimeMillis();
10077 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010078 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010079 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010080 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010081 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010082 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010083 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010084 return;
10085 }
10086
Joe Onorato8a9b2202010-02-26 18:56:32 -080010087 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010088 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010089 r.anrCount++;
10090
10091 // Current receiver has passed its expiration date.
10092 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010093 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010094 return;
10095 }
10096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010097 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010098 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099 logBroadcastReceiverDiscard(r);
10100 if (curReceiver instanceof BroadcastFilter) {
10101 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10102 if (bf.receiverList.pid != 0
10103 && bf.receiverList.pid != MY_PID) {
10104 synchronized (this.mPidsSelfLocked) {
10105 app = this.mPidsSelfLocked.get(
10106 bf.receiverList.pid);
10107 }
10108 }
10109 } else {
10110 app = r.curApp;
10111 }
10112
10113 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010114 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010115 }
10116
10117 if (mPendingBroadcast == r) {
10118 mPendingBroadcast = null;
10119 }
10120
10121 // Move on to the next receiver.
10122 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10123 r.resultExtras, r.resultAbort, true);
10124 scheduleBroadcastsLocked();
10125 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010126
10127 if (anrMessage != null) {
10128 appNotResponding(app, null, null, anrMessage);
10129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130 }
10131
10132 private final void processCurBroadcastLocked(BroadcastRecord r,
10133 ProcessRecord app) throws RemoteException {
10134 if (app.thread == null) {
10135 throw new RemoteException();
10136 }
10137 r.receiver = app.thread.asBinder();
10138 r.curApp = app;
10139 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010140 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010141
10142 // Tell the application to launch this receiver.
10143 r.intent.setComponent(r.curComponent);
10144
10145 boolean started = false;
10146 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010147 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 "Delivering to component " + r.curComponent
10149 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010150 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010151 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10152 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10153 started = true;
10154 } finally {
10155 if (!started) {
10156 r.receiver = null;
10157 r.curApp = null;
10158 app.curReceiver = null;
10159 }
10160 }
10161
10162 }
10163
10164 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010165 Intent intent, int resultCode, String data, Bundle extras,
10166 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010167 if (app != null && app.thread != null) {
10168 // If we have an app thread, do the call through that so it is
10169 // correctly ordered with other one-way calls.
10170 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010171 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010172 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010173 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010174 }
10175 }
10176
10177 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10178 BroadcastFilter filter, boolean ordered) {
10179 boolean skip = false;
10180 if (filter.requiredPermission != null) {
10181 int perm = checkComponentPermission(filter.requiredPermission,
10182 r.callingPid, r.callingUid, -1);
10183 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010184 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010185 + r.intent.toString()
10186 + " from " + r.callerPackage + " (pid="
10187 + r.callingPid + ", uid=" + r.callingUid + ")"
10188 + " requires " + filter.requiredPermission
10189 + " due to registered receiver " + filter);
10190 skip = true;
10191 }
10192 }
10193 if (r.requiredPermission != null) {
10194 int perm = checkComponentPermission(r.requiredPermission,
10195 filter.receiverList.pid, filter.receiverList.uid, -1);
10196 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010197 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010198 + r.intent.toString()
10199 + " to " + filter.receiverList.app
10200 + " (pid=" + filter.receiverList.pid
10201 + ", uid=" + filter.receiverList.uid + ")"
10202 + " requires " + r.requiredPermission
10203 + " due to sender " + r.callerPackage
10204 + " (uid " + r.callingUid + ")");
10205 skip = true;
10206 }
10207 }
10208
10209 if (!skip) {
10210 // If this is not being sent as an ordered broadcast, then we
10211 // don't want to touch the fields that keep track of the current
10212 // state of ordered broadcasts.
10213 if (ordered) {
10214 r.receiver = filter.receiverList.receiver.asBinder();
10215 r.curFilter = filter;
10216 filter.receiverList.curBroadcast = r;
10217 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010218 if (filter.receiverList.app != null) {
10219 // Bump hosting application to no longer be in background
10220 // scheduling class. Note that we can't do that if there
10221 // isn't an app... but we can only be in that case for
10222 // things that directly call the IActivityManager API, which
10223 // are already core system stuff so don't matter for this.
10224 r.curApp = filter.receiverList.app;
10225 filter.receiverList.app.curReceiver = r;
10226 updateOomAdjLocked();
10227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010228 }
10229 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010230 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010232 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010233 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 }
10235 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10236 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010237 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 if (ordered) {
10239 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10240 }
10241 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010242 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010243 if (ordered) {
10244 r.receiver = null;
10245 r.curFilter = null;
10246 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010247 if (filter.receiverList.app != null) {
10248 filter.receiverList.app.curReceiver = null;
10249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010250 }
10251 }
10252 }
10253 }
10254
Dianne Hackborn12527f92009-11-11 17:39:50 -080010255 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10256 if (r.callingUid < 0) {
10257 // This was from a registerReceiver() call; ignore it.
10258 return;
10259 }
10260 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10261 MAX_BROADCAST_HISTORY-1);
10262 r.finishTime = SystemClock.uptimeMillis();
10263 mBroadcastHistory[0] = r;
10264 }
10265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 private final void processNextBroadcast(boolean fromMsg) {
10267 synchronized(this) {
10268 BroadcastRecord r;
10269
Joe Onorato8a9b2202010-02-26 18:56:32 -080010270 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010271 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010272 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010273
10274 updateCpuStats();
10275
10276 if (fromMsg) {
10277 mBroadcastsScheduled = false;
10278 }
10279
10280 // First, deliver any non-serialized broadcasts right away.
10281 while (mParallelBroadcasts.size() > 0) {
10282 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010283 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010285 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010286 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010287 for (int i=0; i<N; i++) {
10288 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010289 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010290 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291 + target + ": " + r);
10292 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10293 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010294 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010295 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010296 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010297 }
10298
10299 // Now take care of the next serialized one...
10300
10301 // If we are waiting for a process to come up to handle the next
10302 // broadcast, then do nothing at this point. Just in case, we
10303 // check that the process we're waiting for still exists.
10304 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010305 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010306 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010307 + mPendingBroadcast.curApp);
10308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010309
10310 boolean isDead;
10311 synchronized (mPidsSelfLocked) {
10312 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10313 }
10314 if (!isDead) {
10315 // It's still alive, so keep waiting
10316 return;
10317 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010318 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 + " died before responding to broadcast");
10320 mPendingBroadcast = null;
10321 }
10322 }
10323
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010324 boolean looped = false;
10325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010326 do {
10327 if (mOrderedBroadcasts.size() == 0) {
10328 // No more broadcasts pending, so all done!
10329 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010330 if (looped) {
10331 // If we had finished the last ordered broadcast, then
10332 // make sure all processes have correct oom and sched
10333 // adjustments.
10334 updateOomAdjLocked();
10335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010336 return;
10337 }
10338 r = mOrderedBroadcasts.get(0);
10339 boolean forceReceive = false;
10340
10341 // Ensure that even if something goes awry with the timeout
10342 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010343 // and continue to make progress.
10344 //
10345 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10346 // receivers don't get executed with with timeouts. They're intended for
10347 // one time heavy lifting after system upgrades and can take
10348 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010349 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010350 if (mSystemReady && r.dispatchTime > 0) {
10351 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010352 if ((numReceivers > 0) &&
10353 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010354 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010355 + " now=" + now
10356 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010357 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 + " intent=" + r.intent
10359 + " numReceivers=" + numReceivers
10360 + " nextReceiver=" + r.nextReceiver
10361 + " state=" + r.state);
10362 broadcastTimeout(); // forcibly finish this broadcast
10363 forceReceive = true;
10364 r.state = BroadcastRecord.IDLE;
10365 }
10366 }
10367
10368 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010369 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 "processNextBroadcast() called when not idle (state="
10371 + r.state + ")");
10372 return;
10373 }
10374
10375 if (r.receivers == null || r.nextReceiver >= numReceivers
10376 || r.resultAbort || forceReceive) {
10377 // No more receivers for this broadcast! Send the final
10378 // result if requested...
10379 if (r.resultTo != null) {
10380 try {
10381 if (DEBUG_BROADCAST) {
10382 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010383 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010384 + " seq=" + seq + " app=" + r.callerApp);
10385 }
10386 performReceive(r.callerApp, r.resultTo,
10387 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010388 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010389 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010390 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010391 }
10392 }
10393
Joe Onorato8a9b2202010-02-26 18:56:32 -080010394 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010395 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10396
Joe Onorato8a9b2202010-02-26 18:56:32 -080010397 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010398 + r);
10399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010401 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 mOrderedBroadcasts.remove(0);
10403 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010404 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 continue;
10406 }
10407 } while (r == null);
10408
10409 // Get the next receiver...
10410 int recIdx = r.nextReceiver++;
10411
10412 // Keep track of when this receiver started, and make sure there
10413 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010414 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010415 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010416 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010417
Joe Onorato8a9b2202010-02-26 18:56:32 -080010418 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010419 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010420 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010421 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010422 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010424 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 }
10426
10427 Object nextReceiver = r.receivers.get(recIdx);
10428 if (nextReceiver instanceof BroadcastFilter) {
10429 // Simple case: this is a registered receiver who gets
10430 // a direct call.
10431 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010432 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010433 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010434 + filter + ": " + r);
10435 deliverToRegisteredReceiver(r, filter, r.ordered);
10436 if (r.receiver == null || !r.ordered) {
10437 // The receiver has already finished, so schedule to
10438 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010439 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10440 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010441 r.state = BroadcastRecord.IDLE;
10442 scheduleBroadcastsLocked();
10443 }
10444 return;
10445 }
10446
10447 // Hard case: need to instantiate the receiver, possibly
10448 // starting its application process to host it.
10449
10450 ResolveInfo info =
10451 (ResolveInfo)nextReceiver;
10452
10453 boolean skip = false;
10454 int perm = checkComponentPermission(info.activityInfo.permission,
10455 r.callingPid, r.callingUid,
10456 info.activityInfo.exported
10457 ? -1 : info.activityInfo.applicationInfo.uid);
10458 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010459 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 + r.intent.toString()
10461 + " from " + r.callerPackage + " (pid=" + r.callingPid
10462 + ", uid=" + r.callingUid + ")"
10463 + " requires " + info.activityInfo.permission
10464 + " due to receiver " + info.activityInfo.packageName
10465 + "/" + info.activityInfo.name);
10466 skip = true;
10467 }
10468 if (r.callingUid != Process.SYSTEM_UID &&
10469 r.requiredPermission != null) {
10470 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010471 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010472 checkPermission(r.requiredPermission,
10473 info.activityInfo.applicationInfo.packageName);
10474 } catch (RemoteException e) {
10475 perm = PackageManager.PERMISSION_DENIED;
10476 }
10477 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010478 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 + r.intent + " to "
10480 + info.activityInfo.applicationInfo.packageName
10481 + " requires " + r.requiredPermission
10482 + " due to sender " + r.callerPackage
10483 + " (uid " + r.callingUid + ")");
10484 skip = true;
10485 }
10486 }
10487 if (r.curApp != null && r.curApp.crashing) {
10488 // If the target process is crashing, just skip it.
10489 skip = true;
10490 }
10491
10492 if (skip) {
10493 r.receiver = null;
10494 r.curFilter = null;
10495 r.state = BroadcastRecord.IDLE;
10496 scheduleBroadcastsLocked();
10497 return;
10498 }
10499
10500 r.state = BroadcastRecord.APP_RECEIVE;
10501 String targetProcess = info.activityInfo.processName;
10502 r.curComponent = new ComponentName(
10503 info.activityInfo.applicationInfo.packageName,
10504 info.activityInfo.name);
10505 r.curReceiver = info.activityInfo;
10506
10507 // Is this receiver's application already running?
10508 ProcessRecord app = getProcessRecordLocked(targetProcess,
10509 info.activityInfo.applicationInfo.uid);
10510 if (app != null && app.thread != null) {
10511 try {
10512 processCurBroadcastLocked(r, app);
10513 return;
10514 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010515 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010516 + r.curComponent, e);
10517 }
10518
10519 // If a dead object exception was thrown -- fall through to
10520 // restart the application.
10521 }
10522
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010523 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524 if ((r.curApp=startProcessLocked(targetProcess,
10525 info.activityInfo.applicationInfo, true,
10526 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010527 "broadcast", r.curComponent,
10528 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10529 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010530 // Ah, this recipient is unavailable. Finish it if necessary,
10531 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010532 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010533 + info.activityInfo.applicationInfo.packageName + "/"
10534 + info.activityInfo.applicationInfo.uid + " for broadcast "
10535 + r.intent + ": process is bad");
10536 logBroadcastReceiverDiscard(r);
10537 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10538 r.resultExtras, r.resultAbort, true);
10539 scheduleBroadcastsLocked();
10540 r.state = BroadcastRecord.IDLE;
10541 return;
10542 }
10543
10544 mPendingBroadcast = r;
10545 }
10546 }
10547
10548 // =========================================================
10549 // INSTRUMENTATION
10550 // =========================================================
10551
10552 public boolean startInstrumentation(ComponentName className,
10553 String profileFile, int flags, Bundle arguments,
10554 IInstrumentationWatcher watcher) {
10555 // Refuse possible leaked file descriptors
10556 if (arguments != null && arguments.hasFileDescriptors()) {
10557 throw new IllegalArgumentException("File descriptors passed in Bundle");
10558 }
10559
10560 synchronized(this) {
10561 InstrumentationInfo ii = null;
10562 ApplicationInfo ai = null;
10563 try {
10564 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010565 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010566 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010567 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 } catch (PackageManager.NameNotFoundException e) {
10569 }
10570 if (ii == null) {
10571 reportStartInstrumentationFailure(watcher, className,
10572 "Unable to find instrumentation info for: " + className);
10573 return false;
10574 }
10575 if (ai == null) {
10576 reportStartInstrumentationFailure(watcher, className,
10577 "Unable to find instrumentation target package: " + ii.targetPackage);
10578 return false;
10579 }
10580
10581 int match = mContext.getPackageManager().checkSignatures(
10582 ii.targetPackage, ii.packageName);
10583 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10584 String msg = "Permission Denial: starting instrumentation "
10585 + className + " from pid="
10586 + Binder.getCallingPid()
10587 + ", uid=" + Binder.getCallingPid()
10588 + " not allowed because package " + ii.packageName
10589 + " does not have a signature matching the target "
10590 + ii.targetPackage;
10591 reportStartInstrumentationFailure(watcher, className, msg);
10592 throw new SecurityException(msg);
10593 }
10594
10595 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010596 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010597 ProcessRecord app = addAppLocked(ai);
10598 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010599 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010600 app.instrumentationProfileFile = profileFile;
10601 app.instrumentationArguments = arguments;
10602 app.instrumentationWatcher = watcher;
10603 app.instrumentationResultClass = className;
10604 Binder.restoreCallingIdentity(origId);
10605 }
10606
10607 return true;
10608 }
10609
10610 /**
10611 * Report errors that occur while attempting to start Instrumentation. Always writes the
10612 * error to the logs, but if somebody is watching, send the report there too. This enables
10613 * the "am" command to report errors with more information.
10614 *
10615 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10616 * @param cn The component name of the instrumentation.
10617 * @param report The error report.
10618 */
10619 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10620 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010621 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010622 try {
10623 if (watcher != null) {
10624 Bundle results = new Bundle();
10625 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10626 results.putString("Error", report);
10627 watcher.instrumentationStatus(cn, -1, results);
10628 }
10629 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010630 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010631 }
10632 }
10633
10634 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10635 if (app.instrumentationWatcher != null) {
10636 try {
10637 // NOTE: IInstrumentationWatcher *must* be oneway here
10638 app.instrumentationWatcher.instrumentationFinished(
10639 app.instrumentationClass,
10640 resultCode,
10641 results);
10642 } catch (RemoteException e) {
10643 }
10644 }
10645 app.instrumentationWatcher = null;
10646 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010647 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648 app.instrumentationProfileFile = null;
10649 app.instrumentationArguments = null;
10650
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010651 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 }
10653
10654 public void finishInstrumentation(IApplicationThread target,
10655 int resultCode, Bundle results) {
10656 // Refuse possible leaked file descriptors
10657 if (results != null && results.hasFileDescriptors()) {
10658 throw new IllegalArgumentException("File descriptors passed in Intent");
10659 }
10660
10661 synchronized(this) {
10662 ProcessRecord app = getRecordForAppLocked(target);
10663 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010664 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010665 return;
10666 }
10667 final long origId = Binder.clearCallingIdentity();
10668 finishInstrumentationLocked(app, resultCode, results);
10669 Binder.restoreCallingIdentity(origId);
10670 }
10671 }
10672
10673 // =========================================================
10674 // CONFIGURATION
10675 // =========================================================
10676
10677 public ConfigurationInfo getDeviceConfigurationInfo() {
10678 ConfigurationInfo config = new ConfigurationInfo();
10679 synchronized (this) {
10680 config.reqTouchScreen = mConfiguration.touchscreen;
10681 config.reqKeyboardType = mConfiguration.keyboard;
10682 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010683 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10684 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010685 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10686 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010687 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10688 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010689 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10690 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010691 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010692 }
10693 return config;
10694 }
10695
10696 public Configuration getConfiguration() {
10697 Configuration ci;
10698 synchronized(this) {
10699 ci = new Configuration(mConfiguration);
10700 }
10701 return ci;
10702 }
10703
10704 public void updateConfiguration(Configuration values) {
10705 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10706 "updateConfiguration()");
10707
10708 synchronized(this) {
10709 if (values == null && mWindowManager != null) {
10710 // sentinel: fetch the current configuration from the window manager
10711 values = mWindowManager.computeNewConfiguration();
10712 }
10713
10714 final long origId = Binder.clearCallingIdentity();
10715 updateConfigurationLocked(values, null);
10716 Binder.restoreCallingIdentity(origId);
10717 }
10718 }
10719
10720 /**
10721 * Do either or both things: (1) change the current configuration, and (2)
10722 * make sure the given activity is running with the (now) current
10723 * configuration. Returns true if the activity has been left running, or
10724 * false if <var>starting</var> is being destroyed to match the new
10725 * configuration.
10726 */
10727 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010728 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010729 int changes = 0;
10730
10731 boolean kept = true;
10732
10733 if (values != null) {
10734 Configuration newConfig = new Configuration(mConfiguration);
10735 changes = newConfig.updateFrom(values);
10736 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010737 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010738 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010739 }
10740
Doug Zongker2bec3d42009-12-04 12:52:44 -080010741 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010742
10743 if (values.locale != null) {
10744 saveLocaleLocked(values.locale,
10745 !values.locale.equals(mConfiguration.locale),
10746 values.userSetLocale);
10747 }
10748
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010749 mConfigurationSeq++;
10750 if (mConfigurationSeq <= 0) {
10751 mConfigurationSeq = 1;
10752 }
10753 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010755 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010756
10757 AttributeCache ac = AttributeCache.instance();
10758 if (ac != null) {
10759 ac.updateConfiguration(mConfiguration);
10760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010762 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10763 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10764 msg.obj = new Configuration(mConfiguration);
10765 mHandler.sendMessage(msg);
10766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010767
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010768 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10769 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010770 try {
10771 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010772 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010773 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010774 app.thread.scheduleConfigurationChanged(mConfiguration);
10775 }
10776 } catch (Exception e) {
10777 }
10778 }
10779 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010780 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10781 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10783 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010784 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10785 broadcastIntentLocked(null, null,
10786 new Intent(Intent.ACTION_LOCALE_CHANGED),
10787 null, null, 0, null, null,
10788 null, false, false, MY_PID, Process.SYSTEM_UID);
10789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010790 }
10791 }
10792
10793 if (changes != 0 && starting == null) {
10794 // If the configuration changed, and the caller is not already
10795 // in the process of starting an activity, then find the top
10796 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010797 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010798 }
10799
10800 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010801 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010802 if (kept) {
10803 // If this didn't result in the starting activity being
10804 // destroyed, then we need to make sure at this point that all
10805 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010806 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010807 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010808 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010809 }
10810 }
10811
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010812 if (values != null && mWindowManager != null) {
10813 mWindowManager.setNewConfiguration(mConfiguration);
10814 }
10815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010816 return kept;
10817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010818
10819 /**
10820 * Save the locale. You must be inside a synchronized (this) block.
10821 */
10822 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10823 if(isDiff) {
10824 SystemProperties.set("user.language", l.getLanguage());
10825 SystemProperties.set("user.region", l.getCountry());
10826 }
10827
10828 if(isPersist) {
10829 SystemProperties.set("persist.sys.language", l.getLanguage());
10830 SystemProperties.set("persist.sys.country", l.getCountry());
10831 SystemProperties.set("persist.sys.localevar", l.getVariant());
10832 }
10833 }
10834
10835 // =========================================================
10836 // LIFETIME MANAGEMENT
10837 // =========================================================
10838
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010839 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
10840 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010841 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010842 // This adjustment has already been computed. If we are calling
10843 // from the top, we may have already computed our adjustment with
10844 // an earlier hidden adjustment that isn't really for us... if
10845 // so, use the new hidden adjustment.
10846 if (!recursed && app.hidden) {
10847 app.curAdj = hiddenAdj;
10848 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010849 return app.curAdj;
10850 }
10851
10852 if (app.thread == null) {
10853 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010854 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010855 return (app.curAdj=EMPTY_APP_ADJ);
10856 }
10857
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010858 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
10859 // The max adjustment doesn't allow this app to be anything
10860 // below foreground, so it is not worth doing work for it.
10861 app.adjType = "fixed";
10862 app.adjSeq = mAdjSeq;
10863 app.curRawAdj = app.maxAdj;
10864 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
10865 return (app.curAdj=app.maxAdj);
10866 }
10867
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010868 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010869 app.adjSource = null;
10870 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010871 app.empty = false;
10872 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010873
The Android Open Source Project4df24232009-03-05 14:34:35 -080010874 // Determine the importance of the process, starting with most
10875 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010876 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010877 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010878 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010879 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010880 // The last app on the list is the foreground app.
10881 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010882 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010883 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010884 } else if (app.instrumentationClass != null) {
10885 // Don't want to kill running instrumentation.
10886 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010887 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010888 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010889 } else if (app.persistentActivities > 0) {
10890 // Special persistent activities... shouldn't be used these days.
10891 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010892 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010893 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 } else if (app.curReceiver != null ||
10895 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
10896 // An app that is currently receiving a broadcast also
10897 // counts as being in the foreground.
10898 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010899 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010900 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010901 } else if (app.executingServices.size() > 0) {
10902 // An app that is currently executing a service callback also
10903 // counts as being in the foreground.
10904 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010905 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010906 app.adjType = "exec-service";
10907 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010909 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010910 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010911 app.adjType = "foreground-service";
10912 } else if (app.forcingToForeground != null) {
10913 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010914 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010915 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010916 app.adjType = "force-foreground";
10917 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010918 } else if (app == mHeavyWeightProcess) {
10919 // We don't want to kill the current heavy-weight process.
10920 adj = HEAVY_WEIGHT_APP_ADJ;
10921 schedGroup = Process.THREAD_GROUP_DEFAULT;
10922 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080010923 } else if (app == mHomeProcess) {
10924 // This process is hosting what we currently consider to be the
10925 // home app, so we don't want to let it go into the background.
10926 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010927 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010928 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 } else if ((N=app.activities.size()) != 0) {
10930 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010931 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010932 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010933 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010934 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010935 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010936 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010937 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010939 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010940 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010941 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010942 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010943 break;
10944 }
10945 }
10946 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010947 // A very not-needed process. If this is lower in the lru list,
10948 // we will push it in to the empty bucket.
10949 app.hidden = true;
10950 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010951 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010952 adj = hiddenAdj;
10953 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 }
10955
Joe Onorato8a9b2202010-02-26 18:56:32 -080010956 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010957
The Android Open Source Project4df24232009-03-05 14:34:35 -080010958 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959 // there are applications dependent on our services or providers, but
10960 // this gives us a baseline and makes sure we don't get into an
10961 // infinite recursion.
10962 app.adjSeq = mAdjSeq;
10963 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010964
Christopher Tate6fa95972009-06-05 18:43:55 -070010965 if (mBackupTarget != null && app == mBackupTarget.app) {
10966 // If possible we want to avoid killing apps while they're being backed up
10967 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010968 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070010969 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010970 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010971 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070010972 }
10973 }
10974
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010975 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
10976 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010977 final long now = SystemClock.uptimeMillis();
10978 // This process is more important if the top activity is
10979 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010980 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010981 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010982 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010983 if (s.startRequested) {
10984 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
10985 // This service has seen some activity within
10986 // recent memory, so we will keep its process ahead
10987 // of the background processes.
10988 if (adj > SECONDARY_SERVER_ADJ) {
10989 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010990 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010991 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992 }
10993 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080010994 // If we have let the service slide into the background
10995 // state, still have some text describing what it is doing
10996 // even though the service no longer has an impact.
10997 if (adj > SECONDARY_SERVER_ADJ) {
10998 app.adjType = "started-bg-services";
10999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011000 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011001 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11002 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011003 Iterator<ConnectionRecord> kt
11004 = s.connections.values().iterator();
11005 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11006 // XXX should compute this based on the max of
11007 // all connected clients.
11008 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011009 if (cr.binding.client == app) {
11010 // Binding to ourself is not interesting.
11011 continue;
11012 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11014 ProcessRecord client = cr.binding.client;
11015 int myHiddenAdj = hiddenAdj;
11016 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011017 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 myHiddenAdj = client.hiddenAdj;
11019 } else {
11020 myHiddenAdj = VISIBLE_APP_ADJ;
11021 }
11022 }
11023 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011024 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011025 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011026 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011028 if (!client.hidden) {
11029 app.hidden = false;
11030 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011031 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011032 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11033 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011034 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011035 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011037 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11038 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11039 schedGroup = Process.THREAD_GROUP_DEFAULT;
11040 }
11041 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011043 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011045 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 //}
11047 if (a != null && adj > FOREGROUND_APP_ADJ &&
11048 (a.state == ActivityState.RESUMED
11049 || a.state == ActivityState.PAUSING)) {
11050 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011051 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011052 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011053 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011054 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11055 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011056 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011057 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058 }
11059 }
11060 }
11061 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011062
11063 // Finally, f this process has active services running in it, we
11064 // would like to avoid killing it unless it would prevent the current
11065 // application from running. By default we put the process in
11066 // with the rest of the background processes; as we scan through
11067 // its services we may bump it up from there.
11068 if (adj > hiddenAdj) {
11069 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011070 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011071 app.adjType = "bg-services";
11072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011073 }
11074
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011075 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11076 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011077 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011078 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11079 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011080 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011081 if (cpr.clients.size() != 0) {
11082 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11083 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11084 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011085 if (client == app) {
11086 // Being our own client is not interesting.
11087 continue;
11088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 int myHiddenAdj = hiddenAdj;
11090 if (myHiddenAdj > client.hiddenAdj) {
11091 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11092 myHiddenAdj = client.hiddenAdj;
11093 } else {
11094 myHiddenAdj = FOREGROUND_APP_ADJ;
11095 }
11096 }
11097 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011098 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011099 if (adj > clientAdj) {
11100 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011101 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011102 if (!client.hidden) {
11103 app.hidden = false;
11104 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011105 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011106 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11107 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011108 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011109 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011111 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11112 schedGroup = Process.THREAD_GROUP_DEFAULT;
11113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 }
11115 }
11116 // If the provider has external (non-framework) process
11117 // dependencies, ensure that its adjustment is at least
11118 // FOREGROUND_APP_ADJ.
11119 if (cpr.externals != 0) {
11120 if (adj > FOREGROUND_APP_ADJ) {
11121 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011122 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011123 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011124 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011125 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011126 }
11127 }
11128 }
11129 }
11130
11131 app.curRawAdj = adj;
11132
Joe Onorato8a9b2202010-02-26 18:56:32 -080011133 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11135 if (adj > app.maxAdj) {
11136 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011137 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011138 schedGroup = Process.THREAD_GROUP_DEFAULT;
11139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 }
11141
11142 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011143 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 return adj;
11146 }
11147
11148 /**
11149 * Ask a given process to GC right now.
11150 */
11151 final void performAppGcLocked(ProcessRecord app) {
11152 try {
11153 app.lastRequestedGc = SystemClock.uptimeMillis();
11154 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011155 if (app.reportLowMemory) {
11156 app.reportLowMemory = false;
11157 app.thread.scheduleLowMemory();
11158 } else {
11159 app.thread.processInBackground();
11160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011161 }
11162 } catch (Exception e) {
11163 // whatever.
11164 }
11165 }
11166
11167 /**
11168 * Returns true if things are idle enough to perform GCs.
11169 */
Josh Bartel7f208742010-02-25 11:01:44 -060011170 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 return mParallelBroadcasts.size() == 0
11172 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011173 && (mSleeping || (mMainStack.mResumedActivity != null &&
11174 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011175 }
11176
11177 /**
11178 * Perform GCs on all processes that are waiting for it, but only
11179 * if things are idle.
11180 */
11181 final void performAppGcsLocked() {
11182 final int N = mProcessesToGc.size();
11183 if (N <= 0) {
11184 return;
11185 }
Josh Bartel7f208742010-02-25 11:01:44 -060011186 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011187 while (mProcessesToGc.size() > 0) {
11188 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011189 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011190 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11191 <= SystemClock.uptimeMillis()) {
11192 // To avoid spamming the system, we will GC processes one
11193 // at a time, waiting a few seconds between each.
11194 performAppGcLocked(proc);
11195 scheduleAppGcsLocked();
11196 return;
11197 } else {
11198 // It hasn't been long enough since we last GCed this
11199 // process... put it in the list to wait for its time.
11200 addProcessToGcListLocked(proc);
11201 break;
11202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011203 }
11204 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011205
11206 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011207 }
11208 }
11209
11210 /**
11211 * If all looks good, perform GCs on all processes waiting for them.
11212 */
11213 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011214 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011215 performAppGcsLocked();
11216 return;
11217 }
11218 // Still not idle, wait some more.
11219 scheduleAppGcsLocked();
11220 }
11221
11222 /**
11223 * Schedule the execution of all pending app GCs.
11224 */
11225 final void scheduleAppGcsLocked() {
11226 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011227
11228 if (mProcessesToGc.size() > 0) {
11229 // Schedule a GC for the time to the next process.
11230 ProcessRecord proc = mProcessesToGc.get(0);
11231 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11232
11233 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11234 long now = SystemClock.uptimeMillis();
11235 if (when < (now+GC_TIMEOUT)) {
11236 when = now + GC_TIMEOUT;
11237 }
11238 mHandler.sendMessageAtTime(msg, when);
11239 }
11240 }
11241
11242 /**
11243 * Add a process to the array of processes waiting to be GCed. Keeps the
11244 * list in sorted order by the last GC time. The process can't already be
11245 * on the list.
11246 */
11247 final void addProcessToGcListLocked(ProcessRecord proc) {
11248 boolean added = false;
11249 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11250 if (mProcessesToGc.get(i).lastRequestedGc <
11251 proc.lastRequestedGc) {
11252 added = true;
11253 mProcessesToGc.add(i+1, proc);
11254 break;
11255 }
11256 }
11257 if (!added) {
11258 mProcessesToGc.add(0, proc);
11259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 }
11261
11262 /**
11263 * Set up to ask a process to GC itself. This will either do it
11264 * immediately, or put it on the list of processes to gc the next
11265 * time things are idle.
11266 */
11267 final void scheduleAppGcLocked(ProcessRecord app) {
11268 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011269 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011270 return;
11271 }
11272 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011273 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011274 scheduleAppGcsLocked();
11275 }
11276 }
11277
11278 private final boolean updateOomAdjLocked(
11279 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11280 app.hiddenAdj = hiddenAdj;
11281
11282 if (app.thread == null) {
11283 return true;
11284 }
11285
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011286 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011287
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011288 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 if (app.curRawAdj != app.setRawAdj) {
11290 if (app.curRawAdj > FOREGROUND_APP_ADJ
11291 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11292 // If this app is transitioning from foreground to
11293 // non-foreground, have it do a gc.
11294 scheduleAppGcLocked(app);
11295 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11296 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11297 // Likewise do a gc when an app is moving in to the
11298 // background (such as a service stopping).
11299 scheduleAppGcLocked(app);
11300 }
11301 app.setRawAdj = app.curRawAdj;
11302 }
11303 if (adj != app.setAdj) {
11304 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011305 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011306 TAG, "Set app " + app.processName +
11307 " oom adj to " + adj);
11308 app.setAdj = adj;
11309 } else {
11310 return false;
11311 }
11312 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011313 if (app.setSchedGroup != app.curSchedGroup) {
11314 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011315 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011316 "Setting process group of " + app.processName
11317 + " to " + app.curSchedGroup);
11318 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011319 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011320 try {
11321 Process.setProcessGroup(app.pid, app.curSchedGroup);
11322 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011323 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011324 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011325 e.printStackTrace();
11326 } finally {
11327 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011328 }
11329 }
11330 if (false) {
11331 if (app.thread != null) {
11332 try {
11333 app.thread.setSchedulingGroup(app.curSchedGroup);
11334 } catch (RemoteException e) {
11335 }
11336 }
11337 }
11338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 }
11340
11341 return true;
11342 }
11343
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011344 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011345 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011346 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011347 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011348 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011349 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011350 }
11351 }
11352 return resumedActivity;
11353 }
11354
11355 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011356 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11358 int curAdj = app.curAdj;
11359 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11360 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11361
11362 mAdjSeq++;
11363
11364 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11365 if (res) {
11366 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11367 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11368 if (nowHidden != wasHidden) {
11369 // Changed to/from hidden state, so apps after it in the LRU
11370 // list may also be changed.
11371 updateOomAdjLocked();
11372 }
11373 }
11374 return res;
11375 }
11376
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011377 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011379 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011380 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11381
11382 if (false) {
11383 RuntimeException e = new RuntimeException();
11384 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011385 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011386 }
11387
11388 mAdjSeq++;
11389
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011390 // Let's determine how many processes we have running vs.
11391 // how many slots we have for background processes; we may want
11392 // to put multiple processes in a slot of there are enough of
11393 // them.
11394 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11395 int factor = (mLruProcesses.size()-4)/numSlots;
11396 if (factor < 1) factor = 1;
11397 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011398 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011400 // First try updating the OOM adjustment for each of the
11401 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011402 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11404 while (i > 0) {
11405 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011406 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011407 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011409 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011411 step++;
11412 if (step >= factor) {
11413 step = 0;
11414 curHiddenAdj++;
11415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011416 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011417 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011418 if (!app.killedBackground) {
11419 numHidden++;
11420 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011421 Slog.i(TAG, "No longer want " + app.processName
11422 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011423 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11424 app.processName, app.setAdj, "too many background");
11425 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011426 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011427 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011428 }
11429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011430 } else {
11431 didOomAdj = false;
11432 }
11433 }
11434
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011435 // If we return false, we will fall back on killing processes to
11436 // have a fixed limit. Do this if a limit has been requested; else
11437 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011438 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11439 }
11440
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011441 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 synchronized (this) {
11443 int i;
11444
11445 // First remove any unused application processes whose package
11446 // has been removed.
11447 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11448 final ProcessRecord app = mRemovedProcesses.get(i);
11449 if (app.activities.size() == 0
11450 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011451 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 TAG, "Exiting empty application process "
11453 + app.processName + " ("
11454 + (app.thread != null ? app.thread.asBinder() : null)
11455 + ")\n");
11456 if (app.pid > 0 && app.pid != MY_PID) {
11457 Process.killProcess(app.pid);
11458 } else {
11459 try {
11460 app.thread.scheduleExit();
11461 } catch (Exception e) {
11462 // Ignore exceptions.
11463 }
11464 }
11465 cleanUpApplicationRecordLocked(app, false, -1);
11466 mRemovedProcesses.remove(i);
11467
11468 if (app.persistent) {
11469 if (app.persistent) {
11470 addAppLocked(app.info);
11471 }
11472 }
11473 }
11474 }
11475
11476 // Now try updating the OOM adjustment for each of the
11477 // application processes based on their current state.
11478 // If the setOomAdj() API is not supported, then go with our
11479 // back-up plan...
11480 if (!updateOomAdjLocked()) {
11481
11482 // Count how many processes are running services.
11483 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011484 for (i=mLruProcesses.size()-1; i>=0; i--) {
11485 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011486
11487 if (app.persistent || app.services.size() != 0
11488 || app.curReceiver != null
11489 || app.persistentActivities > 0) {
11490 // Don't count processes holding services against our
11491 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011492 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011493 TAG, "Not trimming app " + app + " with services: "
11494 + app.services);
11495 numServiceProcs++;
11496 }
11497 }
11498
11499 int curMaxProcs = mProcessLimit;
11500 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11501 if (mAlwaysFinishActivities) {
11502 curMaxProcs = 1;
11503 }
11504 curMaxProcs += numServiceProcs;
11505
11506 // Quit as many processes as we can to get down to the desired
11507 // process count. First remove any processes that no longer
11508 // have activites running in them.
11509 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011510 i<mLruProcesses.size()
11511 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011512 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011513 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011514 // Quit an application only if it is not currently
11515 // running any activities.
11516 if (!app.persistent && app.activities.size() == 0
11517 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011518 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011519 TAG, "Exiting empty application process "
11520 + app.processName + " ("
11521 + (app.thread != null ? app.thread.asBinder() : null)
11522 + ")\n");
11523 if (app.pid > 0 && app.pid != MY_PID) {
11524 Process.killProcess(app.pid);
11525 } else {
11526 try {
11527 app.thread.scheduleExit();
11528 } catch (Exception e) {
11529 // Ignore exceptions.
11530 }
11531 }
11532 // todo: For now we assume the application is not buggy
11533 // or evil, and will quit as a result of our request.
11534 // Eventually we need to drive this off of the death
11535 // notification, and kill the process if it takes too long.
11536 cleanUpApplicationRecordLocked(app, false, i);
11537 i--;
11538 }
11539 }
11540
11541 // If we still have too many processes, now from the least
11542 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011543 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011544 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 " of " + curMaxProcs + " processes");
11546 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011547 i<mLruProcesses.size()
11548 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011550 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011551 // Quit the application only if we have a state saved for
11552 // all of its activities.
11553 boolean canQuit = !app.persistent && app.curReceiver == null
11554 && app.services.size() == 0
11555 && app.persistentActivities == 0;
11556 int NUMA = app.activities.size();
11557 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011558 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011559 TAG, "Looking to quit " + app.processName);
11560 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011561 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011562 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 TAG, " " + r.intent.getComponent().flattenToShortString()
11564 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11565 canQuit = (r.haveState || !r.stateNotNeeded)
11566 && !r.visible && r.stopped;
11567 }
11568 if (canQuit) {
11569 // Finish all of the activities, and then the app itself.
11570 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011571 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011573 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011574 }
11575 r.resultTo = null;
11576 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011577 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 + app.processName + " ("
11579 + (app.thread != null ? app.thread.asBinder() : null)
11580 + ")\n");
11581 if (app.pid > 0 && app.pid != MY_PID) {
11582 Process.killProcess(app.pid);
11583 } else {
11584 try {
11585 app.thread.scheduleExit();
11586 } catch (Exception e) {
11587 // Ignore exceptions.
11588 }
11589 }
11590 // todo: For now we assume the application is not buggy
11591 // or evil, and will quit as a result of our request.
11592 // Eventually we need to drive this off of the death
11593 // notification, and kill the process if it takes too long.
11594 cleanUpApplicationRecordLocked(app, false, i);
11595 i--;
11596 //dump();
11597 }
11598 }
11599
11600 }
11601
11602 int curMaxActivities = MAX_ACTIVITIES;
11603 if (mAlwaysFinishActivities) {
11604 curMaxActivities = 1;
11605 }
11606
11607 // Finally, if there are too many activities now running, try to
11608 // finish as many as we can to get back down to the limit.
11609 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011610 i<mMainStack.mLRUActivities.size()
11611 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011612 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011613 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011614 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011615
11616 // We can finish this one if we have its icicle saved and
11617 // it is not persistent.
11618 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11619 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011620 final int origSize = mMainStack.mLRUActivities.size();
11621 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011622
11623 // This will remove it from the LRU list, so keep
11624 // our index at the same value. Note that this check to
11625 // see if the size changes is just paranoia -- if
11626 // something unexpected happens, we don't want to end up
11627 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011628 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011629 i--;
11630 }
11631 }
11632 }
11633 }
11634 }
11635
11636 /** This method sends the specified signal to each of the persistent apps */
11637 public void signalPersistentProcesses(int sig) throws RemoteException {
11638 if (sig != Process.SIGNAL_USR1) {
11639 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11640 }
11641
11642 synchronized (this) {
11643 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11644 != PackageManager.PERMISSION_GRANTED) {
11645 throw new SecurityException("Requires permission "
11646 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11647 }
11648
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011649 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11650 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011651 if (r.thread != null && r.persistent) {
11652 Process.sendSignal(r.pid, sig);
11653 }
11654 }
11655 }
11656 }
11657
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011658 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011659 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011660
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011661 try {
11662 synchronized (this) {
11663 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11664 // its own permission.
11665 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11666 != PackageManager.PERMISSION_GRANTED) {
11667 throw new SecurityException("Requires permission "
11668 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011669 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011670
11671 if (start && fd == null) {
11672 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011673 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011674
11675 ProcessRecord proc = null;
11676 try {
11677 int pid = Integer.parseInt(process);
11678 synchronized (mPidsSelfLocked) {
11679 proc = mPidsSelfLocked.get(pid);
11680 }
11681 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011682 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011683
11684 if (proc == null) {
11685 HashMap<String, SparseArray<ProcessRecord>> all
11686 = mProcessNames.getMap();
11687 SparseArray<ProcessRecord> procs = all.get(process);
11688 if (procs != null && procs.size() > 0) {
11689 proc = procs.valueAt(0);
11690 }
11691 }
11692
11693 if (proc == null || proc.thread == null) {
11694 throw new IllegalArgumentException("Unknown process: " + process);
11695 }
11696
11697 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11698 if (isSecure) {
11699 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11700 throw new SecurityException("Process not debuggable: " + proc);
11701 }
11702 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011703
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011704 proc.thread.profilerControl(start, path, fd);
11705 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011706 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011707 }
11708 } catch (RemoteException e) {
11709 throw new IllegalStateException("Process disappeared");
11710 } finally {
11711 if (fd != null) {
11712 try {
11713 fd.close();
11714 } catch (IOException e) {
11715 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011716 }
11717 }
11718 }
Andy McFadden824c5102010-07-09 16:26:57 -070011719
11720 public boolean dumpHeap(String process, boolean managed,
11721 String path, ParcelFileDescriptor fd) throws RemoteException {
11722
11723 try {
11724 synchronized (this) {
11725 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11726 // its own permission (same as profileControl).
11727 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11728 != PackageManager.PERMISSION_GRANTED) {
11729 throw new SecurityException("Requires permission "
11730 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
11731 }
11732
11733 if (fd == null) {
11734 throw new IllegalArgumentException("null fd");
11735 }
11736
11737 ProcessRecord proc = null;
11738 try {
11739 int pid = Integer.parseInt(process);
11740 synchronized (mPidsSelfLocked) {
11741 proc = mPidsSelfLocked.get(pid);
11742 }
11743 } catch (NumberFormatException e) {
11744 }
11745
11746 if (proc == null) {
11747 HashMap<String, SparseArray<ProcessRecord>> all
11748 = mProcessNames.getMap();
11749 SparseArray<ProcessRecord> procs = all.get(process);
11750 if (procs != null && procs.size() > 0) {
11751 proc = procs.valueAt(0);
11752 }
11753 }
11754
11755 if (proc == null || proc.thread == null) {
11756 throw new IllegalArgumentException("Unknown process: " + process);
11757 }
11758
11759 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11760 if (isSecure) {
11761 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11762 throw new SecurityException("Process not debuggable: " + proc);
11763 }
11764 }
11765
11766 proc.thread.dumpHeap(managed, path, fd);
11767 fd = null;
11768 return true;
11769 }
11770 } catch (RemoteException e) {
11771 throw new IllegalStateException("Process disappeared");
11772 } finally {
11773 if (fd != null) {
11774 try {
11775 fd.close();
11776 } catch (IOException e) {
11777 }
11778 }
11779 }
11780 }
11781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011782 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11783 public void monitor() {
11784 synchronized (this) { }
11785 }
11786}