blob: 2c6806bcace7089f59a65f14ede2ca51809e7bd8 [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;
61import android.content.Intent;
62import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070063import android.content.IIntentReceiver;
64import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070065import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.ActivityInfo;
67import android.content.pm.ApplicationInfo;
68import android.content.pm.ConfigurationInfo;
69import android.content.pm.IPackageDataObserver;
70import android.content.pm.IPackageManager;
71import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080072import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070074import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.content.pm.ProviderInfo;
76import android.content.pm.ResolveInfo;
77import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070078import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.content.res.Configuration;
80import android.graphics.Bitmap;
81import android.net.Uri;
82import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080084import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070085import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.FileUtils;
90import android.os.Handler;
91import android.os.IBinder;
92import android.os.IPermissionController;
93import android.os.Looper;
94import android.os.Message;
95import android.os.Parcel;
96import android.os.ParcelFileDescriptor;
97import android.os.PowerManager;
98import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070099import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.RemoteException;
101import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700102import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.os.SystemClock;
104import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.util.Config;
107import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800108import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800109import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.util.PrintWriterPrinter;
111import android.util.SparseArray;
112import android.view.Gravity;
113import android.view.LayoutInflater;
114import android.view.View;
115import android.view.WindowManager;
116import android.view.WindowManagerPolicy;
117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import java.io.File;
119import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200121import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800122import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import java.io.PrintWriter;
124import java.lang.IllegalStateException;
125import java.lang.ref.WeakReference;
126import java.util.ArrayList;
127import java.util.HashMap;
128import java.util.HashSet;
129import java.util.Iterator;
130import java.util.List;
131import java.util.Locale;
132import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700133import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700134import java.util.concurrent.atomic.AtomicBoolean;
135import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136
137public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
138 static final String TAG = "ActivityManager";
139 static final boolean DEBUG = false;
140 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
141 static final boolean DEBUG_SWITCH = localLOGV || false;
142 static final boolean DEBUG_TASKS = localLOGV || false;
143 static final boolean DEBUG_PAUSE = localLOGV || false;
144 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
145 static final boolean DEBUG_TRANSITION = localLOGV || false;
146 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700147 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 static final boolean DEBUG_SERVICE = localLOGV || false;
149 static final boolean DEBUG_VISBILITY = localLOGV || false;
150 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700151 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800152 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700154 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700155 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700156 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean VALIDATE_TOKENS = false;
158 static final boolean SHOW_ACTIVITY_START_TIME = true;
159
160 // Control over CPU and battery monitoring.
161 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
162 static final boolean MONITOR_CPU_USAGE = true;
163 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
164 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
165 static final boolean MONITOR_THREAD_CPU_USAGE = false;
166
Dianne Hackborn1655be42009-05-08 14:29:01 -0700167 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700168 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 private static final String SYSTEM_SECURE = "ro.secure";
171
172 // This is the maximum number of application processes we would like
173 // to have running. Due to the asynchronous nature of things, we can
174 // temporarily go beyond this limit.
175 static final int MAX_PROCESSES = 2;
176
177 // Set to false to leave processes running indefinitely, relying on
178 // the kernel killing them as resources are required.
179 static final boolean ENFORCE_PROCESS_LIMIT = false;
180
181 // This is the maximum number of activities that we would like to have
182 // running at a given time.
183 static final int MAX_ACTIVITIES = 20;
184
185 // Maximum number of recent tasks that we can remember.
186 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700187
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700188 // Amount of time after a call to stopAppSwitches() during which we will
189 // prevent further untrusted switches from happening.
190 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191
192 // How long we wait for a launched process to attach to the activity manager
193 // before we decide it's never going to come up for real.
194 static final int PROC_START_TIMEOUT = 10*1000;
195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 // How long to wait after going idle before forcing apps to GC.
197 static final int GC_TIMEOUT = 5*1000;
198
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700199 // The minimum amount of time between successive GC requests for a process.
200 static final int GC_MIN_INTERVAL = 60*1000;
201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 // How long we allow a receiver to run before giving up on it.
203 static final int BROADCAST_TIMEOUT = 10*1000;
204
205 // How long we wait for a service to finish executing.
206 static final int SERVICE_TIMEOUT = 20*1000;
207
208 // How long a service needs to be running until restarting its process
209 // is no longer considered to be a relaunch of the service.
210 static final int SERVICE_RESTART_DURATION = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // How long a service needs to be running until it will start back at
213 // SERVICE_RESTART_DURATION after being killed.
214 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
215
216 // Multiplying factor to increase restart duration time by, for each time
217 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
218 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
219
220 // The minimum amount of time between restarting services that we allow.
221 // That is, when multiple services are restarting, we won't allow each
222 // to restart less than this amount of time from the last one.
223 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // Maximum amount of time for there to be no activity on a service before
226 // we consider it non-essential and allow its process to go on the
227 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700228 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
230 // How long we wait until we timeout on key dispatching.
231 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
232
233 // The minimum time we allow between crashes, for us to consider this
234 // application to be bad and stop and its services and reject broadcasts.
235 static final int MIN_CRASH_INTERVAL = 60*1000;
236
237 // How long we wait until we timeout on key dispatching during instrumentation.
238 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
239
240 // OOM adjustments for processes in various states:
241
242 // This is a process without anything currently running in it. Definitely
243 // the first to go! Value set in system/rootdir/init.rc on startup.
244 // This value is initalized in the constructor, careful when refering to
245 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800246 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // This is a process only hosting activities that are not visible,
249 // so it can be killed without any disruption. Value set in
250 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800251 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 static int HIDDEN_APP_MIN_ADJ;
253
The Android Open Source Project4df24232009-03-05 14:34:35 -0800254 // This is a process holding the home application -- we want to try
255 // avoiding killing it, even if it would normally be in the background,
256 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800257 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800258
Christopher Tate6fa95972009-06-05 18:43:55 -0700259 // This is a process currently hosting a backup operation. Killing it
260 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800261 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 // This is a process holding a secondary server -- killing it will not
264 // have much of an impact as far as the user is concerned. Value set in
265 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800266 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700268 // This is a process with a heavy-weight application. It is in the
269 // background, but we want to try to avoid killing it. Value set in
270 // system/rootdir/init.rc on startup.
271 static final int HEAVY_WEIGHT_APP_ADJ;
272
273 // This is a process only hosting components that are perceptible to the
274 // user, and we really want to avoid killing them, but they are not
275 // immediately visible. An example is background music playback. Value set in
276 // system/rootdir/init.rc on startup.
277 static final int PERCEPTIBLE_APP_ADJ;
278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 // This is a process only hosting activities that are visible to the
280 // user, so we'd prefer they don't disappear. Value set in
281 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800282 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283
284 // This is the process running the current foreground app. We'd really
285 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
288 // This is a process running a core server, such as telephony. Definitely
289 // don't want to kill it, but doing so is not completely fatal.
290 static final int CORE_SERVER_ADJ = -12;
291
292 // The system process runs at the default adjustment.
293 static final int SYSTEM_ADJ = -16;
294
295 // Memory pages are 4K.
296 static final int PAGE_SIZE = 4*1024;
297
298 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800299 static final int EMPTY_APP_MEM;
300 static final int HIDDEN_APP_MEM;
301 static final int HOME_APP_MEM;
302 static final int BACKUP_APP_MEM;
303 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700304 static final int HEAVY_WEIGHT_APP_MEM;
305 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int VISIBLE_APP_MEM;
307 static final int FOREGROUND_APP_MEM;
308
309 // The minimum number of hidden apps we want to be able to keep around,
310 // without empty apps being able to push them out of memory.
311 static final int MIN_HIDDEN_APPS = 2;
312
Dianne Hackborn8633e682010-04-22 16:03:41 -0700313 // The maximum number of hidden processes we will keep around before
314 // killing them; this is just a control to not let us go too crazy with
315 // keeping around processes on devices with large amounts of RAM.
316 static final int MAX_HIDDEN_APPS = 15;
317
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800318 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700319 // been idle for less than 15 seconds.
320 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800321
322 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700323 // been idle for less than 120 seconds.
324 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800325
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700326 static int getIntProp(String name, boolean allowZero) {
327 String str = SystemProperties.get(name);
328 if (str == null) {
329 throw new IllegalArgumentException("Property not defined: " + name);
330 }
331 int val = Integer.valueOf(str);
332 if (val == 0 && !allowZero) {
333 throw new IllegalArgumentException("Property must not be zero: " + name);
334 }
335 return val;
336 }
337
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800338 static {
339 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700340 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
341 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
342 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
343 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
344 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
345 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
346 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
347 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
348 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
349 // These days we use the last empty slot for hidden apps as well.
350 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
351 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
352 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
353 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
354 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
355 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
356 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
357 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
358 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
359 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
Dan Egnor42471dd2010-01-07 17:25:22 -0800362 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
364 static final String[] EMPTY_STRING_ARRAY = new String[0];
365
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700366 public ActivityStack mMainStack;
367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700369 * Description of a request to start a new activity, which has been held
370 * due to app switches being disabled.
371 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700372 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700373 ActivityRecord r;
374 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700375 Uri[] grantedUriPermissions;
376 int grantedMode;
377 boolean onlyIfNeeded;
378 }
379
380 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
381 = new ArrayList<PendingActivityLaunch>();
382
383 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 * List of all active broadcasts that are to be executed immediately
385 * (without waiting for another broadcast to finish). Currently this only
386 * contains broadcasts to registered receivers, to avoid spinning up
387 * a bunch of processes to execute IntentReceiver components.
388 */
389 final ArrayList<BroadcastRecord> mParallelBroadcasts
390 = new ArrayList<BroadcastRecord>();
391
392 /**
393 * List of all active broadcasts that are to be executed one at a time.
394 * The object at the top of the list is the currently activity broadcasts;
395 * those after it are waiting for the top to finish..
396 */
397 final ArrayList<BroadcastRecord> mOrderedBroadcasts
398 = new ArrayList<BroadcastRecord>();
399
400 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800401 * Historical data of past broadcasts, for debugging.
402 */
403 static final int MAX_BROADCAST_HISTORY = 100;
404 final BroadcastRecord[] mBroadcastHistory
405 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * Set when we current have a BROADCAST_INTENT_MSG in flight.
409 */
410 boolean mBroadcastsScheduled = false;
411
412 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 * Activity we have told the window manager to have key focus.
414 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700415 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700416 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 * List of intents that were used to start the most recent tasks.
418 */
419 final ArrayList<TaskRecord> mRecentTasks
420 = new ArrayList<TaskRecord>();
421
422 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 * All of the applications we currently have running organized by name.
424 * The keys are strings of the application package name (as
425 * returned by the package manager), and the keys are ApplicationRecord
426 * objects.
427 */
428 final ProcessMap<ProcessRecord> mProcessNames
429 = new ProcessMap<ProcessRecord>();
430
431 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700432 * The currently running heavy-weight process, if any.
433 */
434 ProcessRecord mHeavyWeightProcess = null;
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * The last time that various processes have crashed.
438 */
439 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
440
441 /**
442 * Set of applications that we consider to be bad, and will reject
443 * incoming broadcasts from (which the user has no control over).
444 * Processes are added to this set when they have crashed twice within
445 * a minimum amount of time; they are removed from it when they are
446 * later restarted (hopefully due to some user action). The value is the
447 * time it was added to the list.
448 */
449 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
450
451 /**
452 * All of the processes we currently have running organized by pid.
453 * The keys are the pid running the application.
454 *
455 * <p>NOTE: This object is protected by its own lock, NOT the global
456 * activity manager lock!
457 */
458 final SparseArray<ProcessRecord> mPidsSelfLocked
459 = new SparseArray<ProcessRecord>();
460
461 /**
462 * All of the processes that have been forced to be foreground. The key
463 * is the pid of the caller who requested it (we hold a death
464 * link on it).
465 */
466 abstract class ForegroundToken implements IBinder.DeathRecipient {
467 int pid;
468 IBinder token;
469 }
470 final SparseArray<ForegroundToken> mForegroundProcesses
471 = new SparseArray<ForegroundToken>();
472
473 /**
474 * List of records for processes that someone had tried to start before the
475 * system was ready. We don't start them at that point, but ensure they
476 * are started by the time booting is complete.
477 */
478 final ArrayList<ProcessRecord> mProcessesOnHold
479 = new ArrayList<ProcessRecord>();
480
481 /**
482 * List of records for processes that we have started and are waiting
483 * for them to call back. This is really only needed when running in
484 * single processes mode, in which case we do not have a unique pid for
485 * each process.
486 */
487 final ArrayList<ProcessRecord> mStartingProcesses
488 = new ArrayList<ProcessRecord>();
489
490 /**
491 * List of persistent applications that are in the process
492 * of being started.
493 */
494 final ArrayList<ProcessRecord> mPersistentStartingProcesses
495 = new ArrayList<ProcessRecord>();
496
497 /**
498 * Processes that are being forcibly torn down.
499 */
500 final ArrayList<ProcessRecord> mRemovedProcesses
501 = new ArrayList<ProcessRecord>();
502
503 /**
504 * List of running applications, sorted by recent usage.
505 * The first entry in the list is the least recently used.
506 * It contains ApplicationRecord objects. This list does NOT include
507 * any persistent application records (since we never want to exit them).
508 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800509 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 = new ArrayList<ProcessRecord>();
511
512 /**
513 * List of processes that should gc as soon as things are idle.
514 */
515 final ArrayList<ProcessRecord> mProcessesToGc
516 = new ArrayList<ProcessRecord>();
517
518 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800519 * This is the process holding what we currently consider to be
520 * the "home" activity.
521 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700522 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800523
524 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 * Set of PendingResultRecord objects that are currently active.
526 */
527 final HashSet mPendingResultRecords = new HashSet();
528
529 /**
530 * Set of IntentSenderRecord objects that are currently active.
531 */
532 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
533 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
534
535 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700536 * Fingerprints (String.hashCode()) of stack traces that we've
537 * already logged DropBox entries for. Guarded by itself. If
538 * something (rogue user app) forces this over
539 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
540 */
541 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
542 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
543
544 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 * Intent broadcast that we have tried to start, but are
546 * waiting for its application's process to be created. We only
547 * need one (instead of a list) because we always process broadcasts
548 * one at a time, so no others can be started while waiting for this
549 * one.
550 */
551 BroadcastRecord mPendingBroadcast = null;
552
553 /**
554 * Keeps track of all IIntentReceivers that have been registered for
555 * broadcasts. Hash keys are the receiver IBinder, hash value is
556 * a ReceiverList.
557 */
558 final HashMap mRegisteredReceivers = new HashMap();
559
560 /**
561 * Resolver for broadcast intents to registered receivers.
562 * Holds BroadcastFilter (subclass of IntentFilter).
563 */
564 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
565 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
566 @Override
567 protected boolean allowFilterResult(
568 BroadcastFilter filter, List<BroadcastFilter> dest) {
569 IBinder target = filter.receiverList.receiver.asBinder();
570 for (int i=dest.size()-1; i>=0; i--) {
571 if (dest.get(i).receiverList.receiver.asBinder() == target) {
572 return false;
573 }
574 }
575 return true;
576 }
577 };
578
579 /**
580 * State of all active sticky broadcasts. Keys are the action of the
581 * sticky Intent, values are an ArrayList of all broadcasted intents with
582 * that action (which should usually be one).
583 */
584 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
585 new HashMap<String, ArrayList<Intent>>();
586
587 /**
588 * All currently running services.
589 */
590 final HashMap<ComponentName, ServiceRecord> mServices =
591 new HashMap<ComponentName, ServiceRecord>();
592
593 /**
594 * All currently running services indexed by the Intent used to start them.
595 */
596 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
597 new HashMap<Intent.FilterComparison, ServiceRecord>();
598
599 /**
600 * All currently bound service connections. Keys are the IBinder of
601 * the client's IServiceConnection.
602 */
603 final HashMap<IBinder, ConnectionRecord> mServiceConnections
604 = new HashMap<IBinder, ConnectionRecord>();
605
606 /**
607 * List of services that we have been asked to start,
608 * but haven't yet been able to. It is used to hold start requests
609 * while waiting for their corresponding application thread to get
610 * going.
611 */
612 final ArrayList<ServiceRecord> mPendingServices
613 = new ArrayList<ServiceRecord>();
614
615 /**
616 * List of services that are scheduled to restart following a crash.
617 */
618 final ArrayList<ServiceRecord> mRestartingServices
619 = new ArrayList<ServiceRecord>();
620
621 /**
622 * List of services that are in the process of being stopped.
623 */
624 final ArrayList<ServiceRecord> mStoppingServices
625 = new ArrayList<ServiceRecord>();
626
627 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700628 * Backup/restore process management
629 */
630 String mBackupAppName = null;
631 BackupRecord mBackupTarget = null;
632
633 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 * List of PendingThumbnailsRecord objects of clients who are still
635 * waiting to receive all of the thumbnails for a task.
636 */
637 final ArrayList mPendingThumbnails = new ArrayList();
638
639 /**
640 * List of HistoryRecord objects that have been finished and must
641 * still report back to a pending thumbnail receiver.
642 */
643 final ArrayList mCancelledThumbnails = new ArrayList();
644
645 /**
646 * All of the currently running global content providers. Keys are a
647 * string containing the provider name and values are a
648 * ContentProviderRecord object containing the data about it. Note
649 * that a single provider may be published under multiple names, so
650 * there may be multiple entries here for a single one in mProvidersByClass.
651 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700652 final HashMap<String, ContentProviderRecord> mProvidersByName
653 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654
655 /**
656 * All of the currently running global content providers. Keys are a
657 * string containing the provider's implementation class and values are a
658 * ContentProviderRecord object containing the data about it.
659 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700660 final HashMap<String, ContentProviderRecord> mProvidersByClass
661 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662
663 /**
664 * List of content providers who have clients waiting for them. The
665 * application is currently being launched and the provider will be
666 * removed from this list once it is published.
667 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700668 final ArrayList<ContentProviderRecord> mLaunchingProviders
669 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670
671 /**
672 * Global set of specific Uri permissions that have been granted.
673 */
674 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
675 = new SparseArray<HashMap<Uri, UriPermission>>();
676
677 /**
678 * Thread-local storage used to carry caller permissions over through
679 * indirect content-provider access.
680 * @see #ActivityManagerService.openContentUri()
681 */
682 private class Identity {
683 public int pid;
684 public int uid;
685
686 Identity(int _pid, int _uid) {
687 pid = _pid;
688 uid = _uid;
689 }
690 }
691 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
692
693 /**
694 * All information we have collected about the runtime performance of
695 * any user id that can impact battery performance.
696 */
697 final BatteryStatsService mBatteryStatsService;
698
699 /**
700 * information about component usage
701 */
702 final UsageStatsService mUsageStatsService;
703
704 /**
705 * Current configuration information. HistoryRecord objects are given
706 * a reference to this object to indicate which configuration they are
707 * currently running in, so this object must be kept immutable.
708 */
709 Configuration mConfiguration = new Configuration();
710
711 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800712 * Current sequencing integer of the configuration, for skipping old
713 * configurations.
714 */
715 int mConfigurationSeq = 0;
716
717 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700718 * Hardware-reported OpenGLES version.
719 */
720 final int GL_ES_VERSION;
721
722 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 * List of initialization arguments to pass to all processes when binding applications to them.
724 * For example, references to the commonly used services.
725 */
726 HashMap<String, IBinder> mAppBindArgs;
727
728 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700729 * Temporary to avoid allocations. Protected by main lock.
730 */
731 final StringBuilder mStringBuilder = new StringBuilder(256);
732
733 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 * Used to control how we initialize the service.
735 */
736 boolean mStartRunning = false;
737 ComponentName mTopComponent;
738 String mTopAction;
739 String mTopData;
740 boolean mSystemReady = false;
741 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700742 boolean mWaitingUpdate = false;
743 boolean mDidUpdate = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744
745 Context mContext;
746
747 int mFactoryTest;
748
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700749 boolean mCheckedForSetup;
750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700752 * The time at which we will allow normal application switches again,
753 * after a call to {@link #stopAppSwitches()}.
754 */
755 long mAppSwitchesAllowedTime;
756
757 /**
758 * This is set to true after the first switch after mAppSwitchesAllowedTime
759 * is set; any switches after that will clear the time.
760 */
761 boolean mDidAppSwitch;
762
763 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764 * Set while we are wanting to sleep, to prevent any
765 * activities from being started/resumed.
766 */
767 boolean mSleeping = false;
768
769 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700770 * Set if we are shutting down the system, similar to sleeping.
771 */
772 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773
774 /**
775 * Task identifier that activities are currently being started
776 * in. Incremented each time a new task is created.
777 * todo: Replace this with a TokenSpace class that generates non-repeating
778 * integers that won't wrap.
779 */
780 int mCurTask = 1;
781
782 /**
783 * Current sequence id for oom_adj computation traversal.
784 */
785 int mAdjSeq = 0;
786
787 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700788 * Current sequence id for process LRU updating.
789 */
790 int mLruSeq = 0;
791
792 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
794 * is set, indicating the user wants processes started in such a way
795 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
796 * running in each process (thus no pre-initialized process, etc).
797 */
798 boolean mSimpleProcessManagement = false;
799
800 /**
801 * System monitoring: number of processes that died since the last
802 * N procs were started.
803 */
804 int[] mProcDeaths = new int[20];
805
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700806 /**
807 * This is set if we had to do a delayed dexopt of an app before launching
808 * it, to increasing the ANR timeouts in that case.
809 */
810 boolean mDidDexOpt;
811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 String mDebugApp = null;
813 boolean mWaitForDebugger = false;
814 boolean mDebugTransient = false;
815 String mOrigDebugApp = null;
816 boolean mOrigWaitForDebugger = false;
817 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700818 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700820 final RemoteCallbackList<IActivityWatcher> mWatchers
821 = new RemoteCallbackList<IActivityWatcher>();
822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823 /**
824 * Callback of last caller to {@link #requestPss}.
825 */
826 Runnable mRequestPssCallback;
827
828 /**
829 * Remaining processes for which we are waiting results from the last
830 * call to {@link #requestPss}.
831 */
832 final ArrayList<ProcessRecord> mRequestPssList
833 = new ArrayList<ProcessRecord>();
834
835 /**
836 * Runtime statistics collection thread. This object's lock is used to
837 * protect all related state.
838 */
839 final Thread mProcessStatsThread;
840
841 /**
842 * Used to collect process stats when showing not responding dialog.
843 * Protected by mProcessStatsThread.
844 */
845 final ProcessStats mProcessStats = new ProcessStats(
846 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700847 final AtomicLong mLastCpuTime = new AtomicLong(0);
848 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 long mLastWriteTime = 0;
851
852 /**
853 * Set to true after the system has finished booting.
854 */
855 boolean mBooted = false;
856
857 int mProcessLimit = 0;
858
859 WindowManagerService mWindowManager;
860
861 static ActivityManagerService mSelf;
862 static ActivityThread mSystemThread;
863
864 private final class AppDeathRecipient implements IBinder.DeathRecipient {
865 final ProcessRecord mApp;
866 final int mPid;
867 final IApplicationThread mAppThread;
868
869 AppDeathRecipient(ProcessRecord app, int pid,
870 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800871 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 TAG, "New death recipient " + this
873 + " for thread " + thread.asBinder());
874 mApp = app;
875 mPid = pid;
876 mAppThread = thread;
877 }
878
879 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800880 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 TAG, "Death received in " + this
882 + " for thread " + mAppThread.asBinder());
883 removeRequestedPss(mApp);
884 synchronized(ActivityManagerService.this) {
885 appDiedLocked(mApp, mPid, mAppThread);
886 }
887 }
888 }
889
890 static final int SHOW_ERROR_MSG = 1;
891 static final int SHOW_NOT_RESPONDING_MSG = 2;
892 static final int SHOW_FACTORY_ERROR_MSG = 3;
893 static final int UPDATE_CONFIGURATION_MSG = 4;
894 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
895 static final int WAIT_FOR_DEBUGGER_MSG = 6;
896 static final int BROADCAST_INTENT_MSG = 7;
897 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 static final int SERVICE_TIMEOUT_MSG = 12;
899 static final int UPDATE_TIME_ZONE = 13;
900 static final int SHOW_UID_ERROR_MSG = 14;
901 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700903 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700904 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800905 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700906 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
907 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700908 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909
910 AlertDialog mUidAlert;
911
912 final Handler mHandler = new Handler() {
913 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800914 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 //}
916
917 public void handleMessage(Message msg) {
918 switch (msg.what) {
919 case SHOW_ERROR_MSG: {
920 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 synchronized (ActivityManagerService.this) {
922 ProcessRecord proc = (ProcessRecord)data.get("app");
923 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800924 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 return;
926 }
927 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700928 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800929 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 d.show();
931 proc.crashDialog = d;
932 } else {
933 // The device is asleep, so just pretend that the user
934 // saw a crash dialog and hit "force quit".
935 res.set(0);
936 }
937 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700938
939 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 } break;
941 case SHOW_NOT_RESPONDING_MSG: {
942 synchronized (ActivityManagerService.this) {
943 HashMap data = (HashMap) msg.obj;
944 ProcessRecord proc = (ProcessRecord)data.get("app");
945 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800946 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 return;
948 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800949
950 broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
951 null, null, 0, null, null, null,
952 false, false, MY_PID, Process.SYSTEM_UID);
953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700955 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 d.show();
957 proc.anrDialog = d;
958 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700959
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700960 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700962 case SHOW_STRICT_MODE_VIOLATION_MSG: {
963 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
964 synchronized (ActivityManagerService.this) {
965 ProcessRecord proc = (ProcessRecord) data.get("app");
966 if (proc == null) {
967 Slog.e(TAG, "App not found when showing strict mode dialog.");
968 break;
969 }
970 if (proc.crashDialog != null) {
971 Slog.e(TAG, "App already has strict mode dialog: " + proc);
972 return;
973 }
974 AppErrorResult res = (AppErrorResult) data.get("result");
975 if (!mSleeping && !mShuttingDown) {
976 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
977 d.show();
978 proc.crashDialog = d;
979 } else {
980 // The device is asleep, so just pretend that the user
981 // saw a crash dialog and hit "force quit".
982 res.set(0);
983 }
984 }
985 ensureBootCompleted();
986 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 case SHOW_FACTORY_ERROR_MSG: {
988 Dialog d = new FactoryErrorDialog(
989 mContext, msg.getData().getCharSequence("msg"));
990 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700991 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 } break;
993 case UPDATE_CONFIGURATION_MSG: {
994 final ContentResolver resolver = mContext.getContentResolver();
995 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
996 } break;
997 case GC_BACKGROUND_PROCESSES_MSG: {
998 synchronized (ActivityManagerService.this) {
999 performAppGcsIfAppropriateLocked();
1000 }
1001 } break;
1002 case WAIT_FOR_DEBUGGER_MSG: {
1003 synchronized (ActivityManagerService.this) {
1004 ProcessRecord app = (ProcessRecord)msg.obj;
1005 if (msg.arg1 != 0) {
1006 if (!app.waitedForDebugger) {
1007 Dialog d = new AppWaitingForDebuggerDialog(
1008 ActivityManagerService.this,
1009 mContext, app);
1010 app.waitDialog = d;
1011 app.waitedForDebugger = true;
1012 d.show();
1013 }
1014 } else {
1015 if (app.waitDialog != null) {
1016 app.waitDialog.dismiss();
1017 app.waitDialog = null;
1018 }
1019 }
1020 }
1021 } break;
1022 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001023 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 TAG, "Received BROADCAST_INTENT_MSG");
1025 processNextBroadcast(true);
1026 } break;
1027 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001028 if (mDidDexOpt) {
1029 mDidDexOpt = false;
1030 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1031 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1032 return;
1033 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001034 // Only process broadcast timeouts if the system is ready. That way
1035 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1036 // to do heavy lifting for system up
1037 if (mSystemReady) {
1038 broadcastTimeout();
1039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001042 if (mDidDexOpt) {
1043 mDidDexOpt = false;
1044 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1045 nmsg.obj = msg.obj;
1046 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1047 return;
1048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 serviceTimeout((ProcessRecord)msg.obj);
1050 } break;
1051 case UPDATE_TIME_ZONE: {
1052 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001053 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1054 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 if (r.thread != null) {
1056 try {
1057 r.thread.updateTimeZone();
1058 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001059 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 }
1061 }
1062 }
1063 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001064 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 case SHOW_UID_ERROR_MSG: {
1066 // XXX This is a temporary dialog, no need to localize.
1067 AlertDialog d = new BaseErrorDialog(mContext);
1068 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1069 d.setCancelable(false);
1070 d.setTitle("System UIDs Inconsistent");
1071 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1072 d.setButton("I'm Feeling Lucky",
1073 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1074 mUidAlert = d;
1075 d.show();
1076 } break;
1077 case IM_FEELING_LUCKY_MSG: {
1078 if (mUidAlert != null) {
1079 mUidAlert.dismiss();
1080 mUidAlert = null;
1081 }
1082 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001084 if (mDidDexOpt) {
1085 mDidDexOpt = false;
1086 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1087 nmsg.obj = msg.obj;
1088 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1089 return;
1090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 ProcessRecord app = (ProcessRecord)msg.obj;
1092 synchronized (ActivityManagerService.this) {
1093 processStartTimedOutLocked(app);
1094 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001095 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001096 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1097 synchronized (ActivityManagerService.this) {
1098 doPendingActivityLaunchesLocked(true);
1099 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001100 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001101 case KILL_APPLICATION_MSG: {
1102 synchronized (ActivityManagerService.this) {
1103 int uid = msg.arg1;
1104 boolean restart = (msg.arg2 == 1);
1105 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001106 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001107 }
1108 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001109 case FINALIZE_PENDING_INTENT_MSG: {
1110 ((PendingIntentRecord)msg.obj).completeFinalize();
1111 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001112 case POST_HEAVY_NOTIFICATION_MSG: {
1113 INotificationManager inm = NotificationManager.getService();
1114 if (inm == null) {
1115 return;
1116 }
1117
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001118 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001119 ProcessRecord process = root.app;
1120 if (process == null) {
1121 return;
1122 }
1123
1124 try {
1125 Context context = mContext.createPackageContext(process.info.packageName, 0);
1126 String text = mContext.getString(R.string.heavy_weight_notification,
1127 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1128 Notification notification = new Notification();
1129 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1130 notification.when = 0;
1131 notification.flags = Notification.FLAG_ONGOING_EVENT;
1132 notification.tickerText = text;
1133 notification.defaults = 0; // please be quiet
1134 notification.sound = null;
1135 notification.vibrate = null;
1136 notification.setLatestEventInfo(context, text,
1137 mContext.getText(R.string.heavy_weight_notification_detail),
1138 PendingIntent.getActivity(mContext, 0, root.intent,
1139 PendingIntent.FLAG_CANCEL_CURRENT));
1140
1141 try {
1142 int[] outId = new int[1];
1143 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1144 notification, outId);
1145 } catch (RuntimeException e) {
1146 Slog.w(ActivityManagerService.TAG,
1147 "Error showing notification for heavy-weight app", e);
1148 } catch (RemoteException e) {
1149 }
1150 } catch (NameNotFoundException e) {
1151 Log.w(TAG, "Unable to create context for heavy notification", e);
1152 }
1153 } break;
1154 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1155 INotificationManager inm = NotificationManager.getService();
1156 if (inm == null) {
1157 return;
1158 }
1159 try {
1160 inm.cancelNotification("android",
1161 R.string.heavy_weight_notification);
1162 } catch (RuntimeException e) {
1163 Slog.w(ActivityManagerService.TAG,
1164 "Error canceling notification for service", e);
1165 } catch (RemoteException e) {
1166 }
1167 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 }
1169 }
1170 };
1171
1172 public static void setSystemProcess() {
1173 try {
1174 ActivityManagerService m = mSelf;
1175
1176 ServiceManager.addService("activity", m);
1177 ServiceManager.addService("meminfo", new MemBinder(m));
1178 if (MONITOR_CPU_USAGE) {
1179 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 ServiceManager.addService("permission", new PermissionController(m));
1182
1183 ApplicationInfo info =
1184 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001185 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001186 mSystemThread.installSystemApplicationInfo(info);
1187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 synchronized (mSelf) {
1189 ProcessRecord app = mSelf.newProcessRecordLocked(
1190 mSystemThread.getApplicationThread(), info,
1191 info.processName);
1192 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001193 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 app.maxAdj = SYSTEM_ADJ;
1195 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1196 synchronized (mSelf.mPidsSelfLocked) {
1197 mSelf.mPidsSelfLocked.put(app.pid, app);
1198 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001199 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 }
1201 } catch (PackageManager.NameNotFoundException e) {
1202 throw new RuntimeException(
1203 "Unable to find android system package", e);
1204 }
1205 }
1206
1207 public void setWindowManager(WindowManagerService wm) {
1208 mWindowManager = wm;
1209 }
1210
1211 public static final Context main(int factoryTest) {
1212 AThread thr = new AThread();
1213 thr.start();
1214
1215 synchronized (thr) {
1216 while (thr.mService == null) {
1217 try {
1218 thr.wait();
1219 } catch (InterruptedException e) {
1220 }
1221 }
1222 }
1223
1224 ActivityManagerService m = thr.mService;
1225 mSelf = m;
1226 ActivityThread at = ActivityThread.systemMain();
1227 mSystemThread = at;
1228 Context context = at.getSystemContext();
1229 m.mContext = context;
1230 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001231 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232
1233 m.mBatteryStatsService.publish(context);
1234 m.mUsageStatsService.publish(context);
1235
1236 synchronized (thr) {
1237 thr.mReady = true;
1238 thr.notifyAll();
1239 }
1240
1241 m.startRunning(null, null, null, null);
1242
1243 return context;
1244 }
1245
1246 public static ActivityManagerService self() {
1247 return mSelf;
1248 }
1249
1250 static class AThread extends Thread {
1251 ActivityManagerService mService;
1252 boolean mReady = false;
1253
1254 public AThread() {
1255 super("ActivityManager");
1256 }
1257
1258 public void run() {
1259 Looper.prepare();
1260
1261 android.os.Process.setThreadPriority(
1262 android.os.Process.THREAD_PRIORITY_FOREGROUND);
1263
1264 ActivityManagerService m = new ActivityManagerService();
1265
1266 synchronized (this) {
1267 mService = m;
1268 notifyAll();
1269 }
1270
1271 synchronized (this) {
1272 while (!mReady) {
1273 try {
1274 wait();
1275 } catch (InterruptedException e) {
1276 }
1277 }
1278 }
1279
1280 Looper.loop();
1281 }
1282 }
1283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 static class MemBinder extends Binder {
1285 ActivityManagerService mActivityManagerService;
1286 MemBinder(ActivityManagerService activityManagerService) {
1287 mActivityManagerService = activityManagerService;
1288 }
1289
1290 @Override
1291 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1292 ActivityManagerService service = mActivityManagerService;
1293 ArrayList<ProcessRecord> procs;
1294 synchronized (mActivityManagerService) {
1295 if (args != null && args.length > 0
1296 && args[0].charAt(0) != '-') {
1297 procs = new ArrayList<ProcessRecord>();
1298 int pid = -1;
1299 try {
1300 pid = Integer.parseInt(args[0]);
1301 } catch (NumberFormatException e) {
1302
1303 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001304 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1305 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 if (proc.pid == pid) {
1307 procs.add(proc);
1308 } else if (proc.processName.equals(args[0])) {
1309 procs.add(proc);
1310 }
1311 }
1312 if (procs.size() <= 0) {
1313 pw.println("No process found for: " + args[0]);
1314 return;
1315 }
1316 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001317 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001318 }
1319 }
1320 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1321 }
1322 }
1323
1324 static class CpuBinder extends Binder {
1325 ActivityManagerService mActivityManagerService;
1326 CpuBinder(ActivityManagerService activityManagerService) {
1327 mActivityManagerService = activityManagerService;
1328 }
1329
1330 @Override
1331 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1332 synchronized (mActivityManagerService.mProcessStatsThread) {
1333 pw.print(mActivityManagerService.mProcessStats.printCurrentState());
1334 }
1335 }
1336 }
1337
1338 private ActivityManagerService() {
1339 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1340 if (v != null && Integer.getInteger(v) != 0) {
1341 mSimpleProcessManagement = true;
1342 }
1343 v = System.getenv("ANDROID_DEBUG_APP");
1344 if (v != null) {
1345 mSimpleProcessManagement = true;
1346 }
1347
Joe Onorato8a9b2202010-02-26 18:56:32 -08001348 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 File dataDir = Environment.getDataDirectory();
1351 File systemDir = new File(dataDir, "system");
1352 systemDir.mkdirs();
1353 mBatteryStatsService = new BatteryStatsService(new File(
1354 systemDir, "batterystats.bin").toString());
1355 mBatteryStatsService.getActiveStatistics().readLocked();
1356 mBatteryStatsService.getActiveStatistics().writeLocked();
1357
1358 mUsageStatsService = new UsageStatsService( new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001359 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360
Jack Palevichb90d28c2009-07-22 15:35:24 -07001361 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1362 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1363
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001364 mConfiguration.setToDefaults();
1365 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 mProcessStats.init();
1367
1368 // Add ourself to the Watchdog monitors.
1369 Watchdog.getInstance().addMonitor(this);
1370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 mProcessStatsThread = new Thread("ProcessStats") {
1372 public void run() {
1373 while (true) {
1374 try {
1375 try {
1376 synchronized(this) {
1377 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001378 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001380 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 // + ", write delay=" + nextWriteDelay);
1382 if (nextWriteDelay < nextCpuDelay) {
1383 nextCpuDelay = nextWriteDelay;
1384 }
1385 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001386 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 this.wait(nextCpuDelay);
1388 }
1389 }
1390 } catch (InterruptedException e) {
1391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 updateCpuStatsNow();
1393 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001394 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 }
1396 }
1397 }
1398 };
1399 mProcessStatsThread.start();
1400 }
1401
1402 @Override
1403 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1404 throws RemoteException {
1405 try {
1406 return super.onTransact(code, data, reply, flags);
1407 } catch (RuntimeException e) {
1408 // The activity manager only throws security exceptions, so let's
1409 // log all others.
1410 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001411 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 }
1413 throw e;
1414 }
1415 }
1416
1417 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001418 final long now = SystemClock.uptimeMillis();
1419 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1420 return;
1421 }
1422 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1423 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 mProcessStatsThread.notify();
1425 }
1426 }
1427 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 void updateCpuStatsNow() {
1430 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001431 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 final long now = SystemClock.uptimeMillis();
1433 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001436 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1437 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 haveNewCpuStats = true;
1439 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001440 //Slog.i(TAG, mProcessStats.printCurrentState());
1441 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 // + mProcessStats.getTotalCpuPercent() + "%");
1443
Joe Onorato8a9b2202010-02-26 18:56:32 -08001444 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 if ("true".equals(SystemProperties.get("events.cpu"))) {
1446 int user = mProcessStats.getLastUserTime();
1447 int system = mProcessStats.getLastSystemTime();
1448 int iowait = mProcessStats.getLastIoWaitTime();
1449 int irq = mProcessStats.getLastIrqTime();
1450 int softIrq = mProcessStats.getLastSoftIrqTime();
1451 int idle = mProcessStats.getLastIdleTime();
1452
1453 int total = user + system + iowait + irq + softIrq + idle;
1454 if (total == 0) total = 1;
1455
Doug Zongker2bec3d42009-12-04 12:52:44 -08001456 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 ((user+system+iowait+irq+softIrq) * 100) / total,
1458 (user * 100) / total,
1459 (system * 100) / total,
1460 (iowait * 100) / total,
1461 (irq * 100) / total,
1462 (softIrq * 100) / total);
1463 }
1464 }
1465
Amith Yamasanie43530a2009-08-21 13:11:37 -07001466 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001467 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001468 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 synchronized(mPidsSelfLocked) {
1470 if (haveNewCpuStats) {
1471 if (mBatteryStatsService.isOnBattery()) {
1472 final int N = mProcessStats.countWorkingStats();
1473 for (int i=0; i<N; i++) {
1474 ProcessStats.Stats st
1475 = mProcessStats.getWorkingStats(i);
1476 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
1477 if (pr != null) {
1478 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
1479 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001480 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001481 } else {
1482 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001483 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001484 if (ps != null) {
1485 ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001486 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 }
1489 }
1490 }
1491 }
1492 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1495 mLastWriteTime = now;
1496 mBatteryStatsService.getActiveStatistics().writeLocked();
1497 }
1498 }
1499 }
1500 }
1501
1502 /**
1503 * Initialize the application bind args. These are passed to each
1504 * process when the bindApplication() IPC is sent to the process. They're
1505 * lazily setup to make sure the services are running when they're asked for.
1506 */
1507 private HashMap<String, IBinder> getCommonServicesLocked() {
1508 if (mAppBindArgs == null) {
1509 mAppBindArgs = new HashMap<String, IBinder>();
1510
1511 // Setup the application init args
1512 mAppBindArgs.put("package", ServiceManager.getService("package"));
1513 mAppBindArgs.put("window", ServiceManager.getService("window"));
1514 mAppBindArgs.put(Context.ALARM_SERVICE,
1515 ServiceManager.getService(Context.ALARM_SERVICE));
1516 }
1517 return mAppBindArgs;
1518 }
1519
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001520 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 if (mFocusedActivity != r) {
1522 mFocusedActivity = r;
1523 mWindowManager.setFocusedApp(r, true);
1524 }
1525 }
1526
Dianne Hackborn906497c2010-05-10 15:57:38 -07001527 private final void updateLruProcessInternalLocked(ProcessRecord app,
1528 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001530 int lrui = mLruProcesses.indexOf(app);
1531 if (lrui >= 0) mLruProcesses.remove(lrui);
1532
1533 int i = mLruProcesses.size()-1;
1534 int skipTop = 0;
1535
Dianne Hackborn906497c2010-05-10 15:57:38 -07001536 app.lruSeq = mLruSeq;
1537
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001538 // compute the new weight for this process.
1539 if (updateActivityTime) {
1540 app.lastActivityTime = SystemClock.uptimeMillis();
1541 }
1542 if (app.activities.size() > 0) {
1543 // If this process has activities, we more strongly want to keep
1544 // it around.
1545 app.lruWeight = app.lastActivityTime;
1546 } else if (app.pubProviders.size() > 0) {
1547 // If this process contains content providers, we want to keep
1548 // it a little more strongly.
1549 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1550 // Also don't let it kick out the first few "real" hidden processes.
1551 skipTop = MIN_HIDDEN_APPS;
1552 } else {
1553 // If this process doesn't have activities, we less strongly
1554 // want to keep it around, and generally want to avoid getting
1555 // in front of any very recently used activities.
1556 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1557 // Also don't let it kick out the first few "real" hidden processes.
1558 skipTop = MIN_HIDDEN_APPS;
1559 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001560
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001561 while (i >= 0) {
1562 ProcessRecord p = mLruProcesses.get(i);
1563 // If this app shouldn't be in front of the first N background
1564 // apps, then skip over that many that are currently hidden.
1565 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1566 skipTop--;
1567 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001568 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001569 mLruProcesses.add(i+1, app);
1570 break;
1571 }
1572 i--;
1573 }
1574 if (i < 0) {
1575 mLruProcesses.add(0, app);
1576 }
1577
Dianne Hackborn906497c2010-05-10 15:57:38 -07001578 // If the app is currently using a content provider or service,
1579 // bump those processes as well.
1580 if (app.connections.size() > 0) {
1581 for (ConnectionRecord cr : app.connections) {
1582 if (cr.binding != null && cr.binding.service != null
1583 && cr.binding.service.app != null
1584 && cr.binding.service.app.lruSeq != mLruSeq) {
1585 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1586 updateActivityTime, i+1);
1587 }
1588 }
1589 }
1590 if (app.conProviders.size() > 0) {
1591 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1592 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1593 updateLruProcessInternalLocked(cpr.app, oomAdj,
1594 updateActivityTime, i+1);
1595 }
1596 }
1597 }
1598
Joe Onorato8a9b2202010-02-26 18:56:32 -08001599 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 if (oomAdj) {
1601 updateOomAdjLocked();
1602 }
1603 }
1604
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001605 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001606 boolean oomAdj, boolean updateActivityTime) {
1607 mLruSeq++;
1608 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1609 }
1610
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001611 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 String processName, int uid) {
1613 if (uid == Process.SYSTEM_UID) {
1614 // The system gets to run in any process. If there are multiple
1615 // processes with the same uid, just pick the first (this
1616 // should never happen).
1617 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1618 processName);
1619 return procs != null ? procs.valueAt(0) : null;
1620 }
1621 ProcessRecord proc = mProcessNames.get(processName, uid);
1622 return proc;
1623 }
1624
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001625 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001626 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001627 try {
1628 if (pm.performDexOpt(packageName)) {
1629 mDidDexOpt = true;
1630 }
1631 } catch (RemoteException e) {
1632 }
1633 }
1634
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001635 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 int transit = mWindowManager.getPendingAppTransition();
1637 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1638 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1639 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1640 }
1641
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001642 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001644 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1646 // We don't have to do anything more if:
1647 // (1) There is an existing application record; and
1648 // (2) The caller doesn't think it is dead, OR there is no thread
1649 // object attached to it so we know it couldn't have crashed; and
1650 // (3) There is a pid assigned to it, so it is either starting or
1651 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001652 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 + " app=" + app + " knownToBeDead=" + knownToBeDead
1654 + " thread=" + (app != null ? app.thread : null)
1655 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001656 if (app != null && app.pid > 0) {
1657 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001658 // We already have the app running, or are waiting for it to
1659 // come up (we have a pid but not yet its thread), so keep it.
Magnus Edlund7bb25812010-02-24 15:45:06 +01001660 return app;
1661 } else {
1662 // An application record is attached to a previous process,
1663 // clean it up now.
1664 handleAppDiedLocked(app, true);
1665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 String hostingNameStr = hostingName != null
1669 ? hostingName.flattenToShortString() : null;
1670
1671 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1672 // If we are in the background, then check to see if this process
1673 // is bad. If so, we will just silently fail.
1674 if (mBadProcesses.get(info.processName, info.uid) != null) {
1675 return null;
1676 }
1677 } else {
1678 // When the user is explicitly starting a process, then clear its
1679 // crash count so that we won't make it bad until they see at
1680 // least one crash dialog again, and make the process good again
1681 // if it had been bad.
1682 mProcessCrashTimes.remove(info.processName, info.uid);
1683 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001684 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 info.processName);
1686 mBadProcesses.remove(info.processName, info.uid);
1687 if (app != null) {
1688 app.bad = false;
1689 }
1690 }
1691 }
1692
1693 if (app == null) {
1694 app = newProcessRecordLocked(null, info, processName);
1695 mProcessNames.put(processName, info.uid, app);
1696 } else {
1697 // If this is a new package in the process, add the package to the list
1698 app.addPackage(info.packageName);
1699 }
1700
1701 // If the system is not ready yet, then hold off on starting this
1702 // process until it is.
1703 if (!mSystemReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001704 && !isAllowedWhileBooting(info)
1705 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 if (!mProcessesOnHold.contains(app)) {
1707 mProcessesOnHold.add(app);
1708 }
1709 return app;
1710 }
1711
1712 startProcessLocked(app, hostingType, hostingNameStr);
1713 return (app.pid != 0) ? app : null;
1714 }
1715
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001716 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1717 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1718 }
1719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 private final void startProcessLocked(ProcessRecord app,
1721 String hostingType, String hostingNameStr) {
1722 if (app.pid > 0 && app.pid != MY_PID) {
1723 synchronized (mPidsSelfLocked) {
1724 mPidsSelfLocked.remove(app.pid);
1725 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1726 }
1727 app.pid = 0;
1728 }
1729
1730 mProcessesOnHold.remove(app);
1731
1732 updateCpuStats();
1733
1734 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1735 mProcDeaths[0] = 0;
1736
1737 try {
1738 int uid = app.info.uid;
1739 int[] gids = null;
1740 try {
1741 gids = mContext.getPackageManager().getPackageGids(
1742 app.info.packageName);
1743 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001744 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 }
1746 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1747 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1748 && mTopComponent != null
1749 && app.processName.equals(mTopComponent.getPackageName())) {
1750 uid = 0;
1751 }
1752 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1753 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1754 uid = 0;
1755 }
1756 }
1757 int debugFlags = 0;
1758 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1759 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1760 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001761 // Run the app in safe mode if its manifest requests so or the
1762 // system is booted in safe mode.
1763 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1764 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001765 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1768 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1769 }
1770 if ("1".equals(SystemProperties.get("debug.assert"))) {
1771 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1772 }
1773 int pid = Process.start("android.app.ActivityThread",
1774 mSimpleProcessManagement ? app.processName : null, uid, uid,
1775 gids, debugFlags, null);
1776 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1777 synchronized (bs) {
1778 if (bs.isOnBattery()) {
1779 app.batteryStats.incStartsLocked();
1780 }
1781 }
1782
Doug Zongker2bec3d42009-12-04 12:52:44 -08001783 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 app.processName, hostingType,
1785 hostingNameStr != null ? hostingNameStr : "");
1786
1787 if (app.persistent) {
1788 Watchdog.getInstance().processStarted(app, app.processName, pid);
1789 }
1790
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001791 StringBuilder buf = mStringBuilder;
1792 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 buf.append("Start proc ");
1794 buf.append(app.processName);
1795 buf.append(" for ");
1796 buf.append(hostingType);
1797 if (hostingNameStr != null) {
1798 buf.append(" ");
1799 buf.append(hostingNameStr);
1800 }
1801 buf.append(": pid=");
1802 buf.append(pid);
1803 buf.append(" uid=");
1804 buf.append(uid);
1805 buf.append(" gids={");
1806 if (gids != null) {
1807 for (int gi=0; gi<gids.length; gi++) {
1808 if (gi != 0) buf.append(", ");
1809 buf.append(gids[gi]);
1810
1811 }
1812 }
1813 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001814 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001815 if (pid == 0 || pid == MY_PID) {
1816 // Processes are being emulated with threads.
1817 app.pid = MY_PID;
1818 app.removed = false;
1819 mStartingProcesses.add(app);
1820 } else if (pid > 0) {
1821 app.pid = pid;
1822 app.removed = false;
1823 synchronized (mPidsSelfLocked) {
1824 this.mPidsSelfLocked.put(pid, app);
1825 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1826 msg.obj = app;
1827 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1828 }
1829 } else {
1830 app.pid = 0;
1831 RuntimeException e = new RuntimeException(
1832 "Failure starting process " + app.processName
1833 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001834 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 }
1836 } catch (RuntimeException e) {
1837 // XXX do better error recovery.
1838 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001839 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 }
1841 }
1842
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001843 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 if (resumed) {
1845 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1846 } else {
1847 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1848 }
1849 }
1850
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001851 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001852 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1853 && mTopAction == null) {
1854 // We are running in factory test mode, but unable to find
1855 // the factory test app, so just sit around displaying the
1856 // error message and don't try to start anything.
1857 return false;
1858 }
1859 Intent intent = new Intent(
1860 mTopAction,
1861 mTopData != null ? Uri.parse(mTopData) : null);
1862 intent.setComponent(mTopComponent);
1863 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1864 intent.addCategory(Intent.CATEGORY_HOME);
1865 }
1866 ActivityInfo aInfo =
1867 intent.resolveActivityInfo(mContext.getPackageManager(),
1868 STOCK_PM_FLAGS);
1869 if (aInfo != null) {
1870 intent.setComponent(new ComponentName(
1871 aInfo.applicationInfo.packageName, aInfo.name));
1872 // Don't do this if the home app is currently being
1873 // instrumented.
1874 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1875 aInfo.applicationInfo.uid);
1876 if (app == null || app.instrumentationClass == null) {
1877 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001878 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001879 null, null, 0, 0, 0, false, false);
1880 }
1881 }
1882
1883
1884 return true;
1885 }
1886
1887 /**
1888 * Starts the "new version setup screen" if appropriate.
1889 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001890 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001891 // Only do this once per boot.
1892 if (mCheckedForSetup) {
1893 return;
1894 }
1895
1896 // We will show this screen if the current one is a different
1897 // version than the last one shown, and we are not running in
1898 // low-level factory test mode.
1899 final ContentResolver resolver = mContext.getContentResolver();
1900 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1901 Settings.Secure.getInt(resolver,
1902 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1903 mCheckedForSetup = true;
1904
1905 // See if we should be showing the platform update setup UI.
1906 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1907 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1908 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1909
1910 // We don't allow third party apps to replace this.
1911 ResolveInfo ri = null;
1912 for (int i=0; ris != null && i<ris.size(); i++) {
1913 if ((ris.get(i).activityInfo.applicationInfo.flags
1914 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1915 ri = ris.get(i);
1916 break;
1917 }
1918 }
1919
1920 if (ri != null) {
1921 String vers = ri.activityInfo.metaData != null
1922 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1923 : null;
1924 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
1925 vers = ri.activityInfo.applicationInfo.metaData.getString(
1926 Intent.METADATA_SETUP_VERSION);
1927 }
1928 String lastVers = Settings.Secure.getString(
1929 resolver, Settings.Secure.LAST_SETUP_SHOWN);
1930 if (vers != null && !vers.equals(lastVers)) {
1931 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1932 intent.setComponent(new ComponentName(
1933 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001934 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001935 null, null, 0, 0, 0, false, false);
1936 }
1937 }
1938 }
1939 }
1940
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001941 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001942 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07001943
1944 final int identHash = System.identityHashCode(r);
1945 updateUsageStats(r, true);
1946
1947 int i = mWatchers.beginBroadcast();
1948 while (i > 0) {
1949 i--;
1950 IActivityWatcher w = mWatchers.getBroadcastItem(i);
1951 if (w != null) {
1952 try {
1953 w.activityResuming(identHash);
1954 } catch (RemoteException e) {
1955 }
1956 }
1957 }
1958 mWatchers.finishBroadcast();
1959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001961 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001962 final int N = mPendingActivityLaunches.size();
1963 if (N <= 0) {
1964 return;
1965 }
1966 for (int i=0; i<N; i++) {
1967 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001968 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001969 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
1970 doResume && i == (N-1));
1971 }
1972 mPendingActivityLaunches.clear();
1973 }
1974
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001975 public final int startActivity(IApplicationThread caller,
1976 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1977 int grantedMode, IBinder resultTo,
1978 String resultWho, int requestCode, boolean onlyIfNeeded,
1979 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001980 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07001981 grantedUriPermissions, grantedMode, resultTo, resultWho,
1982 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001983 }
1984
1985 public final WaitResult startActivityAndWait(IApplicationThread caller,
1986 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1987 int grantedMode, IBinder resultTo,
1988 String resultWho, int requestCode, boolean onlyIfNeeded,
1989 boolean debug) {
1990 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001991 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07001992 grantedUriPermissions, grantedMode, resultTo, resultWho,
1993 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08001994 return res;
1995 }
1996
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07001997 public final int startActivityWithConfig(IApplicationThread caller,
1998 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
1999 int grantedMode, IBinder resultTo,
2000 String resultWho, int requestCode, boolean onlyIfNeeded,
2001 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002002 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002003 grantedUriPermissions, grantedMode, resultTo, resultWho,
2004 requestCode, onlyIfNeeded, debug, null, config);
2005 }
2006
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002007 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002008 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002009 IBinder resultTo, String resultWho, int requestCode,
2010 int flagsMask, int flagsValues) {
2011 // Refuse possible leaked file descriptors
2012 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2013 throw new IllegalArgumentException("File descriptors passed in Intent");
2014 }
2015
2016 IIntentSender sender = intent.getTarget();
2017 if (!(sender instanceof PendingIntentRecord)) {
2018 throw new IllegalArgumentException("Bad PendingIntent object");
2019 }
2020
2021 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002022
2023 synchronized (this) {
2024 // If this is coming from the currently resumed activity, it is
2025 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002026 if (mMainStack.mResumedActivity != null
2027 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002028 Binder.getCallingUid()) {
2029 mAppSwitchesAllowedTime = 0;
2030 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002031 }
2032
2033 return pir.sendInner(0, fillInIntent, resolvedType,
2034 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2035 }
2036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 public boolean startNextMatchingActivity(IBinder callingActivity,
2038 Intent intent) {
2039 // Refuse possible leaked file descriptors
2040 if (intent != null && intent.hasFileDescriptors() == true) {
2041 throw new IllegalArgumentException("File descriptors passed in Intent");
2042 }
2043
2044 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002045 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 if (index < 0) {
2047 return false;
2048 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002049 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 if (r.app == null || r.app.thread == null) {
2051 // The caller is not running... d'oh!
2052 return false;
2053 }
2054 intent = new Intent(intent);
2055 // The caller is not allowed to change the data.
2056 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2057 // And we are resetting to find the next component...
2058 intent.setComponent(null);
2059
2060 ActivityInfo aInfo = null;
2061 try {
2062 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002063 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002065 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066
2067 // Look for the original activity in the list...
2068 final int N = resolves != null ? resolves.size() : 0;
2069 for (int i=0; i<N; i++) {
2070 ResolveInfo rInfo = resolves.get(i);
2071 if (rInfo.activityInfo.packageName.equals(r.packageName)
2072 && rInfo.activityInfo.name.equals(r.info.name)) {
2073 // We found the current one... the next matching is
2074 // after it.
2075 i++;
2076 if (i<N) {
2077 aInfo = resolves.get(i).activityInfo;
2078 }
2079 break;
2080 }
2081 }
2082 } catch (RemoteException e) {
2083 }
2084
2085 if (aInfo == null) {
2086 // Nobody who is next!
2087 return false;
2088 }
2089
2090 intent.setComponent(new ComponentName(
2091 aInfo.applicationInfo.packageName, aInfo.name));
2092 intent.setFlags(intent.getFlags()&~(
2093 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2094 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2095 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2096 Intent.FLAG_ACTIVITY_NEW_TASK));
2097
2098 // Okay now we need to start the new activity, replacing the
2099 // currently running activity. This is a little tricky because
2100 // we want to start the new one as if the current one is finished,
2101 // but not finish the current one first so that there is no flicker.
2102 // And thus...
2103 final boolean wasFinishing = r.finishing;
2104 r.finishing = true;
2105
2106 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002107 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002108 final String resultWho = r.resultWho;
2109 final int requestCode = r.requestCode;
2110 r.resultTo = null;
2111 if (resultTo != null) {
2112 resultTo.removeResultsLocked(r, resultWho, requestCode);
2113 }
2114
2115 final long origId = Binder.clearCallingIdentity();
2116 // XXX we are not dealing with propagating grantedUriPermissions...
2117 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002118 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002119 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002120 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 Binder.restoreCallingIdentity(origId);
2122
2123 r.finishing = wasFinishing;
2124 if (res != START_SUCCESS) {
2125 return false;
2126 }
2127 return true;
2128 }
2129 }
2130
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002131 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 Intent intent, String resolvedType, IBinder resultTo,
2133 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002134
2135 // This is so super not safe, that only the system (or okay root)
2136 // can do it.
2137 final int callingUid = Binder.getCallingUid();
2138 if (callingUid != 0 && callingUid != Process.myUid()) {
2139 throw new SecurityException(
2140 "startActivityInPackage only available to the system");
2141 }
2142
The Android Open Source Project4df24232009-03-05 14:34:35 -08002143 final boolean componentSpecified = intent.getComponent() != null;
2144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 // Don't modify the client's object!
2146 intent = new Intent(intent);
2147
2148 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 ActivityInfo aInfo;
2150 try {
2151 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002152 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002154 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 aInfo = rInfo != null ? rInfo.activityInfo : null;
2156 } catch (RemoteException e) {
2157 aInfo = null;
2158 }
2159
2160 if (aInfo != null) {
2161 // Store the found target back into the intent, because now that
2162 // we have it we never want to do this again. For example, if the
2163 // user navigates back to this point in the history, we should
2164 // always restart the exact same activity.
2165 intent.setComponent(new ComponentName(
2166 aInfo.applicationInfo.packageName, aInfo.name));
2167 }
2168
2169 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002170 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002172 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 }
2174 }
2175
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002176 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 // Remove any existing entries that are the same kind of task.
2178 int N = mRecentTasks.size();
2179 for (int i=0; i<N; i++) {
2180 TaskRecord tr = mRecentTasks.get(i);
2181 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2182 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2183 mRecentTasks.remove(i);
2184 i--;
2185 N--;
2186 if (task.intent == null) {
2187 // If the new recent task we are adding is not fully
2188 // specified, then replace it with the existing recent task.
2189 task = tr;
2190 }
2191 }
2192 }
2193 if (N >= MAX_RECENT_TASKS) {
2194 mRecentTasks.remove(N-1);
2195 }
2196 mRecentTasks.add(0, task);
2197 }
2198
2199 public void setRequestedOrientation(IBinder token,
2200 int requestedOrientation) {
2201 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002202 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 if (index < 0) {
2204 return;
2205 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002206 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 final long origId = Binder.clearCallingIdentity();
2208 mWindowManager.setAppOrientation(r, requestedOrientation);
2209 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002210 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 r.mayFreezeScreenLocked(r.app) ? r : null);
2212 if (config != null) {
2213 r.frozenBeforeDestroy = true;
2214 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002215 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 }
2217 }
2218 Binder.restoreCallingIdentity(origId);
2219 }
2220 }
2221
2222 public int getRequestedOrientation(IBinder token) {
2223 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002224 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225 if (index < 0) {
2226 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2227 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002228 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002229 return mWindowManager.getAppOrientation(r);
2230 }
2231 }
2232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 /**
2234 * This is the internal entry point for handling Activity.finish().
2235 *
2236 * @param token The Binder token referencing the Activity we want to finish.
2237 * @param resultCode Result code, if any, from this Activity.
2238 * @param resultData Result data (Intent), if any, from this Activity.
2239 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002240 * @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 -08002241 */
2242 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2243 // Refuse possible leaked file descriptors
2244 if (resultData != null && resultData.hasFileDescriptors() == true) {
2245 throw new IllegalArgumentException("File descriptors passed in Intent");
2246 }
2247
2248 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002249 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002251 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 if (next != null) {
2253 // ask watcher if this is allowed
2254 boolean resumeOK = true;
2255 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002256 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002258 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 }
2260
2261 if (!resumeOK) {
2262 return false;
2263 }
2264 }
2265 }
2266 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002267 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 resultData, "app-request");
2269 Binder.restoreCallingIdentity(origId);
2270 return res;
2271 }
2272 }
2273
Dianne Hackborn860755f2010-06-03 18:47:52 -07002274 public final void finishHeavyWeightApp() {
2275 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2276 != PackageManager.PERMISSION_GRANTED) {
2277 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2278 + Binder.getCallingPid()
2279 + ", uid=" + Binder.getCallingUid()
2280 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2281 Slog.w(TAG, msg);
2282 throw new SecurityException(msg);
2283 }
2284
2285 synchronized(this) {
2286 if (mHeavyWeightProcess == null) {
2287 return;
2288 }
2289
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002290 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002291 mHeavyWeightProcess.activities);
2292 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002293 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002294 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002295 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002296 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002297 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002298 null, "finish-heavy");
2299 }
2300 }
2301 }
2302
2303 mHeavyWeightProcess = null;
2304 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2305 }
2306 }
2307
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002308 public void crashApplication(int uid, int initialPid, String packageName,
2309 String message) {
2310 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2311 != PackageManager.PERMISSION_GRANTED) {
2312 String msg = "Permission Denial: crashApplication() from pid="
2313 + Binder.getCallingPid()
2314 + ", uid=" + Binder.getCallingUid()
2315 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2316 Slog.w(TAG, msg);
2317 throw new SecurityException(msg);
2318 }
2319
2320 synchronized(this) {
2321 ProcessRecord proc = null;
2322
2323 // Figure out which process to kill. We don't trust that initialPid
2324 // still has any relation to current pids, so must scan through the
2325 // list.
2326 synchronized (mPidsSelfLocked) {
2327 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2328 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2329 if (p.info.uid != uid) {
2330 continue;
2331 }
2332 if (p.pid == initialPid) {
2333 proc = p;
2334 break;
2335 }
2336 for (String str : p.pkgList) {
2337 if (str.equals(packageName)) {
2338 proc = p;
2339 }
2340 }
2341 }
2342 }
2343
2344 if (proc == null) {
2345 Log.w(TAG, "crashApplication: nothing for uid=" + uid
2346 + " initialPid=" + initialPid
2347 + " packageName=" + packageName);
2348 return;
2349 }
2350
2351 if (proc.thread != null) {
2352 long ident = Binder.clearCallingIdentity();
2353 try {
2354 proc.thread.scheduleCrash(message);
2355 } catch (RemoteException e) {
2356 }
2357 Binder.restoreCallingIdentity(ident);
2358 }
2359 }
2360 }
2361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 public final void finishSubActivity(IBinder token, String resultWho,
2363 int requestCode) {
2364 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002365 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 if (index < 0) {
2367 return;
2368 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002369 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370
2371 final long origId = Binder.clearCallingIdentity();
2372
2373 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002374 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2375 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 if (r.resultTo == self && r.requestCode == requestCode) {
2377 if ((r.resultWho == null && resultWho == null) ||
2378 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002379 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 Activity.RESULT_CANCELED, null, "request-sub");
2381 }
2382 }
2383 }
2384
2385 Binder.restoreCallingIdentity(origId);
2386 }
2387 }
2388
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002389 public boolean willActivityBeVisible(IBinder token) {
2390 synchronized(this) {
2391 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002392 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2393 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002394 if (r == token) {
2395 return true;
2396 }
2397 if (r.fullscreen && !r.finishing) {
2398 return false;
2399 }
2400 }
2401 return true;
2402 }
2403 }
2404
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002405 public void overridePendingTransition(IBinder token, String packageName,
2406 int enterAnim, int exitAnim) {
2407 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002408 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002409 if (index < 0) {
2410 return;
2411 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002412 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002413
2414 final long origId = Binder.clearCallingIdentity();
2415
2416 if (self.state == ActivityState.RESUMED
2417 || self.state == ActivityState.PAUSING) {
2418 mWindowManager.overridePendingAppTransition(packageName,
2419 enterAnim, exitAnim);
2420 }
2421
2422 Binder.restoreCallingIdentity(origId);
2423 }
2424 }
2425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002427 * Main function for removing an existing process from the activity manager
2428 * as a result of that process going away. Clears out all connections
2429 * to the process.
2430 */
2431 private final void handleAppDiedLocked(ProcessRecord app,
2432 boolean restarting) {
2433 cleanUpApplicationRecordLocked(app, restarting, -1);
2434 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002435 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 }
2437
2438 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002439 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2440 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2441 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002443 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2444 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 }
2446
2447 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002448 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002449
2450 boolean atTop = true;
2451 boolean hasVisibleActivities = false;
2452
2453 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002454 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002455 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 TAG, "Removing app " + app + " from history with " + i + " entries");
2457 while (i > 0) {
2458 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002459 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002460 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2462 if (r.app == app) {
2463 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002464 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002465 TAG, "Removing this entry! frozen=" + r.haveState
2466 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002467 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468
2469 r.inHistory = false;
2470 mWindowManager.removeAppToken(r);
2471 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002472 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002474 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002475
2476 } else {
2477 // We have the current state for this activity, so
2478 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002479 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002480 TAG, "Keeping entry, setting app to null");
2481 if (r.visible) {
2482 hasVisibleActivities = true;
2483 }
2484 r.app = null;
2485 r.nowVisible = false;
2486 if (!r.haveState) {
2487 r.icicle = null;
2488 }
2489 }
2490
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002491 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 r.state = ActivityState.STOPPED;
2493 }
2494 atTop = false;
2495 }
2496
2497 app.activities.clear();
2498
2499 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002500 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 + " running instrumentation " + app.instrumentationClass);
2502 Bundle info = new Bundle();
2503 info.putString("shortMsg", "Process crashed.");
2504 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2505 }
2506
2507 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002508 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 // If there was nothing to resume, and we are not already
2510 // restarting this process, but there is a visible activity that
2511 // is hosted by the process... then make sure all visible
2512 // activities are running, taking care of restarting this
2513 // process.
2514 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002515 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 }
2517 }
2518 }
2519 }
2520
2521 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2522 IBinder threadBinder = thread.asBinder();
2523
2524 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002525 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2526 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2528 return i;
2529 }
2530 }
2531 return -1;
2532 }
2533
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002534 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 IApplicationThread thread) {
2536 if (thread == null) {
2537 return null;
2538 }
2539
2540 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002541 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002542 }
2543
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002544 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 IApplicationThread thread) {
2546
2547 mProcDeaths[0]++;
2548
Magnus Edlund7bb25812010-02-24 15:45:06 +01002549 // Clean up already done if the process has been re-started.
2550 if (app.pid == pid && app.thread != null &&
2551 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002552 if (!app.killedBackground) {
2553 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2554 + ") has died.");
2555 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002556 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002557 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 TAG, "Dying app: " + app + ", pid: " + pid
2559 + ", thread: " + thread.asBinder());
2560 boolean doLowMem = app.instrumentationClass == null;
2561 handleAppDiedLocked(app, false);
2562
2563 if (doLowMem) {
2564 // If there are no longer any background processes running,
2565 // and the app that died was not running instrumentation,
2566 // then tell everyone we are now low on memory.
2567 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002568 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2569 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2571 haveBg = true;
2572 break;
2573 }
2574 }
2575
2576 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002577 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002578 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002579 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002580 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2581 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002582 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002583 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2584 // The low memory report is overriding any current
2585 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002586 // heavy/important/visible/foreground processes first.
2587 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002588 rec.lastRequestedGc = 0;
2589 } else {
2590 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002592 rec.reportLowMemory = true;
2593 rec.lastLowMemory = now;
2594 mProcessesToGc.remove(rec);
2595 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 }
2597 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002598 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 }
2600 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002601 } else if (app.pid != pid) {
2602 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002603 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002604 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002605 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002606 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002607 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 + thread.asBinder());
2609 }
2610 }
2611
Dan Egnor42471dd2010-01-07 17:25:22 -08002612 /**
2613 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002614 * @param clearTraces causes the dump file to be erased prior to the new
2615 * traces being written, if true; when false, the new traces will be
2616 * appended to any existing file content.
Dan Egnor42471dd2010-01-07 17:25:22 -08002617 * @param pids of dalvik VM processes to dump stack traces for
2618 * @return file containing stack traces, or null if no dump file is configured
2619 */
Christopher Tate6ee412d2010-05-28 12:01:56 -07002620 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> pids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002621 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2622 if (tracesPath == null || tracesPath.length() == 0) {
2623 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002625
2626 File tracesFile = new File(tracesPath);
2627 try {
2628 File tracesDir = tracesFile.getParentFile();
2629 if (!tracesDir.exists()) tracesFile.mkdirs();
2630 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2631
Christopher Tate6ee412d2010-05-28 12:01:56 -07002632 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002633 tracesFile.createNewFile();
2634 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2635 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002636 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002637 return null;
2638 }
2639
2640 // Use a FileObserver to detect when traces finish writing.
2641 // The order of traces is considered important to maintain for legibility.
2642 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2643 public synchronized void onEvent(int event, String path) { notify(); }
2644 };
2645
2646 try {
2647 observer.startWatching();
2648 int num = pids.size();
2649 for (int i = 0; i < num; i++) {
2650 synchronized (observer) {
2651 Process.sendSignal(pids.get(i), Process.SIGNAL_QUIT);
2652 observer.wait(200); // Wait for write-close, give up after 200msec
2653 }
2654 }
2655 } catch (InterruptedException e) {
Joe Onorato5d3bea62010-03-01 13:44:29 -08002656 Log.wtf(TAG, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002657 } finally {
2658 observer.stopWatching();
2659 }
2660
2661 return tracesFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662 }
2663
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002664 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2665 ActivityRecord parent, final String annotation) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002666 ArrayList<Integer> pids = new ArrayList<Integer>(20);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002667
2668 synchronized (this) {
2669 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2670 if (mShuttingDown) {
2671 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2672 return;
2673 } else if (app.notResponding) {
2674 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2675 return;
2676 } else if (app.crashing) {
2677 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2678 return;
2679 }
2680
2681 // In case we come through here for the same app before completing
2682 // this one, mark as anring now so we will bail out.
2683 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002684
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002685 // Log the ANR to the event log.
2686 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2687 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002688
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002689 // Dump thread traces as quickly as we can, starting with "interesting" processes.
2690 pids.add(app.pid);
2691
2692 int parentPid = app.pid;
2693 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
2694 if (parentPid != app.pid) pids.add(parentPid);
2695
2696 if (MY_PID != app.pid && MY_PID != parentPid) pids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002697
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002698 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2699 ProcessRecord r = mLruProcesses.get(i);
2700 if (r != null && r.thread != null) {
2701 int pid = r.pid;
2702 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) pids.add(pid);
2703 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704 }
2705 }
2706
Christopher Tate6ee412d2010-05-28 12:01:56 -07002707 File tracesFile = dumpStackTraces(true, pids);
Dan Egnor42471dd2010-01-07 17:25:22 -08002708
2709 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002710 StringBuilder info = mStringBuilder;
2711 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002712 info.append("ANR in ").append(app.processName);
2713 if (activity != null && activity.shortComponentName != null) {
2714 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002715 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002716 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002718 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002720 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002721 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723
Dan Egnor42471dd2010-01-07 17:25:22 -08002724 String cpuInfo = null;
2725 if (MONITOR_CPU_USAGE) {
2726 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002727 synchronized (mProcessStatsThread) {
2728 cpuInfo = mProcessStats.printCurrentState();
2729 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002730 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 }
2732
Joe Onorato8a9b2202010-02-26 18:56:32 -08002733 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002734 if (tracesFile == null) {
2735 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2736 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2737 }
2738
2739 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2740
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002741 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002743 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2744 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002746 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2747 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 }
2749 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002750 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 }
2752 }
2753
Dan Egnor42471dd2010-01-07 17:25:22 -08002754 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2755 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2756 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002757
2758 synchronized (this) {
2759 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2760 Process.killProcess(app.pid);
2761 return;
2762 }
2763
2764 // Set the app's notResponding state, and look up the errorReportReceiver
2765 makeAppNotRespondingLocked(app,
2766 activity != null ? activity.shortComponentName : null,
2767 annotation != null ? "ANR " + annotation : "ANR",
2768 info.toString());
2769
2770 // Bring up the infamous App Not Responding dialog
2771 Message msg = Message.obtain();
2772 HashMap map = new HashMap();
2773 msg.what = SHOW_NOT_RESPONDING_MSG;
2774 msg.obj = map;
2775 map.put("app", app);
2776 if (activity != null) {
2777 map.put("activity", activity);
2778 }
2779
2780 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002782 }
2783
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002784 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 app.persistentActivities--;
2786 if (app.persistentActivities > 0) {
2787 // Still more of 'em...
2788 return;
2789 }
2790 if (app.persistent) {
2791 // Ah, but the application itself is persistent. Whatever!
2792 return;
2793 }
2794
2795 // App is no longer persistent... make sure it and the ones
2796 // following it in the LRU list have the correc oom_adj.
2797 updateOomAdjLocked();
2798 }
2799
2800 public void setPersistent(IBinder token, boolean isPersistent) {
2801 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2802 != PackageManager.PERMISSION_GRANTED) {
2803 String msg = "Permission Denial: setPersistent() from pid="
2804 + Binder.getCallingPid()
2805 + ", uid=" + Binder.getCallingUid()
2806 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002807 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 throw new SecurityException(msg);
2809 }
2810
2811 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002812 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002813 if (index < 0) {
2814 return;
2815 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002816 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 ProcessRecord app = r.app;
2818
Joe Onorato8a9b2202010-02-26 18:56:32 -08002819 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 TAG, "Setting persistence " + isPersistent + ": " + r);
2821
2822 if (isPersistent) {
2823 if (r.persistent) {
2824 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002825 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 return;
2827 }
2828 r.persistent = true;
2829 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002830 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 if (app.persistentActivities > 1) {
2832 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08002833 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002834 return;
2835 }
2836 if (app.persistent) {
2837 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002838 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002839 return;
2840 }
2841
2842 // App is now persistent... make sure it and the ones
2843 // following it now have the correct oom_adj.
2844 final long origId = Binder.clearCallingIdentity();
2845 updateOomAdjLocked();
2846 Binder.restoreCallingIdentity(origId);
2847
2848 } else {
2849 if (!r.persistent) {
2850 // Okay okay, I heard you already!
2851 return;
2852 }
2853 r.persistent = false;
2854 final long origId = Binder.clearCallingIdentity();
2855 decPersistentCountLocked(app);
2856 Binder.restoreCallingIdentity(origId);
2857
2858 }
2859 }
2860 }
2861
2862 public boolean clearApplicationUserData(final String packageName,
2863 final IPackageDataObserver observer) {
2864 int uid = Binder.getCallingUid();
2865 int pid = Binder.getCallingPid();
2866 long callingId = Binder.clearCallingIdentity();
2867 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002868 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 int pkgUid = -1;
2870 synchronized(this) {
2871 try {
2872 pkgUid = pm.getPackageUid(packageName);
2873 } catch (RemoteException e) {
2874 }
2875 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002876 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002877 return false;
2878 }
2879 if (uid == pkgUid || checkComponentPermission(
2880 android.Manifest.permission.CLEAR_APP_USER_DATA,
2881 pid, uid, -1)
2882 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08002883 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 } else {
2885 throw new SecurityException(pid+" does not have permission:"+
2886 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
2887 "for process:"+packageName);
2888 }
2889 }
2890
2891 try {
2892 //clear application user data
2893 pm.clearApplicationUserData(packageName, observer);
2894 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
2895 Uri.fromParts("package", packageName, null));
2896 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Josh Bartel2ecce342010-02-25 10:55:48 -06002897 synchronized (this) {
2898 broadcastIntentLocked(null, null, intent,
2899 null, null, 0, null, null, null,
2900 false, false, MY_PID, Process.SYSTEM_UID);
2901 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002902 } catch (RemoteException e) {
2903 }
2904 } finally {
2905 Binder.restoreCallingIdentity(callingId);
2906 }
2907 return true;
2908 }
2909
Dianne Hackborn03abb812010-01-04 18:43:19 -08002910 public void killBackgroundProcesses(final String packageName) {
2911 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
2912 != PackageManager.PERMISSION_GRANTED &&
2913 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
2914 != PackageManager.PERMISSION_GRANTED) {
2915 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002916 + Binder.getCallingPid()
2917 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08002918 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002919 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 throw new SecurityException(msg);
2921 }
2922
2923 long callingId = Binder.clearCallingIdentity();
2924 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002925 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002926 int pkgUid = -1;
2927 synchronized(this) {
2928 try {
2929 pkgUid = pm.getPackageUid(packageName);
2930 } catch (RemoteException e) {
2931 }
2932 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002933 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 return;
2935 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08002936 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08002937 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002938 }
2939 } finally {
2940 Binder.restoreCallingIdentity(callingId);
2941 }
2942 }
2943
2944 public void forceStopPackage(final String packageName) {
2945 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2946 != PackageManager.PERMISSION_GRANTED) {
2947 String msg = "Permission Denial: forceStopPackage() from pid="
2948 + Binder.getCallingPid()
2949 + ", uid=" + Binder.getCallingUid()
2950 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002951 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002952 throw new SecurityException(msg);
2953 }
2954
2955 long callingId = Binder.clearCallingIdentity();
2956 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002957 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08002958 int pkgUid = -1;
2959 synchronized(this) {
2960 try {
2961 pkgUid = pm.getPackageUid(packageName);
2962 } catch (RemoteException e) {
2963 }
2964 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002965 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002966 return;
2967 }
2968 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969 }
2970 } finally {
2971 Binder.restoreCallingIdentity(callingId);
2972 }
2973 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002974
2975 /*
2976 * The pkg name and uid have to be specified.
2977 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
2978 */
2979 public void killApplicationWithUid(String pkg, int uid) {
2980 if (pkg == null) {
2981 return;
2982 }
2983 // Make sure the uid is valid.
2984 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002985 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002986 return;
2987 }
2988 int callerUid = Binder.getCallingUid();
2989 // Only the system server can kill an application
2990 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07002991 // Post an aysnc message to kill the application
2992 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
2993 msg.arg1 = uid;
2994 msg.arg2 = 0;
2995 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07002996 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002997 } else {
2998 throw new SecurityException(callerUid + " cannot kill pkg: " +
2999 pkg);
3000 }
3001 }
3002
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003003 public void closeSystemDialogs(String reason) {
3004 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
3005 if (reason != null) {
3006 intent.putExtra("reason", reason);
3007 }
3008
3009 final int uid = Binder.getCallingUid();
3010 final long origId = Binder.clearCallingIdentity();
3011 synchronized (this) {
3012 int i = mWatchers.beginBroadcast();
3013 while (i > 0) {
3014 i--;
3015 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3016 if (w != null) {
3017 try {
3018 w.closingSystemDialogs(reason);
3019 } catch (RemoteException e) {
3020 }
3021 }
3022 }
3023 mWatchers.finishBroadcast();
3024
Dianne Hackbornffa42482009-09-23 22:20:11 -07003025 mWindowManager.closeSystemDialogs(reason);
3026
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003027 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3028 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003029 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003030 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003031 Activity.RESULT_CANCELED, null, "close-sys");
3032 }
3033 }
3034
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003035 broadcastIntentLocked(null, null, intent, null,
3036 null, 0, null, null, null, false, false, -1, uid);
3037 }
3038 Binder.restoreCallingIdentity(origId);
3039 }
3040
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003041 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003042 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003043 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3044 for (int i=pids.length-1; i>=0; i--) {
3045 infos[i] = new Debug.MemoryInfo();
3046 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003047 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003048 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003049 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003050
3051 public void killApplicationProcess(String processName, int uid) {
3052 if (processName == null) {
3053 return;
3054 }
3055
3056 int callerUid = Binder.getCallingUid();
3057 // Only the system server can kill an application
3058 if (callerUid == Process.SYSTEM_UID) {
3059 synchronized (this) {
3060 ProcessRecord app = getProcessRecordLocked(processName, uid);
3061 if (app != null) {
3062 try {
3063 app.thread.scheduleSuicide();
3064 } catch (RemoteException e) {
3065 // If the other end already died, then our work here is done.
3066 }
3067 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003068 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003069 + processName + " / " + uid);
3070 }
3071 }
3072 } else {
3073 throw new SecurityException(callerUid + " cannot kill app process: " +
3074 processName);
3075 }
3076 }
3077
Dianne Hackborn03abb812010-01-04 18:43:19 -08003078 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003079 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3081 Uri.fromParts("package", packageName, null));
3082 intent.putExtra(Intent.EXTRA_UID, uid);
3083 broadcastIntentLocked(null, null, intent,
3084 null, null, 0, null, null, null,
3085 false, false, MY_PID, Process.SYSTEM_UID);
3086 }
3087
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003088 private final boolean killPackageProcessesLocked(String packageName, int uid,
3089 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003090 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091
Dianne Hackborn03abb812010-01-04 18:43:19 -08003092 // Remove all processes this package may have touched: all with the
3093 // same UID (except for the system or root user), and all whose name
3094 // matches the package name.
3095 final String procNamePrefix = packageName + ":";
3096 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3097 final int NA = apps.size();
3098 for (int ia=0; ia<NA; ia++) {
3099 ProcessRecord app = apps.valueAt(ia);
3100 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003101 if (doit) {
3102 procs.add(app);
3103 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003104 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3105 || app.processName.equals(packageName)
3106 || app.processName.startsWith(procNamePrefix)) {
3107 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003108 if (!doit) {
3109 return true;
3110 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003111 app.removed = true;
3112 procs.add(app);
3113 }
3114 }
3115 }
3116 }
3117
3118 int N = procs.size();
3119 for (int i=0; i<N; i++) {
3120 removeProcessLocked(procs.get(i), callerWillRestart);
3121 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003122 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003123 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003124
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003125 private final boolean forceStopPackageLocked(String name, int uid,
3126 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 int i, N;
3128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003129 if (uid < 0) {
3130 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003131 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 } catch (RemoteException e) {
3133 }
3134 }
3135
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003136 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003137 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003138
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003139 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3140 while (badApps.hasNext()) {
3141 SparseArray<Long> ba = badApps.next();
3142 if (ba.get(uid) != null) {
3143 badApps.remove();
3144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 }
3146 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003147
3148 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3149 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003151 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3152 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003153 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003154 if (!doit) {
3155 return true;
3156 }
3157 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003158 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003159 if (r.app != null) {
3160 r.app.removed = true;
3161 }
3162 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003163 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 }
3165 }
3166
3167 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3168 for (ServiceRecord service : mServices.values()) {
3169 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003170 if (!doit) {
3171 return true;
3172 }
3173 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003174 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 if (service.app != null) {
3176 service.app.removed = true;
3177 }
3178 service.app = null;
3179 services.add(service);
3180 }
3181 }
3182
3183 N = services.size();
3184 for (i=0; i<N; i++) {
3185 bringDownServiceLocked(services.get(i), true);
3186 }
3187
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003188 if (doit) {
3189 if (purgeCache) {
3190 AttributeCache ac = AttributeCache.instance();
3191 if (ac != null) {
3192 ac.removePackage(name);
3193 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003194 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003195 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003196 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003197
3198 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199 }
3200
3201 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3202 final String name = app.processName;
3203 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003204 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 TAG, "Force removing process " + app + " (" + name
3206 + "/" + uid + ")");
3207
3208 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003209 if (mHeavyWeightProcess == app) {
3210 mHeavyWeightProcess = null;
3211 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 boolean needRestart = false;
3214 if (app.pid > 0 && app.pid != MY_PID) {
3215 int pid = app.pid;
3216 synchronized (mPidsSelfLocked) {
3217 mPidsSelfLocked.remove(pid);
3218 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3219 }
3220 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003221 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 Process.killProcess(pid);
3223
3224 if (app.persistent) {
3225 if (!callerWillRestart) {
3226 addAppLocked(app.info);
3227 } else {
3228 needRestart = true;
3229 }
3230 }
3231 } else {
3232 mRemovedProcesses.add(app);
3233 }
3234
3235 return needRestart;
3236 }
3237
3238 private final void processStartTimedOutLocked(ProcessRecord app) {
3239 final int pid = app.pid;
3240 boolean gone = false;
3241 synchronized (mPidsSelfLocked) {
3242 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3243 if (knownApp != null && knownApp.thread == null) {
3244 mPidsSelfLocked.remove(pid);
3245 gone = true;
3246 }
3247 }
3248
3249 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003250 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003251 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003252 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003254 if (mHeavyWeightProcess == app) {
3255 mHeavyWeightProcess = null;
3256 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3257 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003258 // Take care of any launching providers waiting for this process.
3259 checkAppInLaunchingProvidersLocked(app, true);
3260 // Take care of any services that are waiting for the process.
3261 for (int i=0; i<mPendingServices.size(); i++) {
3262 ServiceRecord sr = mPendingServices.get(i);
3263 if (app.info.uid == sr.appInfo.uid
3264 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003265 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003266 mPendingServices.remove(i);
3267 i--;
3268 bringDownServiceLocked(sr, true);
3269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003271 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003272 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003273 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003274 try {
3275 IBackupManager bm = IBackupManager.Stub.asInterface(
3276 ServiceManager.getService(Context.BACKUP_SERVICE));
3277 bm.agentDisconnected(app.info.packageName);
3278 } catch (RemoteException e) {
3279 // Can't happen; the backup manager is local
3280 }
3281 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003282 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003283 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003284 mPendingBroadcast = null;
3285 scheduleBroadcastsLocked();
3286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003288 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 }
3290 }
3291
3292 private final boolean attachApplicationLocked(IApplicationThread thread,
3293 int pid) {
3294
3295 // Find the application record that is being attached... either via
3296 // the pid if we are running in multiple processes, or just pull the
3297 // next app record if we are emulating process with anonymous threads.
3298 ProcessRecord app;
3299 if (pid != MY_PID && pid >= 0) {
3300 synchronized (mPidsSelfLocked) {
3301 app = mPidsSelfLocked.get(pid);
3302 }
3303 } else if (mStartingProcesses.size() > 0) {
3304 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003305 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 } else {
3307 app = null;
3308 }
3309
3310 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003311 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003313 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 if (pid > 0 && pid != MY_PID) {
3315 Process.killProcess(pid);
3316 } else {
3317 try {
3318 thread.scheduleExit();
3319 } catch (Exception e) {
3320 // Ignore exceptions.
3321 }
3322 }
3323 return false;
3324 }
3325
3326 // If this application record is still attached to a previous
3327 // process, clean it up now.
3328 if (app.thread != null) {
3329 handleAppDiedLocked(app, true);
3330 }
3331
3332 // Tell the process all about itself.
3333
Joe Onorato8a9b2202010-02-26 18:56:32 -08003334 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 TAG, "Binding process pid " + pid + " to record " + app);
3336
3337 String processName = app.processName;
3338 try {
3339 thread.asBinder().linkToDeath(new AppDeathRecipient(
3340 app, pid, thread), 0);
3341 } catch (RemoteException e) {
3342 app.resetPackageList();
3343 startProcessLocked(app, "link fail", processName);
3344 return false;
3345 }
3346
Doug Zongker2bec3d42009-12-04 12:52:44 -08003347 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348
3349 app.thread = thread;
3350 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003351 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3352 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 app.forcingToForeground = null;
3354 app.foregroundServices = false;
3355 app.debugging = false;
3356
3357 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3358
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003359 boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
3360 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003361
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003362 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003363 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003364 }
3365
Joe Onorato8a9b2202010-02-26 18:56:32 -08003366 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 TAG, "New app record " + app
3368 + " thread=" + thread.asBinder() + " pid=" + pid);
3369 try {
3370 int testMode = IApplicationThread.DEBUG_OFF;
3371 if (mDebugApp != null && mDebugApp.equals(processName)) {
3372 testMode = mWaitForDebugger
3373 ? IApplicationThread.DEBUG_WAIT
3374 : IApplicationThread.DEBUG_ON;
3375 app.debugging = true;
3376 if (mDebugTransient) {
3377 mDebugApp = mOrigDebugApp;
3378 mWaitForDebugger = mOrigWaitForDebugger;
3379 }
3380 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003381
Christopher Tate181fafa2009-05-14 11:12:14 -07003382 // If the app is being launched for restore or full backup, set it up specially
3383 boolean isRestrictedBackupMode = false;
3384 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3385 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3386 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3387 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003388
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003389 ensurePackageDexOpt(app.instrumentationInfo != null
3390 ? app.instrumentationInfo.packageName
3391 : app.info.packageName);
3392 if (app.instrumentationClass != null) {
3393 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003394 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003395 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003396 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003397 thread.bindApplication(processName, app.instrumentationInfo != null
3398 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003399 app.instrumentationClass, app.instrumentationProfileFile,
3400 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003401 isRestrictedBackupMode || !normalMode,
3402 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003403 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003404 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 } catch (Exception e) {
3406 // todo: Yikes! What should we do? For now we will try to
3407 // start another process, but that could easily get us in
3408 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003409 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003410
3411 app.resetPackageList();
3412 startProcessLocked(app, "bind fail", processName);
3413 return false;
3414 }
3415
3416 // Remove this record from the list of starting applications.
3417 mPersistentStartingProcesses.remove(app);
3418 mProcessesOnHold.remove(app);
3419
3420 boolean badApp = false;
3421 boolean didSomething = false;
3422
3423 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003424 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003425 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3427 && processName.equals(hr.processName)) {
3428 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003429 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 didSomething = true;
3431 }
3432 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003433 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 + hr.intent.getComponent().flattenToShortString(), e);
3435 badApp = true;
3436 }
3437 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003438 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003439 }
3440 }
3441
3442 // Find any services that should be running in this process...
3443 if (!badApp && mPendingServices.size() > 0) {
3444 ServiceRecord sr = null;
3445 try {
3446 for (int i=0; i<mPendingServices.size(); i++) {
3447 sr = mPendingServices.get(i);
3448 if (app.info.uid != sr.appInfo.uid
3449 || !processName.equals(sr.processName)) {
3450 continue;
3451 }
3452
3453 mPendingServices.remove(i);
3454 i--;
3455 realStartServiceLocked(sr, app);
3456 didSomething = true;
3457 }
3458 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003459 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 + sr.shortName, e);
3461 badApp = true;
3462 }
3463 }
3464
3465 // Check if the next broadcast receiver is in this process...
3466 BroadcastRecord br = mPendingBroadcast;
3467 if (!badApp && br != null && br.curApp == app) {
3468 try {
3469 mPendingBroadcast = null;
3470 processCurBroadcastLocked(br, app);
3471 didSomething = true;
3472 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003473 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003474 + br.curComponent.flattenToShortString(), e);
3475 badApp = true;
3476 logBroadcastReceiverDiscard(br);
3477 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3478 br.resultExtras, br.resultAbort, true);
3479 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003480 // We need to reset the state if we fails to start the receiver.
3481 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482 }
3483 }
3484
Christopher Tate181fafa2009-05-14 11:12:14 -07003485 // Check whether the next backup agent is in this process...
3486 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003487 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003488 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003489 try {
3490 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3491 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003492 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003493 e.printStackTrace();
3494 }
3495 }
3496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 if (badApp) {
3498 // todo: Also need to kill application to deal with all
3499 // kinds of exceptions.
3500 handleAppDiedLocked(app, false);
3501 return false;
3502 }
3503
3504 if (!didSomething) {
3505 updateOomAdjLocked();
3506 }
3507
3508 return true;
3509 }
3510
3511 public final void attachApplication(IApplicationThread thread) {
3512 synchronized (this) {
3513 int callingPid = Binder.getCallingPid();
3514 final long origId = Binder.clearCallingIdentity();
3515 attachApplicationLocked(thread, callingPid);
3516 Binder.restoreCallingIdentity(origId);
3517 }
3518 }
3519
Dianne Hackborne88846e2009-09-30 21:34:25 -07003520 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003522 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 Binder.restoreCallingIdentity(origId);
3524 }
3525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003527 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003528 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 mWindowManager.enableScreenAfterBoot();
3530 }
3531
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003532 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003533 IntentFilter pkgFilter = new IntentFilter();
3534 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3535 pkgFilter.addDataScheme("package");
3536 mContext.registerReceiver(new BroadcastReceiver() {
3537 @Override
3538 public void onReceive(Context context, Intent intent) {
3539 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3540 if (pkgs != null) {
3541 for (String pkg : pkgs) {
3542 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3543 setResultCode(Activity.RESULT_OK);
3544 return;
3545 }
3546 }
3547 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003548 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003549 }, pkgFilter);
3550
3551 synchronized (this) {
3552 // Ensure that any processes we had put on hold are now started
3553 // up.
3554 final int NP = mProcessesOnHold.size();
3555 if (NP > 0) {
3556 ArrayList<ProcessRecord> procs =
3557 new ArrayList<ProcessRecord>(mProcessesOnHold);
3558 for (int ip=0; ip<NP; ip++) {
3559 this.startProcessLocked(procs.get(ip), "on-hold", null);
3560 }
3561 }
3562
3563 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
3564 // Tell anyone interested that we are done booting!
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003565 broadcastIntentLocked(null, null,
3566 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3567 null, null, 0, null, null,
3568 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3569 false, false, MY_PID, Process.SYSTEM_UID);
3570 }
3571 }
3572 }
3573
3574 final void ensureBootCompleted() {
3575 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003576 boolean enableScreen;
3577 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003578 booting = mBooting;
3579 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003580 enableScreen = !mBooted;
3581 mBooted = true;
3582 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003583
3584 if (booting) {
3585 finishBooting();
3586 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003587
3588 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003589 enableScreenAfterBoot();
3590 }
3591 }
3592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 public final void activityPaused(IBinder token, Bundle icicle) {
3594 // Refuse possible leaked file descriptors
3595 if (icicle != null && icicle.hasFileDescriptors()) {
3596 throw new IllegalArgumentException("File descriptors passed in Bundle");
3597 }
3598
3599 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003600 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601 Binder.restoreCallingIdentity(origId);
3602 }
3603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003604 public final void activityStopped(IBinder token, Bitmap thumbnail,
3605 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003606 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 TAG, "Activity stopped: token=" + token);
3608
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003609 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610
3611 final long origId = Binder.clearCallingIdentity();
3612
3613 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003614 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003616 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 r.thumbnail = thumbnail;
3618 r.description = description;
3619 r.stopped = true;
3620 r.state = ActivityState.STOPPED;
3621 if (!r.finishing) {
3622 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003623 r.stack.destroyActivityLocked(r, true);
3624 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625 }
3626 }
3627 }
3628 }
3629
3630 if (r != null) {
3631 sendPendingThumbnail(r, null, null, null, false);
3632 }
3633
3634 trimApplications();
3635
3636 Binder.restoreCallingIdentity(origId);
3637 }
3638
3639 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003640 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003641 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 }
3643
3644 public String getCallingPackage(IBinder token) {
3645 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003646 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003647 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003648 }
3649 }
3650
3651 public ComponentName getCallingActivity(IBinder token) {
3652 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003653 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654 return r != null ? r.intent.getComponent() : null;
3655 }
3656 }
3657
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003658 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003659 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003661 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 if (r != null) {
3663 return r.resultTo;
3664 }
3665 }
3666 return null;
3667 }
3668
3669 public ComponentName getActivityClassForToken(IBinder token) {
3670 synchronized(this) {
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 return r.intent.getComponent();
3675 }
3676 return null;
3677 }
3678 }
3679
3680 public String getPackageForToken(IBinder token) {
3681 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003682 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003684 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 return r.packageName;
3686 }
3687 return null;
3688 }
3689 }
3690
3691 public IIntentSender getIntentSender(int type,
3692 String packageName, IBinder token, String resultWho,
3693 int requestCode, Intent intent, String resolvedType, int flags) {
3694 // Refuse possible leaked file descriptors
3695 if (intent != null && intent.hasFileDescriptors() == true) {
3696 throw new IllegalArgumentException("File descriptors passed in Intent");
3697 }
3698
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003699 if (type == INTENT_SENDER_BROADCAST) {
3700 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3701 throw new IllegalArgumentException(
3702 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3703 }
3704 }
3705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 synchronized(this) {
3707 int callingUid = Binder.getCallingUid();
3708 try {
3709 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3710 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003711 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 .getPackageUid(packageName);
3713 if (uid != Binder.getCallingUid()) {
3714 String msg = "Permission Denial: getIntentSender() from pid="
3715 + Binder.getCallingPid()
3716 + ", uid=" + Binder.getCallingUid()
3717 + ", (need uid=" + uid + ")"
3718 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003719 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 throw new SecurityException(msg);
3721 }
3722 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003723
3724 return getIntentSenderLocked(type, packageName, callingUid,
3725 token, resultWho, requestCode, intent, resolvedType, flags);
3726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003727 } catch (RemoteException e) {
3728 throw new SecurityException(e);
3729 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003730 }
3731 }
3732
3733 IIntentSender getIntentSenderLocked(int type,
3734 String packageName, int callingUid, IBinder token, String resultWho,
3735 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003736 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003737 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003738 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003739 if (index < 0) {
3740 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003742 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003743 if (activity.finishing) {
3744 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003746 }
3747
3748 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3749 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3750 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3751 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3752 |PendingIntent.FLAG_UPDATE_CURRENT);
3753
3754 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3755 type, packageName, activity, resultWho,
3756 requestCode, intent, resolvedType, flags);
3757 WeakReference<PendingIntentRecord> ref;
3758 ref = mIntentSenderRecords.get(key);
3759 PendingIntentRecord rec = ref != null ? ref.get() : null;
3760 if (rec != null) {
3761 if (!cancelCurrent) {
3762 if (updateCurrent) {
3763 rec.key.requestIntent.replaceExtras(intent);
3764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 return rec;
3766 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003767 rec.canceled = true;
3768 mIntentSenderRecords.remove(key);
3769 }
3770 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 return rec;
3772 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003773 rec = new PendingIntentRecord(this, key, callingUid);
3774 mIntentSenderRecords.put(key, rec.ref);
3775 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3776 if (activity.pendingResults == null) {
3777 activity.pendingResults
3778 = new HashSet<WeakReference<PendingIntentRecord>>();
3779 }
3780 activity.pendingResults.add(rec.ref);
3781 }
3782 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 }
3784
3785 public void cancelIntentSender(IIntentSender sender) {
3786 if (!(sender instanceof PendingIntentRecord)) {
3787 return;
3788 }
3789 synchronized(this) {
3790 PendingIntentRecord rec = (PendingIntentRecord)sender;
3791 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003792 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 .getPackageUid(rec.key.packageName);
3794 if (uid != Binder.getCallingUid()) {
3795 String msg = "Permission Denial: cancelIntentSender() from pid="
3796 + Binder.getCallingPid()
3797 + ", uid=" + Binder.getCallingUid()
3798 + " is not allowed to cancel packges "
3799 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003800 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003801 throw new SecurityException(msg);
3802 }
3803 } catch (RemoteException e) {
3804 throw new SecurityException(e);
3805 }
3806 cancelIntentSenderLocked(rec, true);
3807 }
3808 }
3809
3810 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3811 rec.canceled = true;
3812 mIntentSenderRecords.remove(rec.key);
3813 if (cleanActivity && rec.key.activity != null) {
3814 rec.key.activity.pendingResults.remove(rec.ref);
3815 }
3816 }
3817
3818 public String getPackageForIntentSender(IIntentSender pendingResult) {
3819 if (!(pendingResult instanceof PendingIntentRecord)) {
3820 return null;
3821 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003822 try {
3823 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3824 return res.key.packageName;
3825 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 }
3827 return null;
3828 }
3829
3830 public void setProcessLimit(int max) {
3831 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3832 "setProcessLimit()");
3833 mProcessLimit = max;
3834 }
3835
3836 public int getProcessLimit() {
3837 return mProcessLimit;
3838 }
3839
3840 void foregroundTokenDied(ForegroundToken token) {
3841 synchronized (ActivityManagerService.this) {
3842 synchronized (mPidsSelfLocked) {
3843 ForegroundToken cur
3844 = mForegroundProcesses.get(token.pid);
3845 if (cur != token) {
3846 return;
3847 }
3848 mForegroundProcesses.remove(token.pid);
3849 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3850 if (pr == null) {
3851 return;
3852 }
3853 pr.forcingToForeground = null;
3854 pr.foregroundServices = false;
3855 }
3856 updateOomAdjLocked();
3857 }
3858 }
3859
3860 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
3861 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3862 "setProcessForeground()");
3863 synchronized(this) {
3864 boolean changed = false;
3865
3866 synchronized (mPidsSelfLocked) {
3867 ProcessRecord pr = mPidsSelfLocked.get(pid);
3868 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003869 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 return;
3871 }
3872 ForegroundToken oldToken = mForegroundProcesses.get(pid);
3873 if (oldToken != null) {
3874 oldToken.token.unlinkToDeath(oldToken, 0);
3875 mForegroundProcesses.remove(pid);
3876 pr.forcingToForeground = null;
3877 changed = true;
3878 }
3879 if (isForeground && token != null) {
3880 ForegroundToken newToken = new ForegroundToken() {
3881 public void binderDied() {
3882 foregroundTokenDied(this);
3883 }
3884 };
3885 newToken.pid = pid;
3886 newToken.token = token;
3887 try {
3888 token.linkToDeath(newToken, 0);
3889 mForegroundProcesses.put(pid, newToken);
3890 pr.forcingToForeground = token;
3891 changed = true;
3892 } catch (RemoteException e) {
3893 // If the process died while doing this, we will later
3894 // do the cleanup with the process death link.
3895 }
3896 }
3897 }
3898
3899 if (changed) {
3900 updateOomAdjLocked();
3901 }
3902 }
3903 }
3904
3905 // =========================================================
3906 // PERMISSIONS
3907 // =========================================================
3908
3909 static class PermissionController extends IPermissionController.Stub {
3910 ActivityManagerService mActivityManagerService;
3911 PermissionController(ActivityManagerService activityManagerService) {
3912 mActivityManagerService = activityManagerService;
3913 }
3914
3915 public boolean checkPermission(String permission, int pid, int uid) {
3916 return mActivityManagerService.checkPermission(permission, pid,
3917 uid) == PackageManager.PERMISSION_GRANTED;
3918 }
3919 }
3920
3921 /**
3922 * This can be called with or without the global lock held.
3923 */
3924 int checkComponentPermission(String permission, int pid, int uid,
3925 int reqUid) {
3926 // We might be performing an operation on behalf of an indirect binder
3927 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
3928 // client identity accordingly before proceeding.
3929 Identity tlsIdentity = sCallerIdentity.get();
3930 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003931 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
3933 uid = tlsIdentity.uid;
3934 pid = tlsIdentity.pid;
3935 }
3936
3937 // Root, system server and our own process get to do everything.
3938 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
3939 !Process.supportsProcesses()) {
3940 return PackageManager.PERMISSION_GRANTED;
3941 }
3942 // If the target requires a specific UID, always fail for others.
3943 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003944 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 return PackageManager.PERMISSION_DENIED;
3946 }
3947 if (permission == null) {
3948 return PackageManager.PERMISSION_GRANTED;
3949 }
3950 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003951 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 .checkUidPermission(permission, uid);
3953 } catch (RemoteException e) {
3954 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003955 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003956 }
3957 return PackageManager.PERMISSION_DENIED;
3958 }
3959
3960 /**
3961 * As the only public entry point for permissions checking, this method
3962 * can enforce the semantic that requesting a check on a null global
3963 * permission is automatically denied. (Internally a null permission
3964 * string is used when calling {@link #checkComponentPermission} in cases
3965 * when only uid-based security is needed.)
3966 *
3967 * This can be called with or without the global lock held.
3968 */
3969 public int checkPermission(String permission, int pid, int uid) {
3970 if (permission == null) {
3971 return PackageManager.PERMISSION_DENIED;
3972 }
3973 return checkComponentPermission(permission, pid, uid, -1);
3974 }
3975
3976 /**
3977 * Binder IPC calls go through the public entry point.
3978 * This can be called with or without the global lock held.
3979 */
3980 int checkCallingPermission(String permission) {
3981 return checkPermission(permission,
3982 Binder.getCallingPid(),
3983 Binder.getCallingUid());
3984 }
3985
3986 /**
3987 * This can be called with or without the global lock held.
3988 */
3989 void enforceCallingPermission(String permission, String func) {
3990 if (checkCallingPermission(permission)
3991 == PackageManager.PERMISSION_GRANTED) {
3992 return;
3993 }
3994
3995 String msg = "Permission Denial: " + func + " from pid="
3996 + Binder.getCallingPid()
3997 + ", uid=" + Binder.getCallingUid()
3998 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003999 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 throw new SecurityException(msg);
4001 }
4002
4003 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4004 ProviderInfo pi, int uid, int modeFlags) {
4005 try {
4006 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4007 if ((pi.readPermission != null) &&
4008 (pm.checkUidPermission(pi.readPermission, uid)
4009 != PackageManager.PERMISSION_GRANTED)) {
4010 return false;
4011 }
4012 }
4013 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4014 if ((pi.writePermission != null) &&
4015 (pm.checkUidPermission(pi.writePermission, uid)
4016 != PackageManager.PERMISSION_GRANTED)) {
4017 return false;
4018 }
4019 }
4020 return true;
4021 } catch (RemoteException e) {
4022 return false;
4023 }
4024 }
4025
4026 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4027 int modeFlags) {
4028 // Root gets to do everything.
4029 if (uid == 0 || !Process.supportsProcesses()) {
4030 return true;
4031 }
4032 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4033 if (perms == null) return false;
4034 UriPermission perm = perms.get(uri);
4035 if (perm == null) return false;
4036 return (modeFlags&perm.modeFlags) == modeFlags;
4037 }
4038
4039 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4040 // Another redirected-binder-call permissions check as in
4041 // {@link checkComponentPermission}.
4042 Identity tlsIdentity = sCallerIdentity.get();
4043 if (tlsIdentity != null) {
4044 uid = tlsIdentity.uid;
4045 pid = tlsIdentity.pid;
4046 }
4047
4048 // Our own process gets to do everything.
4049 if (pid == MY_PID) {
4050 return PackageManager.PERMISSION_GRANTED;
4051 }
4052 synchronized(this) {
4053 return checkUriPermissionLocked(uri, uid, modeFlags)
4054 ? PackageManager.PERMISSION_GRANTED
4055 : PackageManager.PERMISSION_DENIED;
4056 }
4057 }
4058
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004059 void grantUriPermissionLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004060 String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4062 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4063 if (modeFlags == 0) {
4064 return;
4065 }
4066
Joe Onorato8a9b2202010-02-26 18:56:32 -08004067 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004068 "Requested grant " + targetPkg + " permission to " + uri);
4069
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004070 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004071
4072 // If this is not a content: uri, we can't do anything with it.
4073 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004074 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004075 "Can't grant URI permission for non-content URI: " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004076 return;
4077 }
4078
4079 String name = uri.getAuthority();
4080 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004081 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 if (cpr != null) {
4083 pi = cpr.info;
4084 } else {
4085 try {
4086 pi = pm.resolveContentProvider(name,
4087 PackageManager.GET_URI_PERMISSION_PATTERNS);
4088 } catch (RemoteException ex) {
4089 }
4090 }
4091 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004092 Slog.w(TAG, "No content provider found for: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 return;
4094 }
4095
4096 int targetUid;
4097 try {
4098 targetUid = pm.getPackageUid(targetPkg);
4099 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004100 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004101 "Can't grant URI permission no uid for: " + targetPkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 return;
4103 }
4104 } catch (RemoteException ex) {
4105 return;
4106 }
4107
4108 // First... does the target actually need this permission?
4109 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4110 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004111 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004112 "Target " + targetPkg + " already has full permission to " + uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004113 return;
4114 }
4115
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004116 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004117 if (!pi.grantUriPermissions) {
4118 throw new SecurityException("Provider " + pi.packageName
4119 + "/" + pi.name
4120 + " does not allow granting of Uri permissions (uri "
4121 + uri + ")");
4122 }
4123 if (pi.uriPermissionPatterns != null) {
4124 final int N = pi.uriPermissionPatterns.length;
4125 boolean allowed = false;
4126 for (int i=0; i<N; i++) {
4127 if (pi.uriPermissionPatterns[i] != null
4128 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4129 allowed = true;
4130 break;
4131 }
4132 }
4133 if (!allowed) {
4134 throw new SecurityException("Provider " + pi.packageName
4135 + "/" + pi.name
4136 + " does not allow granting of permission to path of Uri "
4137 + uri);
4138 }
4139 }
4140
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004141 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004142 // this uri?
4143 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4144 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4145 throw new SecurityException("Uid " + callingUid
4146 + " does not have permission to uri " + uri);
4147 }
4148 }
4149
4150 // Okay! So here we are: the caller has the assumed permission
4151 // to the uri, and the target doesn't. Let's now give this to
4152 // the target.
4153
Joe Onorato8a9b2202010-02-26 18:56:32 -08004154 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004155 "Granting " + targetPkg + " permission to " + uri);
4156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 HashMap<Uri, UriPermission> targetUris
4158 = mGrantedUriPermissions.get(targetUid);
4159 if (targetUris == null) {
4160 targetUris = new HashMap<Uri, UriPermission>();
4161 mGrantedUriPermissions.put(targetUid, targetUris);
4162 }
4163
4164 UriPermission perm = targetUris.get(uri);
4165 if (perm == null) {
4166 perm = new UriPermission(targetUid, uri);
4167 targetUris.put(uri, perm);
4168
4169 }
4170 perm.modeFlags |= modeFlags;
4171 if (activity == null) {
4172 perm.globalModeFlags |= modeFlags;
4173 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4174 perm.readActivities.add(activity);
4175 if (activity.readUriPermissions == null) {
4176 activity.readUriPermissions = new HashSet<UriPermission>();
4177 }
4178 activity.readUriPermissions.add(perm);
4179 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4180 perm.writeActivities.add(activity);
4181 if (activity.writeUriPermissions == null) {
4182 activity.writeUriPermissions = new HashSet<UriPermission>();
4183 }
4184 activity.writeUriPermissions.add(perm);
4185 }
4186 }
4187
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004188 void grantUriPermissionFromIntentLocked(int callingUid,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004189 String targetPkg, Intent intent, ActivityRecord activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 if (intent == null) {
4191 return;
4192 }
4193 Uri data = intent.getData();
4194 if (data == null) {
4195 return;
4196 }
4197 grantUriPermissionLocked(callingUid, targetPkg, data,
4198 intent.getFlags(), activity);
4199 }
4200
4201 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4202 Uri uri, int modeFlags) {
4203 synchronized(this) {
4204 final ProcessRecord r = getRecordForAppLocked(caller);
4205 if (r == null) {
4206 throw new SecurityException("Unable to find app for caller "
4207 + caller
4208 + " when granting permission to uri " + uri);
4209 }
4210 if (targetPkg == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004211 Slog.w(TAG, "grantUriPermission: null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 return;
4213 }
4214 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004215 Slog.w(TAG, "grantUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004216 return;
4217 }
4218
4219 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4220 null);
4221 }
4222 }
4223
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004224 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4226 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4227 HashMap<Uri, UriPermission> perms
4228 = mGrantedUriPermissions.get(perm.uid);
4229 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004230 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004231 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 perms.remove(perm.uri);
4233 if (perms.size() == 0) {
4234 mGrantedUriPermissions.remove(perm.uid);
4235 }
4236 }
4237 }
4238 }
4239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4241 int modeFlags) {
4242 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4243 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4244 if (modeFlags == 0) {
4245 return;
4246 }
4247
Joe Onorato8a9b2202010-02-26 18:56:32 -08004248 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004249 "Revoking all granted permissions to " + uri);
4250
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004251 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004252
4253 final String authority = uri.getAuthority();
4254 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004255 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004256 if (cpr != null) {
4257 pi = cpr.info;
4258 } else {
4259 try {
4260 pi = pm.resolveContentProvider(authority,
4261 PackageManager.GET_URI_PERMISSION_PATTERNS);
4262 } catch (RemoteException ex) {
4263 }
4264 }
4265 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004266 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 return;
4268 }
4269
4270 // Does the caller have this permission on the URI?
4271 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4272 // Right now, if you are not the original owner of the permission,
4273 // you are not allowed to revoke it.
4274 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4275 throw new SecurityException("Uid " + callingUid
4276 + " does not have permission to uri " + uri);
4277 //}
4278 }
4279
4280 // Go through all of the permissions and remove any that match.
4281 final List<String> SEGMENTS = uri.getPathSegments();
4282 if (SEGMENTS != null) {
4283 final int NS = SEGMENTS.size();
4284 int N = mGrantedUriPermissions.size();
4285 for (int i=0; i<N; i++) {
4286 HashMap<Uri, UriPermission> perms
4287 = mGrantedUriPermissions.valueAt(i);
4288 Iterator<UriPermission> it = perms.values().iterator();
4289 toploop:
4290 while (it.hasNext()) {
4291 UriPermission perm = it.next();
4292 Uri targetUri = perm.uri;
4293 if (!authority.equals(targetUri.getAuthority())) {
4294 continue;
4295 }
4296 List<String> targetSegments = targetUri.getPathSegments();
4297 if (targetSegments == null) {
4298 continue;
4299 }
4300 if (targetSegments.size() < NS) {
4301 continue;
4302 }
4303 for (int j=0; j<NS; j++) {
4304 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4305 continue toploop;
4306 }
4307 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004308 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004309 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 perm.clearModes(modeFlags);
4311 if (perm.modeFlags == 0) {
4312 it.remove();
4313 }
4314 }
4315 if (perms.size() == 0) {
4316 mGrantedUriPermissions.remove(
4317 mGrantedUriPermissions.keyAt(i));
4318 N--;
4319 i--;
4320 }
4321 }
4322 }
4323 }
4324
4325 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4326 int modeFlags) {
4327 synchronized(this) {
4328 final ProcessRecord r = getRecordForAppLocked(caller);
4329 if (r == null) {
4330 throw new SecurityException("Unable to find app for caller "
4331 + caller
4332 + " when revoking permission to uri " + uri);
4333 }
4334 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004335 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336 return;
4337 }
4338
4339 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4340 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4341 if (modeFlags == 0) {
4342 return;
4343 }
4344
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004345 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346
4347 final String authority = uri.getAuthority();
4348 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004349 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 if (cpr != null) {
4351 pi = cpr.info;
4352 } else {
4353 try {
4354 pi = pm.resolveContentProvider(authority,
4355 PackageManager.GET_URI_PERMISSION_PATTERNS);
4356 } catch (RemoteException ex) {
4357 }
4358 }
4359 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004360 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 return;
4362 }
4363
4364 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4365 }
4366 }
4367
4368 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4369 synchronized (this) {
4370 ProcessRecord app =
4371 who != null ? getRecordForAppLocked(who) : null;
4372 if (app == null) return;
4373
4374 Message msg = Message.obtain();
4375 msg.what = WAIT_FOR_DEBUGGER_MSG;
4376 msg.obj = app;
4377 msg.arg1 = waiting ? 1 : 0;
4378 mHandler.sendMessage(msg);
4379 }
4380 }
4381
4382 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4383 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004384 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004386 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004387 }
4388
4389 // =========================================================
4390 // TASK MANAGEMENT
4391 // =========================================================
4392
4393 public List getTasks(int maxNum, int flags,
4394 IThumbnailReceiver receiver) {
4395 ArrayList list = new ArrayList();
4396
4397 PendingThumbnailsRecord pending = null;
4398 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004399 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400
4401 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004402 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4404 + ", receiver=" + receiver);
4405
4406 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4407 != PackageManager.PERMISSION_GRANTED) {
4408 if (receiver != null) {
4409 // If the caller wants to wait for pending thumbnails,
4410 // it ain't gonna get them.
4411 try {
4412 receiver.finished();
4413 } catch (RemoteException ex) {
4414 }
4415 }
4416 String msg = "Permission Denial: getTasks() from pid="
4417 + Binder.getCallingPid()
4418 + ", uid=" + Binder.getCallingUid()
4419 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004420 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421 throw new SecurityException(msg);
4422 }
4423
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004424 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004425 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004426 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004427 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 CharSequence topDescription = null;
4429 TaskRecord curTask = null;
4430 int numActivities = 0;
4431 int numRunning = 0;
4432 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004433 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004435 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436
4437 // Initialize state for next task if needed.
4438 if (top == null ||
4439 (top.state == ActivityState.INITIALIZING
4440 && top.task == r.task)) {
4441 top = r;
4442 topDescription = r.description;
4443 curTask = r.task;
4444 numActivities = numRunning = 0;
4445 }
4446
4447 // Add 'r' into the current task.
4448 numActivities++;
4449 if (r.app != null && r.app.thread != null) {
4450 numRunning++;
4451 }
4452 if (topDescription == null) {
4453 topDescription = r.description;
4454 }
4455
Joe Onorato8a9b2202010-02-26 18:56:32 -08004456 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 TAG, r.intent.getComponent().flattenToShortString()
4458 + ": task=" + r.task);
4459
4460 // If the next one is a different task, generate a new
4461 // TaskInfo entry for what we have.
4462 if (next == null || next.task != curTask) {
4463 ActivityManager.RunningTaskInfo ci
4464 = new ActivityManager.RunningTaskInfo();
4465 ci.id = curTask.taskId;
4466 ci.baseActivity = r.intent.getComponent();
4467 ci.topActivity = top.intent.getComponent();
4468 ci.thumbnail = top.thumbnail;
4469 ci.description = topDescription;
4470 ci.numActivities = numActivities;
4471 ci.numRunning = numRunning;
4472 //System.out.println(
4473 // "#" + maxNum + ": " + " descr=" + ci.description);
4474 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004475 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 TAG, "State=" + top.state + "Idle=" + top.idle
4477 + " app=" + top.app
4478 + " thr=" + (top.app != null ? top.app.thread : null));
4479 if (top.state == ActivityState.RESUMED
4480 || top.state == ActivityState.PAUSING) {
4481 if (top.idle && top.app != null
4482 && top.app.thread != null) {
4483 topRecord = top;
4484 topThumbnail = top.app.thread;
4485 } else {
4486 top.thumbnailNeeded = true;
4487 }
4488 }
4489 if (pending == null) {
4490 pending = new PendingThumbnailsRecord(receiver);
4491 }
4492 pending.pendingRecords.add(top);
4493 }
4494 list.add(ci);
4495 maxNum--;
4496 top = null;
4497 }
4498 }
4499
4500 if (pending != null) {
4501 mPendingThumbnails.add(pending);
4502 }
4503 }
4504
Joe Onorato8a9b2202010-02-26 18:56:32 -08004505 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506
4507 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004508 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004509 try {
4510 topThumbnail.requestThumbnail(topRecord);
4511 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004512 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 sendPendingThumbnail(null, topRecord, null, null, true);
4514 }
4515 }
4516
4517 if (pending == null && receiver != null) {
4518 // In this case all thumbnails were available and the client
4519 // is being asked to be told when the remaining ones come in...
4520 // which is unusually, since the top-most currently running
4521 // activity should never have a canned thumbnail! Oh well.
4522 try {
4523 receiver.finished();
4524 } catch (RemoteException ex) {
4525 }
4526 }
4527
4528 return list;
4529 }
4530
4531 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4532 int flags) {
4533 synchronized (this) {
4534 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4535 "getRecentTasks()");
4536
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004537 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004539 final int N = mRecentTasks.size();
4540 ArrayList<ActivityManager.RecentTaskInfo> res
4541 = new ArrayList<ActivityManager.RecentTaskInfo>(
4542 maxNum < N ? maxNum : N);
4543 for (int i=0; i<N && maxNum > 0; i++) {
4544 TaskRecord tr = mRecentTasks.get(i);
4545 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4546 || (tr.intent == null)
4547 || ((tr.intent.getFlags()
4548 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4549 ActivityManager.RecentTaskInfo rti
4550 = new ActivityManager.RecentTaskInfo();
4551 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4552 rti.baseIntent = new Intent(
4553 tr.intent != null ? tr.intent : tr.affinityIntent);
4554 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004555
4556 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4557 // Check whether this activity is currently available.
4558 try {
4559 if (rti.origActivity != null) {
4560 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4561 continue;
4562 }
4563 } else if (rti.baseIntent != null) {
4564 if (pm.queryIntentActivities(rti.baseIntent,
4565 null, 0) == null) {
4566 continue;
4567 }
4568 }
4569 } catch (RemoteException e) {
4570 // Will never happen.
4571 }
4572 }
4573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004574 res.add(rti);
4575 maxNum--;
4576 }
4577 }
4578 return res;
4579 }
4580 }
4581
4582 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4583 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004584 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 TaskRecord jt = startTask;
4586
4587 // First look backwards
4588 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004589 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004590 if (r.task != jt) {
4591 jt = r.task;
4592 if (affinity.equals(jt.affinity)) {
4593 return j;
4594 }
4595 }
4596 }
4597
4598 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004599 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004600 jt = startTask;
4601 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004602 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 if (r.task != jt) {
4604 if (affinity.equals(jt.affinity)) {
4605 return j;
4606 }
4607 jt = r.task;
4608 }
4609 }
4610
4611 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004612 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004613 return N-1;
4614 }
4615
4616 return -1;
4617 }
4618
4619 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004620 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004621 */
4622 public void moveTaskToFront(int task) {
4623 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4624 "moveTaskToFront()");
4625
4626 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004627 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4628 Binder.getCallingUid(), "Task to front")) {
4629 return;
4630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004631 final long origId = Binder.clearCallingIdentity();
4632 try {
4633 int N = mRecentTasks.size();
4634 for (int i=0; i<N; i++) {
4635 TaskRecord tr = mRecentTasks.get(i);
4636 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004637 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 return;
4639 }
4640 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004641 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4642 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004644 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 return;
4646 }
4647 }
4648 } finally {
4649 Binder.restoreCallingIdentity(origId);
4650 }
4651 }
4652 }
4653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004654 public void moveTaskToBack(int task) {
4655 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4656 "moveTaskToBack()");
4657
4658 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004659 if (mMainStack.mResumedActivity != null
4660 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004661 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4662 Binder.getCallingUid(), "Task to back")) {
4663 return;
4664 }
4665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004667 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004668 Binder.restoreCallingIdentity(origId);
4669 }
4670 }
4671
4672 /**
4673 * Moves an activity, and all of the other activities within the same task, to the bottom
4674 * of the history stack. The activity's order within the task is unchanged.
4675 *
4676 * @param token A reference to the activity we wish to move
4677 * @param nonRoot If false then this only works if the activity is the root
4678 * of a task; if true it will work for any activity in a task.
4679 * @return Returns true if the move completed, false if not.
4680 */
4681 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4682 synchronized(this) {
4683 final long origId = Binder.clearCallingIdentity();
4684 int taskId = getTaskForActivityLocked(token, !nonRoot);
4685 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004686 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 }
4688 Binder.restoreCallingIdentity(origId);
4689 }
4690 return false;
4691 }
4692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004693 public void moveTaskBackwards(int task) {
4694 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4695 "moveTaskBackwards()");
4696
4697 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004698 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4699 Binder.getCallingUid(), "Task backwards")) {
4700 return;
4701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 final long origId = Binder.clearCallingIdentity();
4703 moveTaskBackwardsLocked(task);
4704 Binder.restoreCallingIdentity(origId);
4705 }
4706 }
4707
4708 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004709 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 }
4711
4712 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
4713 synchronized(this) {
4714 return getTaskForActivityLocked(token, onlyRoot);
4715 }
4716 }
4717
4718 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004719 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 TaskRecord lastTask = null;
4721 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004722 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004723 if (r == token) {
4724 if (!onlyRoot || lastTask != r.task) {
4725 return r.task.taskId;
4726 }
4727 return -1;
4728 }
4729 lastTask = r.task;
4730 }
4731
4732 return -1;
4733 }
4734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735 public void finishOtherInstances(IBinder token, ComponentName className) {
4736 synchronized(this) {
4737 final long origId = Binder.clearCallingIdentity();
4738
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004739 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 TaskRecord lastTask = null;
4741 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004742 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004743 if (r.realActivity.equals(className)
4744 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004745 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 null, "others")) {
4747 i--;
4748 N--;
4749 }
4750 }
4751 lastTask = r.task;
4752 }
4753
4754 Binder.restoreCallingIdentity(origId);
4755 }
4756 }
4757
4758 // =========================================================
4759 // THUMBNAILS
4760 // =========================================================
4761
4762 public void reportThumbnail(IBinder token,
4763 Bitmap thumbnail, CharSequence description) {
4764 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
4765 final long origId = Binder.clearCallingIdentity();
4766 sendPendingThumbnail(null, token, thumbnail, description, true);
4767 Binder.restoreCallingIdentity(origId);
4768 }
4769
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004770 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771 Bitmap thumbnail, CharSequence description, boolean always) {
4772 TaskRecord task = null;
4773 ArrayList receivers = null;
4774
4775 //System.out.println("Send pending thumbnail: " + r);
4776
4777 synchronized(this) {
4778 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004779 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 if (index < 0) {
4781 return;
4782 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004783 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004784 }
4785 if (thumbnail == null) {
4786 thumbnail = r.thumbnail;
4787 description = r.description;
4788 }
4789 if (thumbnail == null && !always) {
4790 // If there is no thumbnail, and this entry is not actually
4791 // going away, then abort for now and pick up the next
4792 // thumbnail we get.
4793 return;
4794 }
4795 task = r.task;
4796
4797 int N = mPendingThumbnails.size();
4798 int i=0;
4799 while (i<N) {
4800 PendingThumbnailsRecord pr =
4801 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
4802 //System.out.println("Looking in " + pr.pendingRecords);
4803 if (pr.pendingRecords.remove(r)) {
4804 if (receivers == null) {
4805 receivers = new ArrayList();
4806 }
4807 receivers.add(pr);
4808 if (pr.pendingRecords.size() == 0) {
4809 pr.finished = true;
4810 mPendingThumbnails.remove(i);
4811 N--;
4812 continue;
4813 }
4814 }
4815 i++;
4816 }
4817 }
4818
4819 if (receivers != null) {
4820 final int N = receivers.size();
4821 for (int i=0; i<N; i++) {
4822 try {
4823 PendingThumbnailsRecord pr =
4824 (PendingThumbnailsRecord)receivers.get(i);
4825 pr.receiver.newThumbnail(
4826 task != null ? task.taskId : -1, thumbnail, description);
4827 if (pr.finished) {
4828 pr.receiver.finished();
4829 }
4830 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004831 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 }
4833 }
4834 }
4835 }
4836
4837 // =========================================================
4838 // CONTENT PROVIDERS
4839 // =========================================================
4840
4841 private final List generateApplicationProvidersLocked(ProcessRecord app) {
4842 List providers = null;
4843 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004844 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07004846 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 } catch (RemoteException ex) {
4848 }
4849 if (providers != null) {
4850 final int N = providers.size();
4851 for (int i=0; i<N; i++) {
4852 ProviderInfo cpi =
4853 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004854 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 if (cpr == null) {
4856 cpr = new ContentProviderRecord(cpi, app.info);
4857 mProvidersByClass.put(cpi.name, cpr);
4858 }
4859 app.pubProviders.put(cpi.name, cpr);
4860 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004861 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004862 }
4863 }
4864 return providers;
4865 }
4866
4867 private final String checkContentProviderPermissionLocked(
4868 ProviderInfo cpi, ProcessRecord r, int mode) {
4869 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
4870 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
4871 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
4872 cpi.exported ? -1 : cpi.applicationInfo.uid)
4873 == PackageManager.PERMISSION_GRANTED
4874 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4875 return null;
4876 }
4877 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
4878 cpi.exported ? -1 : cpi.applicationInfo.uid)
4879 == PackageManager.PERMISSION_GRANTED) {
4880 return null;
4881 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07004882
4883 PathPermission[] pps = cpi.pathPermissions;
4884 if (pps != null) {
4885 int i = pps.length;
4886 while (i > 0) {
4887 i--;
4888 PathPermission pp = pps[i];
4889 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
4890 cpi.exported ? -1 : cpi.applicationInfo.uid)
4891 == PackageManager.PERMISSION_GRANTED
4892 && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
4893 return null;
4894 }
4895 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
4896 cpi.exported ? -1 : cpi.applicationInfo.uid)
4897 == PackageManager.PERMISSION_GRANTED) {
4898 return null;
4899 }
4900 }
4901 }
4902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004903 String msg = "Permission Denial: opening provider " + cpi.name
4904 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
4905 + ", uid=" + callingUid + ") requires "
4906 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004907 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 return msg;
4909 }
4910
4911 private final ContentProviderHolder getContentProviderImpl(
4912 IApplicationThread caller, String name) {
4913 ContentProviderRecord cpr;
4914 ProviderInfo cpi = null;
4915
4916 synchronized(this) {
4917 ProcessRecord r = null;
4918 if (caller != null) {
4919 r = getRecordForAppLocked(caller);
4920 if (r == null) {
4921 throw new SecurityException(
4922 "Unable to find app for caller " + caller
4923 + " (pid=" + Binder.getCallingPid()
4924 + ") when getting content provider " + name);
4925 }
4926 }
4927
4928 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07004929 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 if (cpr != null) {
4931 cpi = cpr.info;
4932 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
4933 return new ContentProviderHolder(cpi,
4934 cpi.readPermission != null
4935 ? cpi.readPermission : cpi.writePermission);
4936 }
4937
4938 if (r != null && cpr.canRunHere(r)) {
4939 // This provider has been published or is in the process
4940 // of being published... but it is also allowed to run
4941 // in the caller's process, so don't make a connection
4942 // and just let the caller instantiate its own instance.
4943 if (cpr.provider != null) {
4944 // don't give caller the provider object, it needs
4945 // to make its own.
4946 cpr = new ContentProviderRecord(cpr);
4947 }
4948 return cpr;
4949 }
4950
4951 final long origId = Binder.clearCallingIdentity();
4952
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004953 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004954 // return it right away.
4955 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004956 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07004957 "Adding provider requested by "
4958 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07004959 + cpr.info.processName);
4960 Integer cnt = r.conProviders.get(cpr);
4961 if (cnt == null) {
4962 r.conProviders.put(cpr, new Integer(1));
4963 } else {
4964 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
4965 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004966 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07004967 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
4968 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07004969 // make sure to count it as being accessed and thus
4970 // back up on the LRU list. This is good because
4971 // content providers are often expensive to start.
4972 updateLruProcessLocked(cpr.app, false, true);
4973 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07004974 } else {
4975 cpr.externals++;
4976 }
4977
4978 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 updateOomAdjLocked(cpr.app);
4980 }
4981
4982 Binder.restoreCallingIdentity(origId);
4983
4984 } else {
4985 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004986 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07004987 resolveContentProvider(name,
4988 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 } catch (RemoteException ex) {
4990 }
4991 if (cpi == null) {
4992 return null;
4993 }
4994
4995 if (checkContentProviderPermissionLocked(cpi, r, -1) != null) {
4996 return new ContentProviderHolder(cpi,
4997 cpi.readPermission != null
4998 ? cpi.readPermission : cpi.writePermission);
4999 }
5000
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005001 if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
5002 && !cpi.processName.equals("system")) {
5003 // If this content provider does not run in the system
5004 // process, and the system is not yet ready to run other
5005 // processes, then fail fast instead of hanging.
5006 throw new IllegalArgumentException(
5007 "Attempt to launch content provider before system ready");
5008 }
5009
Dianne Hackborn860755f2010-06-03 18:47:52 -07005010 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005011 final boolean firstClass = cpr == null;
5012 if (firstClass) {
5013 try {
5014 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005015 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 getApplicationInfo(
5017 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005018 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005020 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005021 + cpi.name);
5022 return null;
5023 }
5024 cpr = new ContentProviderRecord(cpi, ai);
5025 } catch (RemoteException ex) {
5026 // pm is in same process, this will never happen.
5027 }
5028 }
5029
5030 if (r != null && cpr.canRunHere(r)) {
5031 // If this is a multiprocess provider, then just return its
5032 // info and allow the caller to instantiate it. Only do
5033 // this if the provider is the same user as the caller's
5034 // process, or can run as root (so can be in any process).
5035 return cpr;
5036 }
5037
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005038 if (DEBUG_PROVIDER) {
5039 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005040 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005041 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 }
5043
5044 // This is single process, and our app is now connecting to it.
5045 // See if we are already in the process of launching this
5046 // provider.
5047 final int N = mLaunchingProviders.size();
5048 int i;
5049 for (i=0; i<N; i++) {
5050 if (mLaunchingProviders.get(i) == cpr) {
5051 break;
5052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 }
5054
5055 // If the provider is not already being launched, then get it
5056 // started.
5057 if (i >= N) {
5058 final long origId = Binder.clearCallingIdentity();
5059 ProcessRecord proc = startProcessLocked(cpi.processName,
5060 cpr.appInfo, false, 0, "content provider",
5061 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005062 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005064 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 + cpi.applicationInfo.packageName + "/"
5066 + cpi.applicationInfo.uid + " for provider "
5067 + name + ": process is bad");
5068 return null;
5069 }
5070 cpr.launchingApp = proc;
5071 mLaunchingProviders.add(cpr);
5072 Binder.restoreCallingIdentity(origId);
5073 }
5074
5075 // Make sure the provider is published (the same provider class
5076 // may be published under multiple names).
5077 if (firstClass) {
5078 mProvidersByClass.put(cpi.name, cpr);
5079 }
5080 mProvidersByName.put(name, cpr);
5081
5082 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005083 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005084 "Adding provider requested by "
5085 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005086 + cpr.info.processName);
5087 Integer cnt = r.conProviders.get(cpr);
5088 if (cnt == null) {
5089 r.conProviders.put(cpr, new Integer(1));
5090 } else {
5091 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 cpr.clients.add(r);
5094 } else {
5095 cpr.externals++;
5096 }
5097 }
5098 }
5099
5100 // Wait for the provider to be published...
5101 synchronized (cpr) {
5102 while (cpr.provider == null) {
5103 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005104 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 + cpi.applicationInfo.packageName + "/"
5106 + cpi.applicationInfo.uid + " for provider "
5107 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005108 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 cpi.applicationInfo.packageName,
5110 cpi.applicationInfo.uid, name);
5111 return null;
5112 }
5113 try {
5114 cpr.wait();
5115 } catch (InterruptedException ex) {
5116 }
5117 }
5118 }
5119 return cpr;
5120 }
5121
5122 public final ContentProviderHolder getContentProvider(
5123 IApplicationThread caller, String name) {
5124 if (caller == null) {
5125 String msg = "null IApplicationThread when getting content provider "
5126 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005127 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 throw new SecurityException(msg);
5129 }
5130
5131 return getContentProviderImpl(caller, name);
5132 }
5133
5134 private ContentProviderHolder getContentProviderExternal(String name) {
5135 return getContentProviderImpl(null, name);
5136 }
5137
5138 /**
5139 * Drop a content provider from a ProcessRecord's bookkeeping
5140 * @param cpr
5141 */
5142 public void removeContentProvider(IApplicationThread caller, String name) {
5143 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005144 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005146 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005147 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005148 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 return;
5150 }
5151 final ProcessRecord r = getRecordForAppLocked(caller);
5152 if (r == null) {
5153 throw new SecurityException(
5154 "Unable to find app for caller " + caller +
5155 " when removing content provider " + name);
5156 }
5157 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005158 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005159 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005160 + r.info.processName + " from process "
5161 + localCpr.appInfo.processName);
5162 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005163 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005164 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005165 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 return;
5167 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005168 Integer cnt = r.conProviders.get(localCpr);
5169 if (cnt == null || cnt.intValue() <= 1) {
5170 localCpr.clients.remove(r);
5171 r.conProviders.remove(localCpr);
5172 } else {
5173 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 }
5176 updateOomAdjLocked();
5177 }
5178 }
5179
5180 private void removeContentProviderExternal(String name) {
5181 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005182 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005183 if(cpr == null) {
5184 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005185 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005186 return;
5187 }
5188
5189 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005190 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 localCpr.externals--;
5192 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005193 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 }
5195 updateOomAdjLocked();
5196 }
5197 }
5198
5199 public final void publishContentProviders(IApplicationThread caller,
5200 List<ContentProviderHolder> providers) {
5201 if (providers == null) {
5202 return;
5203 }
5204
5205 synchronized(this) {
5206 final ProcessRecord r = getRecordForAppLocked(caller);
5207 if (r == null) {
5208 throw new SecurityException(
5209 "Unable to find app for caller " + caller
5210 + " (pid=" + Binder.getCallingPid()
5211 + ") when publishing content providers");
5212 }
5213
5214 final long origId = Binder.clearCallingIdentity();
5215
5216 final int N = providers.size();
5217 for (int i=0; i<N; i++) {
5218 ContentProviderHolder src = providers.get(i);
5219 if (src == null || src.info == null || src.provider == null) {
5220 continue;
5221 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005222 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 if (dst != null) {
5224 mProvidersByClass.put(dst.info.name, dst);
5225 String names[] = dst.info.authority.split(";");
5226 for (int j = 0; j < names.length; j++) {
5227 mProvidersByName.put(names[j], dst);
5228 }
5229
5230 int NL = mLaunchingProviders.size();
5231 int j;
5232 for (j=0; j<NL; j++) {
5233 if (mLaunchingProviders.get(j) == dst) {
5234 mLaunchingProviders.remove(j);
5235 j--;
5236 NL--;
5237 }
5238 }
5239 synchronized (dst) {
5240 dst.provider = src.provider;
5241 dst.app = r;
5242 dst.notifyAll();
5243 }
5244 updateOomAdjLocked(r);
5245 }
5246 }
5247
5248 Binder.restoreCallingIdentity(origId);
5249 }
5250 }
5251
5252 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005253 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005254 synchronized (mSelf) {
5255 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5256 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005257 if (providers != null) {
5258 for (int i=providers.size()-1; i>=0; i--) {
5259 ProviderInfo pi = (ProviderInfo)providers.get(i);
5260 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5261 Slog.w(TAG, "Not installing system proc provider " + pi.name
5262 + ": not system .apk");
5263 providers.remove(i);
5264 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005265 }
5266 }
5267 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005268 if (providers != null) {
5269 mSystemThread.installSystemProviders(providers);
5270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 }
5272
5273 // =========================================================
5274 // GLOBAL MANAGEMENT
5275 // =========================================================
5276
5277 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5278 ApplicationInfo info, String customProcess) {
5279 String proc = customProcess != null ? customProcess : info.processName;
5280 BatteryStatsImpl.Uid.Proc ps = null;
5281 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5282 synchronized (stats) {
5283 ps = stats.getProcessStatsLocked(info.uid, proc);
5284 }
5285 return new ProcessRecord(ps, thread, info, proc);
5286 }
5287
5288 final ProcessRecord addAppLocked(ApplicationInfo info) {
5289 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5290
5291 if (app == null) {
5292 app = newProcessRecordLocked(null, info, null);
5293 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005294 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 }
5296
5297 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5298 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5299 app.persistent = true;
5300 app.maxAdj = CORE_SERVER_ADJ;
5301 }
5302 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5303 mPersistentStartingProcesses.add(app);
5304 startProcessLocked(app, "added application", app.processName);
5305 }
5306
5307 return app;
5308 }
5309
5310 public void unhandledBack() {
5311 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5312 "unhandledBack()");
5313
5314 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005315 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005316 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 TAG, "Performing unhandledBack(): stack size = " + count);
5318 if (count > 1) {
5319 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005320 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5322 Binder.restoreCallingIdentity(origId);
5323 }
5324 }
5325 }
5326
5327 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5328 String name = uri.getAuthority();
5329 ContentProviderHolder cph = getContentProviderExternal(name);
5330 ParcelFileDescriptor pfd = null;
5331 if (cph != null) {
5332 // We record the binder invoker's uid in thread-local storage before
5333 // going to the content provider to open the file. Later, in the code
5334 // that handles all permissions checks, we look for this uid and use
5335 // that rather than the Activity Manager's own uid. The effect is that
5336 // we do the check against the caller's permissions even though it looks
5337 // to the content provider like the Activity Manager itself is making
5338 // the request.
5339 sCallerIdentity.set(new Identity(
5340 Binder.getCallingPid(), Binder.getCallingUid()));
5341 try {
5342 pfd = cph.provider.openFile(uri, "r");
5343 } catch (FileNotFoundException e) {
5344 // do nothing; pfd will be returned null
5345 } finally {
5346 // Ensure that whatever happens, we clean up the identity state
5347 sCallerIdentity.remove();
5348 }
5349
5350 // We've got the fd now, so we're done with the provider.
5351 removeContentProviderExternal(name);
5352 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005353 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 }
5355 return pfd;
5356 }
5357
5358 public void goingToSleep() {
5359 synchronized(this) {
5360 mSleeping = true;
5361 mWindowManager.setEventDispatching(false);
5362
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005363 if (mMainStack.mResumedActivity != null) {
5364 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005366 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367 }
5368 }
5369 }
5370
Dianne Hackborn55280a92009-05-07 15:53:46 -07005371 public boolean shutdown(int timeout) {
5372 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5373 != PackageManager.PERMISSION_GRANTED) {
5374 throw new SecurityException("Requires permission "
5375 + android.Manifest.permission.SHUTDOWN);
5376 }
5377
5378 boolean timedout = false;
5379
5380 synchronized(this) {
5381 mShuttingDown = true;
5382 mWindowManager.setEventDispatching(false);
5383
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005384 if (mMainStack.mResumedActivity != null) {
5385 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005386 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005387 while (mMainStack.mResumedActivity != null
5388 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005389 long delay = endTime - System.currentTimeMillis();
5390 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005391 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005392 timedout = true;
5393 break;
5394 }
5395 try {
5396 this.wait();
5397 } catch (InterruptedException e) {
5398 }
5399 }
5400 }
5401 }
5402
5403 mUsageStatsService.shutdown();
5404 mBatteryStatsService.shutdown();
5405
5406 return timedout;
5407 }
5408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 public void wakingUp() {
5410 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005411 if (mMainStack.mGoingToSleep.isHeld()) {
5412 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005413 }
5414 mWindowManager.setEventDispatching(true);
5415 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005416 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005417 }
5418 }
5419
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005420 public void stopAppSwitches() {
5421 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5422 != PackageManager.PERMISSION_GRANTED) {
5423 throw new SecurityException("Requires permission "
5424 + android.Manifest.permission.STOP_APP_SWITCHES);
5425 }
5426
5427 synchronized(this) {
5428 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5429 + APP_SWITCH_DELAY_TIME;
5430 mDidAppSwitch = false;
5431 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5432 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5433 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5434 }
5435 }
5436
5437 public void resumeAppSwitches() {
5438 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5439 != PackageManager.PERMISSION_GRANTED) {
5440 throw new SecurityException("Requires permission "
5441 + android.Manifest.permission.STOP_APP_SWITCHES);
5442 }
5443
5444 synchronized(this) {
5445 // Note that we don't execute any pending app switches... we will
5446 // let those wait until either the timeout, or the next start
5447 // activity request.
5448 mAppSwitchesAllowedTime = 0;
5449 }
5450 }
5451
5452 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5453 String name) {
5454 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5455 return true;
5456 }
5457
5458 final int perm = checkComponentPermission(
5459 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5460 callingUid, -1);
5461 if (perm == PackageManager.PERMISSION_GRANTED) {
5462 return true;
5463 }
5464
Joe Onorato8a9b2202010-02-26 18:56:32 -08005465 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005466 return false;
5467 }
5468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 public void setDebugApp(String packageName, boolean waitForDebugger,
5470 boolean persistent) {
5471 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5472 "setDebugApp()");
5473
5474 // Note that this is not really thread safe if there are multiple
5475 // callers into it at the same time, but that's not a situation we
5476 // care about.
5477 if (persistent) {
5478 final ContentResolver resolver = mContext.getContentResolver();
5479 Settings.System.putString(
5480 resolver, Settings.System.DEBUG_APP,
5481 packageName);
5482 Settings.System.putInt(
5483 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5484 waitForDebugger ? 1 : 0);
5485 }
5486
5487 synchronized (this) {
5488 if (!persistent) {
5489 mOrigDebugApp = mDebugApp;
5490 mOrigWaitForDebugger = mWaitForDebugger;
5491 }
5492 mDebugApp = packageName;
5493 mWaitForDebugger = waitForDebugger;
5494 mDebugTransient = !persistent;
5495 if (packageName != null) {
5496 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005497 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 Binder.restoreCallingIdentity(origId);
5499 }
5500 }
5501 }
5502
5503 public void setAlwaysFinish(boolean enabled) {
5504 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5505 "setAlwaysFinish()");
5506
5507 Settings.System.putInt(
5508 mContext.getContentResolver(),
5509 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5510
5511 synchronized (this) {
5512 mAlwaysFinishActivities = enabled;
5513 }
5514 }
5515
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005516 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005518 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005520 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 }
5522 }
5523
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005524 public boolean isUserAMonkey() {
5525 // For now the fact that there is a controller implies
5526 // we have a monkey.
5527 synchronized (this) {
5528 return mController != null;
5529 }
5530 }
5531
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005532 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005533 synchronized (this) {
5534 mWatchers.register(watcher);
5535 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005536 }
5537
5538 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005539 synchronized (this) {
5540 mWatchers.unregister(watcher);
5541 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005542 }
5543
Daniel Sandler69a48172010-06-23 16:29:36 -04005544 public void setImmersive(IBinder token, boolean immersive) {
5545 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005546 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005547 if (index < 0) {
5548 throw new IllegalArgumentException();
5549 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005550 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005551 r.immersive = immersive;
5552 }
5553 }
5554
5555 public boolean isImmersive(IBinder token) {
5556 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005557 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04005558 if (index < 0) {
5559 throw new IllegalArgumentException();
5560 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005561 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04005562 return r.immersive;
5563 }
5564 }
5565
5566 public boolean isTopActivityImmersive() {
5567 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005568 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04005569 return (r != null) ? r.immersive : false;
5570 }
5571 }
5572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 public final void enterSafeMode() {
5574 synchronized(this) {
5575 // It only makes sense to do this before the system is ready
5576 // and started launching other packages.
5577 if (!mSystemReady) {
5578 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005579 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005580 } catch (RemoteException e) {
5581 }
5582
5583 View v = LayoutInflater.from(mContext).inflate(
5584 com.android.internal.R.layout.safe_mode, null);
5585 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5586 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5587 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5588 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5589 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5590 lp.format = v.getBackground().getOpacity();
5591 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5592 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5593 ((WindowManager)mContext.getSystemService(
5594 Context.WINDOW_SERVICE)).addView(v, lp);
5595 }
5596 }
5597 }
5598
5599 public void noteWakeupAlarm(IIntentSender sender) {
5600 if (!(sender instanceof PendingIntentRecord)) {
5601 return;
5602 }
5603 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5604 synchronized (stats) {
5605 if (mBatteryStatsService.isOnBattery()) {
5606 mBatteryStatsService.enforceCallingPermission();
5607 PendingIntentRecord rec = (PendingIntentRecord)sender;
5608 int MY_UID = Binder.getCallingUid();
5609 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5610 BatteryStatsImpl.Uid.Pkg pkg =
5611 stats.getPackageStatsLocked(uid, rec.key.packageName);
5612 pkg.incWakeupsLocked();
5613 }
5614 }
5615 }
5616
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005617 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005618 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005619 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005621 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 // XXX Note: don't acquire main activity lock here, because the window
5623 // manager calls in with its locks held.
5624
5625 boolean killed = false;
5626 synchronized (mPidsSelfLocked) {
5627 int[] types = new int[pids.length];
5628 int worstType = 0;
5629 for (int i=0; i<pids.length; i++) {
5630 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5631 if (proc != null) {
5632 int type = proc.setAdj;
5633 types[i] = type;
5634 if (type > worstType) {
5635 worstType = type;
5636 }
5637 }
5638 }
5639
5640 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5641 // then constrain it so we will kill all hidden procs.
5642 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5643 worstType = HIDDEN_APP_MIN_ADJ;
5644 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005645 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005646 for (int i=0; i<pids.length; i++) {
5647 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5648 if (proc == null) {
5649 continue;
5650 }
5651 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005652 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005653 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005654 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5655 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005657 proc.killedBackground = true;
5658 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 }
5660 }
5661 }
5662 return killed;
5663 }
5664
5665 public void reportPss(IApplicationThread caller, int pss) {
5666 Watchdog.PssRequestor req;
5667 String name;
5668 ProcessRecord callerApp;
5669 synchronized (this) {
5670 if (caller == null) {
5671 return;
5672 }
5673 callerApp = getRecordForAppLocked(caller);
5674 if (callerApp == null) {
5675 return;
5676 }
5677 callerApp.lastPss = pss;
5678 req = callerApp;
5679 name = callerApp.processName;
5680 }
5681 Watchdog.getInstance().reportPss(req, name, pss);
5682 if (!callerApp.persistent) {
5683 removeRequestedPss(callerApp);
5684 }
5685 }
5686
5687 public void requestPss(Runnable completeCallback) {
5688 ArrayList<ProcessRecord> procs;
5689 synchronized (this) {
5690 mRequestPssCallback = completeCallback;
5691 mRequestPssList.clear();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005692 for (int i=mLruProcesses.size()-1; i>=0; i--) {
5693 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694 if (!proc.persistent) {
5695 mRequestPssList.add(proc);
5696 }
5697 }
5698 procs = new ArrayList<ProcessRecord>(mRequestPssList);
5699 }
5700
5701 int oldPri = Process.getThreadPriority(Process.myTid());
5702 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
5703 for (int i=procs.size()-1; i>=0; i--) {
5704 ProcessRecord proc = procs.get(i);
5705 proc.lastPss = 0;
5706 proc.requestPss();
5707 }
5708 Process.setThreadPriority(oldPri);
5709 }
5710
5711 void removeRequestedPss(ProcessRecord proc) {
5712 Runnable callback = null;
5713 synchronized (this) {
5714 if (mRequestPssList.remove(proc)) {
5715 if (mRequestPssList.size() == 0) {
5716 callback = mRequestPssCallback;
5717 mRequestPssCallback = null;
5718 }
5719 }
5720 }
5721
5722 if (callback != null) {
5723 callback.run();
5724 }
5725 }
5726
5727 public void collectPss(Watchdog.PssStats stats) {
5728 stats.mEmptyPss = 0;
5729 stats.mEmptyCount = 0;
5730 stats.mBackgroundPss = 0;
5731 stats.mBackgroundCount = 0;
5732 stats.mServicePss = 0;
5733 stats.mServiceCount = 0;
5734 stats.mVisiblePss = 0;
5735 stats.mVisibleCount = 0;
5736 stats.mForegroundPss = 0;
5737 stats.mForegroundCount = 0;
5738 stats.mNoPssCount = 0;
5739 synchronized (this) {
5740 int i;
5741 int NPD = mProcDeaths.length < stats.mProcDeaths.length
5742 ? mProcDeaths.length : stats.mProcDeaths.length;
5743 int aggr = 0;
5744 for (i=0; i<NPD; i++) {
5745 aggr += mProcDeaths[i];
5746 stats.mProcDeaths[i] = aggr;
5747 }
5748 while (i<stats.mProcDeaths.length) {
5749 stats.mProcDeaths[i] = 0;
5750 i++;
5751 }
5752
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005753 for (i=mLruProcesses.size()-1; i>=0; i--) {
5754 ProcessRecord proc = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005755 if (proc.persistent) {
5756 continue;
5757 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005758 //Slog.i(TAG, "Proc " + proc + ": pss=" + proc.lastPss);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005759 if (proc.lastPss == 0) {
5760 stats.mNoPssCount++;
5761 continue;
5762 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005763 if (proc.setAdj >= HIDDEN_APP_MIN_ADJ) {
5764 if (proc.empty) {
5765 stats.mEmptyPss += proc.lastPss;
5766 stats.mEmptyCount++;
5767 } else {
5768 stats.mBackgroundPss += proc.lastPss;
5769 stats.mBackgroundCount++;
5770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005771 } else if (proc.setAdj >= VISIBLE_APP_ADJ) {
5772 stats.mVisiblePss += proc.lastPss;
5773 stats.mVisibleCount++;
5774 } else {
5775 stats.mForegroundPss += proc.lastPss;
5776 stats.mForegroundCount++;
5777 }
5778 }
5779 }
5780 }
5781
5782 public final void startRunning(String pkg, String cls, String action,
5783 String data) {
5784 synchronized(this) {
5785 if (mStartRunning) {
5786 return;
5787 }
5788 mStartRunning = true;
5789 mTopComponent = pkg != null && cls != null
5790 ? new ComponentName(pkg, cls) : null;
5791 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5792 mTopData = data;
5793 if (!mSystemReady) {
5794 return;
5795 }
5796 }
5797
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005798 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 }
5800
5801 private void retrieveSettings() {
5802 final ContentResolver resolver = mContext.getContentResolver();
5803 String debugApp = Settings.System.getString(
5804 resolver, Settings.System.DEBUG_APP);
5805 boolean waitForDebugger = Settings.System.getInt(
5806 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5807 boolean alwaysFinishActivities = Settings.System.getInt(
5808 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5809
5810 Configuration configuration = new Configuration();
5811 Settings.System.getConfiguration(resolver, configuration);
5812
5813 synchronized (this) {
5814 mDebugApp = mOrigDebugApp = debugApp;
5815 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5816 mAlwaysFinishActivities = alwaysFinishActivities;
5817 // This happens before any activities are started, so we can
5818 // change mConfiguration in-place.
5819 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005820 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005821 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 }
5823 }
5824
5825 public boolean testIsSystemReady() {
5826 // no need to synchronize(this) just to read & return the value
5827 return mSystemReady;
5828 }
5829
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005830 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005831 // In the simulator, startRunning will never have been called, which
5832 // normally sets a few crucial variables. Do it here instead.
5833 if (!Process.supportsProcesses()) {
5834 mStartRunning = true;
5835 mTopAction = Intent.ACTION_MAIN;
5836 }
5837
5838 synchronized(this) {
5839 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005840 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005841 return;
5842 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005843
5844 // Check to see if there are any update receivers to run.
5845 if (!mDidUpdate) {
5846 if (mWaitingUpdate) {
5847 return;
5848 }
5849 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
5850 List<ResolveInfo> ris = null;
5851 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005852 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005853 intent, null, 0);
5854 } catch (RemoteException e) {
5855 }
5856 if (ris != null) {
5857 for (int i=ris.size()-1; i>=0; i--) {
5858 if ((ris.get(i).activityInfo.applicationInfo.flags
5859 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5860 ris.remove(i);
5861 }
5862 }
5863 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
5864 for (int i=0; i<ris.size(); i++) {
5865 ActivityInfo ai = ris.get(i).activityInfo;
5866 intent.setComponent(new ComponentName(ai.packageName, ai.name));
5867 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08005868 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005869 finisher = new IIntentReceiver.Stub() {
5870 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07005871 String data, Bundle extras, boolean ordered,
5872 boolean sticky)
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005873 throws RemoteException {
5874 synchronized (ActivityManagerService.this) {
5875 mDidUpdate = true;
5876 }
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005877 systemReady(goingCallback);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005878 }
5879 };
5880 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005881 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005882 broadcastIntentLocked(null, null, intent, null, finisher,
5883 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08005884 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005885 mWaitingUpdate = true;
5886 }
5887 }
5888 }
5889 if (mWaitingUpdate) {
5890 return;
5891 }
5892 mDidUpdate = true;
5893 }
5894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895 mSystemReady = true;
5896 if (!mStartRunning) {
5897 return;
5898 }
5899 }
5900
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005901 ArrayList<ProcessRecord> procsToKill = null;
5902 synchronized(mPidsSelfLocked) {
5903 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
5904 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
5905 if (!isAllowedWhileBooting(proc.info)){
5906 if (procsToKill == null) {
5907 procsToKill = new ArrayList<ProcessRecord>();
5908 }
5909 procsToKill.add(proc);
5910 }
5911 }
5912 }
5913
5914 if (procsToKill != null) {
5915 synchronized(this) {
5916 for (int i=procsToKill.size()-1; i>=0; i--) {
5917 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005918 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005919 removeProcessLocked(proc, true);
5920 }
5921 }
5922 }
5923
Joe Onorato8a9b2202010-02-26 18:56:32 -08005924 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005925 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005926 SystemClock.uptimeMillis());
5927
5928 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005929 // Make sure we have no pre-ready processes sitting around.
5930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
5932 ResolveInfo ri = mContext.getPackageManager()
5933 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07005934 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 CharSequence errorMsg = null;
5936 if (ri != null) {
5937 ActivityInfo ai = ri.activityInfo;
5938 ApplicationInfo app = ai.applicationInfo;
5939 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
5940 mTopAction = Intent.ACTION_FACTORY_TEST;
5941 mTopData = null;
5942 mTopComponent = new ComponentName(app.packageName,
5943 ai.name);
5944 } else {
5945 errorMsg = mContext.getResources().getText(
5946 com.android.internal.R.string.factorytest_not_system);
5947 }
5948 } else {
5949 errorMsg = mContext.getResources().getText(
5950 com.android.internal.R.string.factorytest_no_action);
5951 }
5952 if (errorMsg != null) {
5953 mTopAction = null;
5954 mTopData = null;
5955 mTopComponent = null;
5956 Message msg = Message.obtain();
5957 msg.what = SHOW_FACTORY_ERROR_MSG;
5958 msg.getData().putCharSequence("msg", errorMsg);
5959 mHandler.sendMessage(msg);
5960 }
5961 }
5962 }
5963
5964 retrieveSettings();
5965
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005966 if (goingCallback != null) goingCallback.run();
5967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 synchronized (this) {
5969 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
5970 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005971 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005972 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005973 if (apps != null) {
5974 int N = apps.size();
5975 int i;
5976 for (i=0; i<N; i++) {
5977 ApplicationInfo info
5978 = (ApplicationInfo)apps.get(i);
5979 if (info != null &&
5980 !info.packageName.equals("android")) {
5981 addAppLocked(info);
5982 }
5983 }
5984 }
5985 } catch (RemoteException ex) {
5986 // pm is in same process, this will never happen.
5987 }
5988 }
5989
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005990 // Start up initial activity.
5991 mBooting = true;
5992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005993 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005994 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005995 Message msg = Message.obtain();
5996 msg.what = SHOW_UID_ERROR_MSG;
5997 mHandler.sendMessage(msg);
5998 }
5999 } catch (RemoteException e) {
6000 }
6001
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006002 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 }
6004 }
6005
Dan Egnorb7f03672009-12-09 16:22:32 -08006006 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006007 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006008 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006009 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006010 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006011 startAppProblemLocked(app);
6012 app.stopFreezingAllLocked();
6013 return handleAppCrashLocked(app);
6014 }
6015
Dan Egnorb7f03672009-12-09 16:22:32 -08006016 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006017 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006018 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006019 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006020 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6021 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 startAppProblemLocked(app);
6023 app.stopFreezingAllLocked();
6024 }
6025
6026 /**
6027 * Generate a process error record, suitable for attachment to a ProcessRecord.
6028 *
6029 * @param app The ProcessRecord in which the error occurred.
6030 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6031 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006032 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 * @param shortMsg Short message describing the crash.
6034 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006035 * @param stackTrace Full crash stack trace, may be null.
6036 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006037 * @return Returns a fully-formed AppErrorStateInfo record.
6038 */
6039 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006040 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 report.condition = condition;
6044 report.processName = app.processName;
6045 report.pid = app.pid;
6046 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006047 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 report.shortMsg = shortMsg;
6049 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006050 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051
6052 return report;
6053 }
6054
Dan Egnor42471dd2010-01-07 17:25:22 -08006055 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 synchronized (this) {
6057 app.crashing = false;
6058 app.crashingReport = null;
6059 app.notResponding = false;
6060 app.notRespondingReport = null;
6061 if (app.anrDialog == fromDialog) {
6062 app.anrDialog = null;
6063 }
6064 if (app.waitDialog == fromDialog) {
6065 app.waitDialog = null;
6066 }
6067 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006068 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006069 Slog.i(ActivityManagerService.TAG, "Killing "
6070 + app.processName + " (pid=" + app.pid + "): user's request");
6071 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6072 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006073 Process.killProcess(app.pid);
6074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006075 }
6076 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006077
Dan Egnorb7f03672009-12-09 16:22:32 -08006078 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 long now = SystemClock.uptimeMillis();
6080
6081 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6082 app.info.uid);
6083 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6084 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006085 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006087 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006088 app.info.processName, app.info.uid);
6089 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006090 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6091 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006092 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006093 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006094 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006095 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006096 }
6097 }
6098 if (!app.persistent) {
6099 // We don't want to start this process again until the user
6100 // explicitly does so... but for persistent process, we really
6101 // need to keep it running. If a persistent process is actually
6102 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006103 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006104 app.info.processName);
6105 mBadProcesses.put(app.info.processName, app.info.uid, now);
6106 app.bad = true;
6107 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6108 app.removed = true;
6109 removeProcessLocked(app, false);
6110 return false;
6111 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006112 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006113 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006114 if (r.app == app) {
6115 // If the top running activity is from this crashing
6116 // process, then terminate it to avoid getting in a loop.
6117 Slog.w(TAG, " Force finishing activity "
6118 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006119 int index = mMainStack.indexOfTokenLocked(r);
6120 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006121 Activity.RESULT_CANCELED, null, "crashed");
6122 // Also terminate an activities below it that aren't yet
6123 // stopped, to avoid a situation where one will get
6124 // re-start our crashing activity once it gets resumed again.
6125 index--;
6126 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006127 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006128 if (r.state == ActivityState.RESUMED
6129 || r.state == ActivityState.PAUSING
6130 || r.state == ActivityState.PAUSED) {
6131 if (!r.isHomeActivity) {
6132 Slog.w(TAG, " Force finishing activity "
6133 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006134 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006135 Activity.RESULT_CANCELED, null, "crashed");
6136 }
6137 }
6138 }
6139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006140 }
6141
6142 // Bump up the crash count of any services currently running in the proc.
6143 if (app.services.size() != 0) {
6144 // Any services running in the application need to be placed
6145 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006146 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006147 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006148 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006149 sr.crashCount++;
6150 }
6151 }
6152
6153 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6154 return true;
6155 }
6156
6157 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006158 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6159 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 skipCurrentReceiverLocked(app);
6161 }
6162
6163 void skipCurrentReceiverLocked(ProcessRecord app) {
6164 boolean reschedule = false;
6165 BroadcastRecord r = app.curReceiver;
6166 if (r != null) {
6167 // The current broadcast is waiting for this app's receiver
6168 // to be finished. Looks like that's not going to happen, so
6169 // let the broadcast continue.
6170 logBroadcastReceiverDiscard(r);
6171 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6172 r.resultExtras, r.resultAbort, true);
6173 reschedule = true;
6174 }
6175 r = mPendingBroadcast;
6176 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006177 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006178 "skip & discard pending app " + r);
6179 logBroadcastReceiverDiscard(r);
6180 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6181 r.resultExtras, r.resultAbort, true);
6182 reschedule = true;
6183 }
6184 if (reschedule) {
6185 scheduleBroadcastsLocked();
6186 }
6187 }
6188
Dan Egnor60d87622009-12-16 16:32:58 -08006189 /**
6190 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6191 * The application process will exit immediately after this call returns.
6192 * @param app object of the crashing app, null for the system server
6193 * @param crashInfo describing the exception
6194 */
6195 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6196 ProcessRecord r = findAppProcess(app);
6197
6198 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6199 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006200 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006201 crashInfo.exceptionClassName,
6202 crashInfo.exceptionMessage,
6203 crashInfo.throwFileName,
6204 crashInfo.throwLineNumber);
6205
Dan Egnor42471dd2010-01-07 17:25:22 -08006206 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006207
6208 crashApplication(r, crashInfo);
6209 }
6210
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006211 public void handleApplicationStrictModeViolation(
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006212 IBinder app, int violationMask, ApplicationErrorReport.CrashInfo crashInfo) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006213 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006214
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006215 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006216 Integer stackFingerprint = crashInfo.stackTrace.hashCode();
6217 boolean logIt = true;
6218 synchronized (mAlreadyLoggedViolatedStacks) {
6219 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6220 logIt = false;
6221 // TODO: sub-sample into EventLog for these, with
6222 // the crashInfo.durationMillis? Then we'd get
6223 // the relative pain numbers, without logging all
6224 // the stack traces repeatedly. We'd want to do
6225 // likewise in the client code, which also does
6226 // dup suppression, before the Binder call.
6227 } else {
6228 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6229 mAlreadyLoggedViolatedStacks.clear();
6230 }
6231 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6232 }
6233 }
6234 if (logIt) {
6235 addErrorToDropBox("strictmode", r, null, null, null, null, null, crashInfo);
6236 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006237 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006238
6239 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6240 AppErrorResult result = new AppErrorResult();
6241 synchronized (this) {
6242 final long origId = Binder.clearCallingIdentity();
6243
6244 Message msg = Message.obtain();
6245 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6246 HashMap<String, Object> data = new HashMap<String, Object>();
6247 data.put("result", result);
6248 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006249 data.put("violationMask", violationMask);
6250 data.put("crashInfo", crashInfo);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006251 msg.obj = data;
6252 mHandler.sendMessage(msg);
6253
6254 Binder.restoreCallingIdentity(origId);
6255 }
6256 int res = result.get();
6257 Log.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
6258 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006259 }
6260
Dan Egnor60d87622009-12-16 16:32:58 -08006261 /**
6262 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6263 * @param app object of the crashing app, null for the system server
6264 * @param tag reported by the caller
6265 * @param crashInfo describing the context of the error
6266 * @return true if the process should exit immediately (WTF is fatal)
6267 */
6268 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006269 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006270 ProcessRecord r = findAppProcess(app);
6271
6272 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6273 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006274 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006275 tag, crashInfo.exceptionMessage);
6276
Dan Egnor42471dd2010-01-07 17:25:22 -08006277 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006278
Doug Zongker43866e02010-01-07 12:09:54 -08006279 if (Settings.Secure.getInt(mContext.getContentResolver(),
6280 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006281 crashApplication(r, crashInfo);
6282 return true;
6283 } else {
6284 return false;
6285 }
6286 }
6287
6288 /**
6289 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6290 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6291 */
6292 private ProcessRecord findAppProcess(IBinder app) {
6293 if (app == null) {
6294 return null;
6295 }
6296
6297 synchronized (this) {
6298 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6299 final int NA = apps.size();
6300 for (int ia=0; ia<NA; ia++) {
6301 ProcessRecord p = apps.valueAt(ia);
6302 if (p.thread != null && p.thread.asBinder() == app) {
6303 return p;
6304 }
6305 }
6306 }
6307
Joe Onorato8a9b2202010-02-26 18:56:32 -08006308 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006309 return null;
6310 }
6311 }
6312
6313 /**
Dan Egnor42471dd2010-01-07 17:25:22 -08006314 * Write a description of an error (crash, WTF, ANR) to the drop box.
Dan Egnor60d87622009-12-16 16:32:58 -08006315 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
Dan Egnor42471dd2010-01-07 17:25:22 -08006316 * @param process which caused the error, null means the system server
6317 * @param activity which triggered the error, null if unknown
6318 * @param parent activity related to the error, null if unknown
6319 * @param subject line related to the error, null if absent
6320 * @param report in long form describing the error, null if absent
6321 * @param logFile to include in the report, null if none
6322 * @param crashInfo giving an application stack trace, null if absent
Dan Egnor60d87622009-12-16 16:32:58 -08006323 */
Dan Egnor9bdc94b2010-03-04 14:20:31 -08006324 public void addErrorToDropBox(String eventType,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006325 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
Dan Egnora455d192010-03-12 08:52:28 -08006326 final String report, final File logFile,
6327 final ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor9bdc94b2010-03-04 14:20:31 -08006328 // NOTE -- this must never acquire the ActivityManagerService lock,
6329 // otherwise the watchdog may be prevented from resetting the system.
6330
Dan Egnora455d192010-03-12 08:52:28 -08006331 String prefix;
Dan Egnor42471dd2010-01-07 17:25:22 -08006332 if (process == null || process.pid == MY_PID) {
Dan Egnora455d192010-03-12 08:52:28 -08006333 prefix = "system_server_";
Dan Egnor42471dd2010-01-07 17:25:22 -08006334 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dan Egnora455d192010-03-12 08:52:28 -08006335 prefix = "system_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08006336 } else {
Dan Egnora455d192010-03-12 08:52:28 -08006337 prefix = "data_app_";
Dan Egnor60d87622009-12-16 16:32:58 -08006338 }
6339
Dan Egnora455d192010-03-12 08:52:28 -08006340 final String dropboxTag = prefix + eventType;
6341 final DropBoxManager dbox = (DropBoxManager)
6342 mContext.getSystemService(Context.DROPBOX_SERVICE);
6343
6344 // Exit early if the dropbox isn't configured to accept this report type.
6345 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6346
6347 final StringBuilder sb = new StringBuilder(1024);
6348 if (process == null || process.pid == MY_PID) {
6349 sb.append("Process: system_server\n");
6350 } else {
6351 sb.append("Process: ").append(process.processName).append("\n");
6352 }
6353 if (process != null) {
6354 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006355 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006356 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6357 for (String pkg : process.pkgList) {
6358 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006359 try {
Dan Egnora455d192010-03-12 08:52:28 -08006360 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6361 if (pi != null) {
6362 sb.append(" v").append(pi.versionCode);
6363 if (pi.versionName != null) {
6364 sb.append(" (").append(pi.versionName).append(")");
6365 }
6366 }
6367 } catch (RemoteException e) {
6368 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006369 }
Dan Egnora455d192010-03-12 08:52:28 -08006370 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006371 }
Dan Egnora455d192010-03-12 08:52:28 -08006372 }
6373 if (activity != null) {
6374 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6375 }
6376 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6377 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6378 }
6379 if (parent != null && parent != activity) {
6380 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6381 }
6382 if (subject != null) {
6383 sb.append("Subject: ").append(subject).append("\n");
6384 }
6385 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Brad Fitzpatrick04b243d2010-06-21 08:01:13 -07006386 if (crashInfo != null && crashInfo.durationMillis != -1) {
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006387 sb.append("Duration-Millis: ").append(crashInfo.durationMillis).append("\n");
6388 }
Dan Egnora455d192010-03-12 08:52:28 -08006389 sb.append("\n");
6390
6391 // Do the rest in a worker thread to avoid blocking the caller on I/O
6392 // (After this point, we shouldn't access AMS internal data structures.)
6393 Thread worker = new Thread("Error dump: " + dropboxTag) {
6394 @Override
6395 public void run() {
6396 if (report != null) {
6397 sb.append(report);
6398 }
6399 if (logFile != null) {
6400 try {
6401 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6402 } catch (IOException e) {
6403 Slog.e(TAG, "Error reading " + logFile, e);
6404 }
6405 }
6406 if (crashInfo != null && crashInfo.stackTrace != null) {
6407 sb.append(crashInfo.stackTrace);
6408 }
6409
6410 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6411 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6412 if (lines > 0) {
6413 sb.append("\n");
6414
6415 // Merge several logcat streams, and take the last N lines
6416 InputStreamReader input = null;
6417 try {
6418 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6419 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6420 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6421
6422 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6423 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6424 input = new InputStreamReader(logcat.getInputStream());
6425
6426 int num;
6427 char[] buf = new char[8192];
6428 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6429 } catch (IOException e) {
6430 Slog.e(TAG, "Error running logcat", e);
6431 } finally {
6432 if (input != null) try { input.close(); } catch (IOException e) {}
6433 }
6434 }
6435
6436 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006437 }
Dan Egnora455d192010-03-12 08:52:28 -08006438 };
6439
6440 if (process == null || process.pid == MY_PID) {
6441 worker.run(); // We may be about to die -- need to run this synchronously
6442 } else {
6443 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006444 }
6445 }
6446
6447 /**
6448 * Bring up the "unexpected error" dialog box for a crashing app.
6449 * Deal with edge cases (intercepts from instrumented applications,
6450 * ActivityController, error intent receivers, that sort of thing).
6451 * @param r the application crashing
6452 * @param crashInfo describing the failure
6453 */
6454 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006455 long timeMillis = System.currentTimeMillis();
6456 String shortMsg = crashInfo.exceptionClassName;
6457 String longMsg = crashInfo.exceptionMessage;
6458 String stackTrace = crashInfo.stackTrace;
6459 if (shortMsg != null && longMsg != null) {
6460 longMsg = shortMsg + ": " + longMsg;
6461 } else if (shortMsg != null) {
6462 longMsg = shortMsg;
6463 }
6464
Dan Egnor60d87622009-12-16 16:32:58 -08006465 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006467 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006468 try {
6469 String name = r != null ? r.processName : null;
6470 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006471 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006472 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006473 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006474 + " at watcher's request");
6475 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006476 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006477 }
6478 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006479 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 }
6481 }
6482
6483 final long origId = Binder.clearCallingIdentity();
6484
6485 // If this process is running instrumentation, finish it.
6486 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006487 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006488 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006489 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6490 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006491 Bundle info = new Bundle();
6492 info.putString("shortMsg", shortMsg);
6493 info.putString("longMsg", longMsg);
6494 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6495 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006496 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006497 }
6498
Dan Egnor60d87622009-12-16 16:32:58 -08006499 // If we can't identify the process or it's already exceeded its crash quota,
6500 // quit right away without showing a crash dialog.
6501 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006502 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006503 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006504 }
6505
6506 Message msg = Message.obtain();
6507 msg.what = SHOW_ERROR_MSG;
6508 HashMap data = new HashMap();
6509 data.put("result", result);
6510 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006511 msg.obj = data;
6512 mHandler.sendMessage(msg);
6513
6514 Binder.restoreCallingIdentity(origId);
6515 }
6516
6517 int res = result.get();
6518
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006519 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006520 synchronized (this) {
6521 if (r != null) {
6522 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6523 SystemClock.uptimeMillis());
6524 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006525 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006526 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006527 }
6528 }
6529
6530 if (appErrorIntent != null) {
6531 try {
6532 mContext.startActivity(appErrorIntent);
6533 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006534 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006537 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006538
6539 Intent createAppErrorIntentLocked(ProcessRecord r,
6540 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6541 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006542 if (report == null) {
6543 return null;
6544 }
6545 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6546 result.setComponent(r.errorReportReceiver);
6547 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6548 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6549 return result;
6550 }
6551
Dan Egnorb7f03672009-12-09 16:22:32 -08006552 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6553 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006554 if (r.errorReportReceiver == null) {
6555 return null;
6556 }
6557
6558 if (!r.crashing && !r.notResponding) {
6559 return null;
6560 }
6561
Dan Egnorb7f03672009-12-09 16:22:32 -08006562 ApplicationErrorReport report = new ApplicationErrorReport();
6563 report.packageName = r.info.packageName;
6564 report.installerPackageName = r.errorReportReceiver.getPackageName();
6565 report.processName = r.processName;
6566 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006567 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006568
Dan Egnorb7f03672009-12-09 16:22:32 -08006569 if (r.crashing) {
6570 report.type = ApplicationErrorReport.TYPE_CRASH;
6571 report.crashInfo = crashInfo;
6572 } else if (r.notResponding) {
6573 report.type = ApplicationErrorReport.TYPE_ANR;
6574 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006575
Dan Egnorb7f03672009-12-09 16:22:32 -08006576 report.anrInfo.activity = r.notRespondingReport.tag;
6577 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6578 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006579 }
6580
Dan Egnorb7f03672009-12-09 16:22:32 -08006581 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006582 }
6583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6585 // assume our apps are happy - lazy create the list
6586 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6587
6588 synchronized (this) {
6589
6590 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006591 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6592 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006593 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6594 // This one's in trouble, so we'll generate a report for it
6595 // crashes are higher priority (in case there's a crash *and* an anr)
6596 ActivityManager.ProcessErrorStateInfo report = null;
6597 if (app.crashing) {
6598 report = app.crashingReport;
6599 } else if (app.notResponding) {
6600 report = app.notRespondingReport;
6601 }
6602
6603 if (report != null) {
6604 if (errList == null) {
6605 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6606 }
6607 errList.add(report);
6608 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006609 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006610 " crashing = " + app.crashing +
6611 " notResponding = " + app.notResponding);
6612 }
6613 }
6614 }
6615 }
6616
6617 return errList;
6618 }
6619
6620 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6621 // Lazy instantiation of list
6622 List<ActivityManager.RunningAppProcessInfo> runList = null;
6623 synchronized (this) {
6624 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006625 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6626 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006627 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6628 // Generate process state info for running application
6629 ActivityManager.RunningAppProcessInfo currApp =
6630 new ActivityManager.RunningAppProcessInfo(app.processName,
6631 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006632 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006633 if (mHeavyWeightProcess == app) {
6634 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
6635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006636 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006637 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006638 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6639 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6640 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006641 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6642 } else if (adj >= HOME_APP_ADJ) {
6643 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6644 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006645 } else if (adj >= SECONDARY_SERVER_ADJ) {
6646 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006647 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6648 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6649 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6650 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 } else if (adj >= VISIBLE_APP_ADJ) {
6652 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6653 } else {
6654 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6655 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006656 currApp.importanceReasonCode = app.adjTypeCode;
6657 if (app.adjSource instanceof ProcessRecord) {
6658 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006659 } else if (app.adjSource instanceof ActivityRecord) {
6660 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006661 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6662 }
6663 if (app.adjTarget instanceof ComponentName) {
6664 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6665 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006666 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006667 // + " lru=" + currApp.lru);
6668 if (runList == null) {
6669 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6670 }
6671 runList.add(currApp);
6672 }
6673 }
6674 }
6675 return runList;
6676 }
6677
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006678 public List<ApplicationInfo> getRunningExternalApplications() {
6679 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6680 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6681 if (runningApps != null && runningApps.size() > 0) {
6682 Set<String> extList = new HashSet<String>();
6683 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6684 if (app.pkgList != null) {
6685 for (String pkg : app.pkgList) {
6686 extList.add(pkg);
6687 }
6688 }
6689 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006690 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006691 for (String pkg : extList) {
6692 try {
6693 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6694 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6695 retList.add(info);
6696 }
6697 } catch (RemoteException e) {
6698 }
6699 }
6700 }
6701 return retList;
6702 }
6703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006704 @Override
6705 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006706 if (checkCallingPermission(android.Manifest.permission.DUMP)
6707 != PackageManager.PERMISSION_GRANTED) {
6708 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6709 + Binder.getCallingPid()
6710 + ", uid=" + Binder.getCallingUid()
6711 + " without permission "
6712 + android.Manifest.permission.DUMP);
6713 return;
6714 }
6715
6716 boolean dumpAll = false;
6717
6718 int opti = 0;
6719 while (opti < args.length) {
6720 String opt = args[opti];
6721 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6722 break;
6723 }
6724 opti++;
6725 if ("-a".equals(opt)) {
6726 dumpAll = true;
6727 } else if ("-h".equals(opt)) {
6728 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006729 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006730 pw.println(" cmd may be one of:");
6731 pw.println(" activities: activity stack state");
6732 pw.println(" broadcasts: broadcast state");
6733 pw.println(" intents: pending intent state");
6734 pw.println(" processes: process state");
6735 pw.println(" providers: content provider state");
6736 pw.println(" services: service state");
6737 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006738 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006739 } else {
6740 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006742 }
6743
6744 // Is the caller requesting to dump a particular piece of data?
6745 if (opti < args.length) {
6746 String cmd = args[opti];
6747 opti++;
6748 if ("activities".equals(cmd) || "a".equals(cmd)) {
6749 synchronized (this) {
6750 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006751 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006752 return;
6753 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
6754 synchronized (this) {
6755 dumpBroadcastsLocked(fd, pw, args, opti, true);
6756 }
6757 return;
6758 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
6759 synchronized (this) {
6760 dumpPendingIntentsLocked(fd, pw, args, opti, true);
6761 }
6762 return;
6763 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
6764 synchronized (this) {
6765 dumpProcessesLocked(fd, pw, args, opti, true);
6766 }
6767 return;
6768 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
6769 synchronized (this) {
6770 dumpProvidersLocked(fd, pw, args, opti, true);
6771 }
6772 return;
6773 } else if ("service".equals(cmd)) {
6774 dumpService(fd, pw, args, opti, true);
6775 return;
6776 } else if ("services".equals(cmd) || "s".equals(cmd)) {
6777 synchronized (this) {
6778 dumpServicesLocked(fd, pw, args, opti, true);
6779 }
6780 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006781 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006782 }
6783
6784 // No piece of data specified, dump everything.
6785 synchronized (this) {
6786 boolean needSep;
6787 if (dumpAll) {
6788 pw.println("Providers in Current Activity Manager State:");
6789 }
6790 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
6791 if (needSep) {
6792 pw.println(" ");
6793 }
6794 if (dumpAll) {
6795 pw.println("-------------------------------------------------------------------------------");
6796 pw.println("Broadcasts in Current Activity Manager State:");
6797 }
6798 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
6799 if (needSep) {
6800 pw.println(" ");
6801 }
6802 if (dumpAll) {
6803 pw.println("-------------------------------------------------------------------------------");
6804 pw.println("Services in Current Activity Manager State:");
6805 }
6806 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
6807 if (needSep) {
6808 pw.println(" ");
6809 }
6810 if (dumpAll) {
6811 pw.println("-------------------------------------------------------------------------------");
6812 pw.println("PendingIntents in Current Activity Manager State:");
6813 }
6814 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
6815 if (needSep) {
6816 pw.println(" ");
6817 }
6818 if (dumpAll) {
6819 pw.println("-------------------------------------------------------------------------------");
6820 pw.println("Activities in Current Activity Manager State:");
6821 }
6822 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
6823 if (needSep) {
6824 pw.println(" ");
6825 }
6826 if (dumpAll) {
6827 pw.println("-------------------------------------------------------------------------------");
6828 pw.println("Processes in Current Activity Manager State:");
6829 }
6830 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
6831 }
6832 }
6833
6834 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6835 int opti, boolean dumpAll, boolean needHeader) {
6836 if (needHeader) {
6837 pw.println(" Activity stack:");
6838 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006839 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006840 pw.println(" ");
6841 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006842 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
6843 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006844 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006845 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006846 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006847 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006848 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006849 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006850 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006851 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006852 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006853 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006854 pw.println(" ");
6855 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006856 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006858
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006859 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006860 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
6861 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006862 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006863 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006864
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006865 if (dumpAll && mRecentTasks.size() > 0) {
6866 pw.println(" ");
6867 pw.println("Recent tasks in Current Activity Manager State:");
6868
6869 final int N = mRecentTasks.size();
6870 for (int i=0; i<N; i++) {
6871 TaskRecord tr = mRecentTasks.get(i);
6872 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
6873 pw.println(tr);
6874 mRecentTasks.get(i).dump(pw, " ");
6875 }
6876 }
6877
6878 pw.println(" ");
6879 pw.println(" mCurTask: " + mCurTask);
6880
6881 return true;
6882 }
6883
6884 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
6885 int opti, boolean dumpAll) {
6886 boolean needSep = false;
6887 int numPers = 0;
6888
6889 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006890 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
6891 final int NA = procs.size();
6892 for (int ia=0; ia<NA; ia++) {
6893 if (!needSep) {
6894 pw.println(" All known processes:");
6895 needSep = true;
6896 }
6897 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006898 pw.print(r.persistent ? " *PERS*" : " *APP*");
6899 pw.print(" UID "); pw.print(procs.keyAt(ia));
6900 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006901 r.dump(pw, " ");
6902 if (r.persistent) {
6903 numPers++;
6904 }
6905 }
6906 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006907 }
6908
6909 if (mLruProcesses.size() > 0) {
6910 if (needSep) pw.println(" ");
6911 needSep = true;
6912 pw.println(" Running processes (most recent first):");
6913 dumpProcessList(pw, this, mLruProcesses, " ",
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006914 "Proc", "PERS", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006915 needSep = true;
6916 }
6917
6918 synchronized (mPidsSelfLocked) {
6919 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006920 if (needSep) pw.println(" ");
6921 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006922 pw.println(" PID mappings:");
6923 for (int i=0; i<mPidsSelfLocked.size(); i++) {
6924 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
6925 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006926 }
6927 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006928 }
6929
6930 if (mForegroundProcesses.size() > 0) {
6931 if (needSep) pw.println(" ");
6932 needSep = true;
6933 pw.println(" Foreground Processes:");
6934 for (int i=0; i<mForegroundProcesses.size(); i++) {
6935 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
6936 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006938 }
6939
6940 if (mPersistentStartingProcesses.size() > 0) {
6941 if (needSep) pw.println(" ");
6942 needSep = true;
6943 pw.println(" Persisent processes that are starting:");
6944 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
6945 "Starting Norm", "Restarting PERS", false);
6946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006947
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006948 if (mStartingProcesses.size() > 0) {
6949 if (needSep) pw.println(" ");
6950 needSep = true;
6951 pw.println(" Processes that are starting:");
6952 dumpProcessList(pw, this, mStartingProcesses, " ",
6953 "Starting Norm", "Starting PERS", false);
6954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006955
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006956 if (mRemovedProcesses.size() > 0) {
6957 if (needSep) pw.println(" ");
6958 needSep = true;
6959 pw.println(" Processes that are being removed:");
6960 dumpProcessList(pw, this, mRemovedProcesses, " ",
6961 "Removed Norm", "Removed PERS", false);
6962 }
6963
6964 if (mProcessesOnHold.size() > 0) {
6965 if (needSep) pw.println(" ");
6966 needSep = true;
6967 pw.println(" Processes that are on old until the system is ready:");
6968 dumpProcessList(pw, this, mProcessesOnHold, " ",
6969 "OnHold Norm", "OnHold PERS", false);
6970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006971
Dianne Hackbornc59411b2009-12-21 20:10:14 -08006972 if (mProcessesToGc.size() > 0) {
6973 if (needSep) pw.println(" ");
6974 needSep = true;
6975 pw.println(" Processes that are waiting to GC:");
6976 long now = SystemClock.uptimeMillis();
6977 for (int i=0; i<mProcessesToGc.size(); i++) {
6978 ProcessRecord proc = mProcessesToGc.get(i);
6979 pw.print(" Process "); pw.println(proc);
6980 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
6981 pw.print(", last gced=");
6982 pw.print(now-proc.lastRequestedGc);
6983 pw.print(" ms ago, last lowMem=");
6984 pw.print(now-proc.lastLowMemory);
6985 pw.println(" ms ago");
6986
6987 }
6988 }
6989
6990 if (mProcessCrashTimes.getMap().size() > 0) {
6991 if (needSep) pw.println(" ");
6992 needSep = true;
6993 pw.println(" Time since processes crashed:");
6994 long now = SystemClock.uptimeMillis();
6995 for (Map.Entry<String, SparseArray<Long>> procs
6996 : mProcessCrashTimes.getMap().entrySet()) {
6997 SparseArray<Long> uids = procs.getValue();
6998 final int N = uids.size();
6999 for (int i=0; i<N; i++) {
7000 pw.print(" Process "); pw.print(procs.getKey());
7001 pw.print(" uid "); pw.print(uids.keyAt(i));
7002 pw.print(": last crashed ");
7003 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007004 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007005 }
7006 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007008
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007009 if (mBadProcesses.getMap().size() > 0) {
7010 if (needSep) pw.println(" ");
7011 needSep = true;
7012 pw.println(" Bad processes:");
7013 for (Map.Entry<String, SparseArray<Long>> procs
7014 : mBadProcesses.getMap().entrySet()) {
7015 SparseArray<Long> uids = procs.getValue();
7016 final int N = uids.size();
7017 for (int i=0; i<N; i++) {
7018 pw.print(" Bad process "); pw.print(procs.getKey());
7019 pw.print(" uid "); pw.print(uids.keyAt(i));
7020 pw.print(": crashed at time ");
7021 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007022 }
7023 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007025
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007026 pw.println(" ");
7027 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007028 if (mHeavyWeightProcess != null) {
7029 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7030 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007031 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007032 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007033 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7034 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7035 || mOrigWaitForDebugger) {
7036 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7037 + " mDebugTransient=" + mDebugTransient
7038 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7039 }
7040 if (mAlwaysFinishActivities || mController != null) {
7041 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7042 + " mController=" + mController);
7043 }
7044 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007045 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046 pw.println(" mStartRunning=" + mStartRunning
7047 + " mSystemReady=" + mSystemReady
7048 + " mBooting=" + mBooting
7049 + " mBooted=" + mBooted
7050 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007051 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7052 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007053 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007055
7056 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007057 }
7058
7059 /**
7060 * There are three ways to call this:
7061 * - no service specified: dump all the services
7062 * - a flattened component name that matched an existing service was specified as the
7063 * first arg: dump that one service
7064 * - the first arg isn't the flattened component name of an existing service:
7065 * dump all services whose component contains the first arg as a substring
7066 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007067 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7068 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007069 String[] newArgs;
7070 String componentNameString;
7071 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007072 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007073 componentNameString = null;
7074 newArgs = EMPTY_STRING_ARRAY;
7075 r = null;
7076 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007077 componentNameString = args[opti];
7078 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007079 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
7080 r = componentName != null ? mServices.get(componentName) : null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007081 newArgs = new String[args.length - opti];
7082 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007083 }
7084
7085 if (r != null) {
7086 dumpService(fd, pw, r, newArgs);
7087 } else {
7088 for (ServiceRecord r1 : mServices.values()) {
7089 if (componentNameString == null
7090 || r1.name.flattenToString().contains(componentNameString)) {
7091 dumpService(fd, pw, r1, newArgs);
7092 }
7093 }
7094 }
7095 }
7096
7097 /**
7098 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7099 * there is a thread associated with the service.
7100 */
7101 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7102 pw.println(" Service " + r.name.flattenToString());
7103 if (r.app != null && r.app.thread != null) {
7104 try {
7105 // flush anything that is already in the PrintWriter since the thread is going
7106 // to write to the file descriptor directly
7107 pw.flush();
7108 r.app.thread.dumpService(fd, r, args);
7109 pw.print("\n");
7110 } catch (RemoteException e) {
7111 pw.println("got a RemoteException while dumping the service");
7112 }
7113 }
7114 }
7115
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007116 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7117 int opti, boolean dumpAll) {
7118 boolean needSep = false;
7119
7120 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007121 if (mRegisteredReceivers.size() > 0) {
7122 pw.println(" ");
7123 pw.println(" Registered Receivers:");
7124 Iterator it = mRegisteredReceivers.values().iterator();
7125 while (it.hasNext()) {
7126 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007127 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007128 r.dump(pw, " ");
7129 }
7130 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007132 pw.println(" ");
7133 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007134 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007135 needSep = true;
7136 }
7137
7138 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7139 || mPendingBroadcast != null) {
7140 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007141 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007142 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007143 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007144 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7145 pw.println(" Broadcast #" + i + ":");
7146 mParallelBroadcasts.get(i).dump(pw, " ");
7147 }
7148 if (mOrderedBroadcasts.size() > 0) {
7149 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007150 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007151 }
7152 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7153 pw.println(" Serialized Broadcast #" + i + ":");
7154 mOrderedBroadcasts.get(i).dump(pw, " ");
7155 }
7156 pw.println(" ");
7157 pw.println(" Pending broadcast:");
7158 if (mPendingBroadcast != null) {
7159 mPendingBroadcast.dump(pw, " ");
7160 } else {
7161 pw.println(" (null)");
7162 }
7163 needSep = true;
7164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007166 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007167 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007168 pw.println(" Historical broadcasts:");
7169 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7170 BroadcastRecord r = mBroadcastHistory[i];
7171 if (r == null) {
7172 break;
7173 }
7174 pw.println(" Historical Broadcast #" + i + ":");
7175 r.dump(pw, " ");
7176 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007177 needSep = true;
7178 }
7179
7180 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007181 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007182 pw.println(" Sticky broadcasts:");
7183 StringBuilder sb = new StringBuilder(128);
7184 for (Map.Entry<String, ArrayList<Intent>> ent
7185 : mStickyBroadcasts.entrySet()) {
7186 pw.print(" * Sticky action "); pw.print(ent.getKey());
7187 pw.println(":");
7188 ArrayList<Intent> intents = ent.getValue();
7189 final int N = intents.size();
7190 for (int i=0; i<N; i++) {
7191 sb.setLength(0);
7192 sb.append(" Intent: ");
7193 intents.get(i).toShortString(sb, true, false);
7194 pw.println(sb.toString());
7195 Bundle bundle = intents.get(i).getExtras();
7196 if (bundle != null) {
7197 pw.print(" ");
7198 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007199 }
7200 }
7201 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007202 needSep = true;
7203 }
7204
7205 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007206 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007207 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007208 pw.println(" mHandler:");
7209 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007210 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007211 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007212
7213 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007214 }
7215
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007216 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7217 int opti, boolean dumpAll) {
7218 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007219
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007220 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007221 if (mServices.size() > 0) {
7222 pw.println(" Active services:");
7223 Iterator<ServiceRecord> it = mServices.values().iterator();
7224 while (it.hasNext()) {
7225 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007226 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227 r.dump(pw, " ");
7228 }
7229 needSep = true;
7230 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007233 if (mPendingServices.size() > 0) {
7234 if (needSep) pw.println(" ");
7235 pw.println(" Pending services:");
7236 for (int i=0; i<mPendingServices.size(); i++) {
7237 ServiceRecord r = mPendingServices.get(i);
7238 pw.print(" * Pending "); pw.println(r);
7239 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007240 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007241 needSep = true;
7242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007243
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007244 if (mRestartingServices.size() > 0) {
7245 if (needSep) pw.println(" ");
7246 pw.println(" Restarting services:");
7247 for (int i=0; i<mRestartingServices.size(); i++) {
7248 ServiceRecord r = mRestartingServices.get(i);
7249 pw.print(" * Restarting "); pw.println(r);
7250 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007252 needSep = true;
7253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007254
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007255 if (mStoppingServices.size() > 0) {
7256 if (needSep) pw.println(" ");
7257 pw.println(" Stopping services:");
7258 for (int i=0; i<mStoppingServices.size(); i++) {
7259 ServiceRecord r = mStoppingServices.get(i);
7260 pw.print(" * Stopping "); pw.println(r);
7261 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007263 needSep = true;
7264 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007265
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007266 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007267 if (mServiceConnections.size() > 0) {
7268 if (needSep) pw.println(" ");
7269 pw.println(" Connection bindings to services:");
7270 Iterator<ConnectionRecord> it
7271 = mServiceConnections.values().iterator();
7272 while (it.hasNext()) {
7273 ConnectionRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007274 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275 r.dump(pw, " ");
7276 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007277 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007278 }
7279 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007280
7281 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007282 }
7283
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007284 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7285 int opti, boolean dumpAll) {
7286 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007287
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007288 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007289 if (mProvidersByClass.size() > 0) {
7290 if (needSep) pw.println(" ");
7291 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007292 Iterator<Map.Entry<String, ContentProviderRecord>> it
7293 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007294 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007295 Map.Entry<String, ContentProviderRecord> e = it.next();
7296 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007297 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007298 r.dump(pw, " ");
7299 }
7300 needSep = true;
7301 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007302
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007303 if (mProvidersByName.size() > 0) {
7304 pw.println(" ");
7305 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007306 Iterator<Map.Entry<String, ContentProviderRecord>> it
7307 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007308 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007309 Map.Entry<String, ContentProviderRecord> e = it.next();
7310 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007311 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7312 pw.println(r);
7313 }
7314 needSep = true;
7315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007316 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007317
7318 if (mLaunchingProviders.size() > 0) {
7319 if (needSep) pw.println(" ");
7320 pw.println(" Launching content providers:");
7321 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7322 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7323 pw.println(mLaunchingProviders.get(i));
7324 }
7325 needSep = true;
7326 }
7327
7328 if (mGrantedUriPermissions.size() > 0) {
7329 pw.println();
7330 pw.println("Granted Uri Permissions:");
7331 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7332 int uid = mGrantedUriPermissions.keyAt(i);
7333 HashMap<Uri, UriPermission> perms
7334 = mGrantedUriPermissions.valueAt(i);
7335 pw.print(" * UID "); pw.print(uid);
7336 pw.println(" holds:");
7337 for (UriPermission perm : perms.values()) {
7338 pw.print(" "); pw.println(perm);
7339 perm.dump(pw, " ");
7340 }
7341 }
7342 needSep = true;
7343 }
7344
7345 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 }
7347
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007348 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7349 int opti, boolean dumpAll) {
7350 boolean needSep = false;
7351
7352 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 if (this.mIntentSenderRecords.size() > 0) {
7354 Iterator<WeakReference<PendingIntentRecord>> it
7355 = mIntentSenderRecords.values().iterator();
7356 while (it.hasNext()) {
7357 WeakReference<PendingIntentRecord> ref = it.next();
7358 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007359 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007361 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362 rec.dump(pw, " ");
7363 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007364 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 }
7366 }
7367 }
7368 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007369
7370 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 }
7372
7373 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007374 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007375 TaskRecord lastTask = null;
7376 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007377 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007378 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007379 if (lastTask != r.task) {
7380 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007381 pw.print(prefix);
7382 pw.print(full ? "* " : " ");
7383 pw.println(lastTask);
7384 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007385 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007388 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7389 pw.print(" #"); pw.print(i); pw.print(": ");
7390 pw.println(r);
7391 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007392 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007394 }
7395 }
7396
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007397 private static String buildOomTag(String prefix, String space, int val, int base) {
7398 if (val == base) {
7399 if (space == null) return prefix;
7400 return prefix + " ";
7401 }
7402 return prefix + "+" + Integer.toString(val-base);
7403 }
7404
7405 private static final int dumpProcessList(PrintWriter pw,
7406 ActivityManagerService service, List list,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 String prefix, String normalLabel, String persistentLabel,
7408 boolean inclOomAdj) {
7409 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007410 final int N = list.size()-1;
7411 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007412 ProcessRecord r = (ProcessRecord)list.get(i);
7413 if (false) {
7414 pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
7415 + " #" + i + ":");
7416 r.dump(pw, prefix + " ");
7417 } else if (inclOomAdj) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007418 String oomAdj;
7419 if (r.setAdj >= EMPTY_APP_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007420 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007421 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007422 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7423 } else if (r.setAdj >= HOME_APP_ADJ) {
7424 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7425 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7426 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7427 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7428 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007429 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7430 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7431 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7432 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007433 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7434 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7435 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7436 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007437 } else if (r.setAdj >= CORE_SERVER_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007438 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007439 } else if (r.setAdj >= SYSTEM_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007440 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007441 } else {
7442 oomAdj = Integer.toString(r.setAdj);
7443 }
7444 String schedGroup;
7445 switch (r.setSchedGroup) {
7446 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7447 schedGroup = "B";
7448 break;
7449 case Process.THREAD_GROUP_DEFAULT:
7450 schedGroup = "F";
7451 break;
7452 default:
7453 schedGroup = Integer.toString(r.setSchedGroup);
7454 break;
7455 }
7456 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007457 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007458 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007459 if (r.adjSource != null || r.adjTarget != null) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007460 pw.print(prefix);
7461 pw.print(" ");
7462 if (r.adjTarget instanceof ComponentName) {
7463 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7464 } else if (r.adjTarget != null) {
7465 pw.print(r.adjTarget.toString());
7466 } else {
7467 pw.print("{null}");
7468 }
7469 pw.print("<=");
7470 if (r.adjSource instanceof ProcessRecord) {
7471 pw.print("Proc{");
7472 pw.print(((ProcessRecord)r.adjSource).toShortString());
7473 pw.println("}");
7474 } else if (r.adjSource != null) {
7475 pw.println(r.adjSource.toString());
7476 } else {
7477 pw.println("{null}");
7478 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007479 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007480 } else {
7481 pw.println(String.format("%s%s #%2d: %s",
7482 prefix, (r.persistent ? persistentLabel : normalLabel),
7483 i, r.toString()));
7484 }
7485 if (r.persistent) {
7486 numPers++;
7487 }
7488 }
7489 return numPers;
7490 }
7491
Dianne Hackborn472ad872010-04-07 17:31:48 -07007492 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007493 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007494 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 long uptime = SystemClock.uptimeMillis();
7496 long realtime = SystemClock.elapsedRealtime();
7497
7498 if (isCheckinRequest) {
7499 // short checkin version
7500 pw.println(uptime + "," + realtime);
7501 pw.flush();
7502 } else {
7503 pw.println("Applications Memory Usage (kB):");
7504 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7505 }
7506 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7507 ProcessRecord r = (ProcessRecord)list.get(i);
7508 if (r.thread != null) {
7509 if (!isCheckinRequest) {
7510 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7511 pw.flush();
7512 }
7513 try {
7514 r.thread.asBinder().dump(fd, args);
7515 } catch (RemoteException e) {
7516 if (!isCheckinRequest) {
7517 pw.println("Got RemoteException!");
7518 pw.flush();
7519 }
7520 }
7521 }
7522 }
7523 }
7524
7525 /**
7526 * Searches array of arguments for the specified string
7527 * @param args array of argument strings
7528 * @param value value to search for
7529 * @return true if the value is contained in the array
7530 */
7531 private static boolean scanArgs(String[] args, String value) {
7532 if (args != null) {
7533 for (String arg : args) {
7534 if (value.equals(arg)) {
7535 return true;
7536 }
7537 }
7538 }
7539 return false;
7540 }
7541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542 private final void killServicesLocked(ProcessRecord app,
7543 boolean allowRestart) {
7544 // Report disconnected services.
7545 if (false) {
7546 // XXX we are letting the client link to the service for
7547 // death notifications.
7548 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007549 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007550 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007551 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007552 if (r.connections.size() > 0) {
7553 Iterator<ConnectionRecord> jt
7554 = r.connections.values().iterator();
7555 while (jt.hasNext()) {
7556 ConnectionRecord c = jt.next();
7557 if (c.binding.client != app) {
7558 try {
7559 //c.conn.connected(r.className, null);
7560 } catch (Exception e) {
7561 // todo: this should be asynchronous!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007562 Slog.w(TAG, "Exception thrown disconnected servce "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007563 + r.shortName
7564 + " from app " + app.processName, e);
7565 }
7566 }
7567 }
7568 }
7569 }
7570 }
7571 }
7572
7573 // Clean up any connections this application has to other services.
7574 if (app.connections.size() > 0) {
7575 Iterator<ConnectionRecord> it = app.connections.iterator();
7576 while (it.hasNext()) {
7577 ConnectionRecord r = it.next();
7578 removeConnectionLocked(r, app, null);
7579 }
7580 }
7581 app.connections.clear();
7582
7583 if (app.services.size() != 0) {
7584 // Any services running in the application need to be placed
7585 // back in the pending list.
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 sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007589 synchronized (sr.stats.getBatteryStats()) {
7590 sr.stats.stopLaunchedLocked();
7591 }
7592 sr.app = null;
7593 sr.executeNesting = 0;
7594 mStoppingServices.remove(sr);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007595
7596 boolean hasClients = sr.bindings.size() > 0;
7597 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007598 Iterator<IntentBindRecord> bindings
7599 = sr.bindings.values().iterator();
7600 while (bindings.hasNext()) {
7601 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007602 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 + ": shouldUnbind=" + b.hasBound);
7604 b.binder = null;
7605 b.requested = b.received = b.hasBound = false;
7606 }
7607 }
7608
7609 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007610 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007611 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08007612 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 sr.crashCount, sr.shortName, app.pid);
7614 bringDownServiceLocked(sr, true);
7615 } else if (!allowRestart) {
7616 bringDownServiceLocked(sr, true);
7617 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07007618 boolean canceled = scheduleServiceRestartLocked(sr, true);
7619
7620 // Should the service remain running? Note that in the
7621 // extreme case of so many attempts to deliver a command
7622 // that it failed, that we also will stop it here.
7623 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
7624 if (sr.pendingStarts.size() == 0) {
7625 sr.startRequested = false;
7626 if (!hasClients) {
7627 // Whoops, no reason to restart!
7628 bringDownServiceLocked(sr, true);
7629 }
7630 }
7631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007632 }
7633 }
7634
7635 if (!allowRestart) {
7636 app.services.clear();
7637 }
7638 }
7639
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007640 // Make sure we have no more records on the stopping list.
7641 int i = mStoppingServices.size();
7642 while (i > 0) {
7643 i--;
7644 ServiceRecord sr = mStoppingServices.get(i);
7645 if (sr.app == app) {
7646 mStoppingServices.remove(i);
7647 }
7648 }
7649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007650 app.executingServices.clear();
7651 }
7652
7653 private final void removeDyingProviderLocked(ProcessRecord proc,
7654 ContentProviderRecord cpr) {
7655 synchronized (cpr) {
7656 cpr.launchingApp = null;
7657 cpr.notifyAll();
7658 }
7659
7660 mProvidersByClass.remove(cpr.info.name);
7661 String names[] = cpr.info.authority.split(";");
7662 for (int j = 0; j < names.length; j++) {
7663 mProvidersByName.remove(names[j]);
7664 }
7665
7666 Iterator<ProcessRecord> cit = cpr.clients.iterator();
7667 while (cit.hasNext()) {
7668 ProcessRecord capp = cit.next();
7669 if (!capp.persistent && capp.thread != null
7670 && capp.pid != 0
7671 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07007672 Slog.i(TAG, "Kill " + capp.processName
7673 + " (pid " + capp.pid + "): provider " + cpr.info.name
7674 + " in dying process " + proc.processName);
7675 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
7676 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 Process.killProcess(capp.pid);
7678 }
7679 }
7680
7681 mLaunchingProviders.remove(cpr);
7682 }
7683
7684 /**
7685 * Main code for cleaning up a process when it has gone away. This is
7686 * called both as a result of the process dying, or directly when stopping
7687 * a process when running in single process mode.
7688 */
7689 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
7690 boolean restarting, int index) {
7691 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007692 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693 }
7694
Dianne Hackborn36124872009-10-08 16:22:03 -07007695 mProcessesToGc.remove(app);
7696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 // Dismiss any open dialogs.
7698 if (app.crashDialog != null) {
7699 app.crashDialog.dismiss();
7700 app.crashDialog = null;
7701 }
7702 if (app.anrDialog != null) {
7703 app.anrDialog.dismiss();
7704 app.anrDialog = null;
7705 }
7706 if (app.waitDialog != null) {
7707 app.waitDialog.dismiss();
7708 app.waitDialog = null;
7709 }
7710
7711 app.crashing = false;
7712 app.notResponding = false;
7713
7714 app.resetPackageList();
7715 app.thread = null;
7716 app.forcingToForeground = null;
7717 app.foregroundServices = false;
7718
7719 killServicesLocked(app, true);
7720
7721 boolean restart = false;
7722
7723 int NL = mLaunchingProviders.size();
7724
7725 // Remove published content providers.
7726 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007727 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007728 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007729 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 cpr.provider = null;
7731 cpr.app = null;
7732
7733 // See if someone is waiting for this provider... in which
7734 // case we don't remove it, but just let it restart.
7735 int i = 0;
7736 if (!app.bad) {
7737 for (; i<NL; i++) {
7738 if (mLaunchingProviders.get(i) == cpr) {
7739 restart = true;
7740 break;
7741 }
7742 }
7743 } else {
7744 i = NL;
7745 }
7746
7747 if (i >= NL) {
7748 removeDyingProviderLocked(app, cpr);
7749 NL = mLaunchingProviders.size();
7750 }
7751 }
7752 app.pubProviders.clear();
7753 }
7754
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007755 // Take care of any launching providers waiting for this process.
7756 if (checkAppInLaunchingProvidersLocked(app, false)) {
7757 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007758 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007760 // Unregister from connected content providers.
7761 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07007762 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007763 while (it.hasNext()) {
7764 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
7765 cpr.clients.remove(app);
7766 }
7767 app.conProviders.clear();
7768 }
7769
Dianne Hackbornde42bb62009-08-05 12:26:15 -07007770 // At this point there may be remaining entries in mLaunchingProviders
7771 // where we were the only one waiting, so they are no longer of use.
7772 // Look for these and clean up if found.
7773 // XXX Commented out for now. Trying to figure out a way to reproduce
7774 // the actual situation to identify what is actually going on.
7775 if (false) {
7776 for (int i=0; i<NL; i++) {
7777 ContentProviderRecord cpr = (ContentProviderRecord)
7778 mLaunchingProviders.get(i);
7779 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
7780 synchronized (cpr) {
7781 cpr.launchingApp = null;
7782 cpr.notifyAll();
7783 }
7784 }
7785 }
7786 }
7787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007788 skipCurrentReceiverLocked(app);
7789
7790 // Unregister any receivers.
7791 if (app.receivers.size() > 0) {
7792 Iterator<ReceiverList> it = app.receivers.iterator();
7793 while (it.hasNext()) {
7794 removeReceiverLocked(it.next());
7795 }
7796 app.receivers.clear();
7797 }
7798
Christopher Tate181fafa2009-05-14 11:12:14 -07007799 // If the app is undergoing backup, tell the backup manager about it
7800 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007801 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07007802 try {
7803 IBackupManager bm = IBackupManager.Stub.asInterface(
7804 ServiceManager.getService(Context.BACKUP_SERVICE));
7805 bm.agentDisconnected(app.info.packageName);
7806 } catch (RemoteException e) {
7807 // can't happen; backup manager is local
7808 }
7809 }
7810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 // If the caller is restarting this app, then leave it in its
7812 // current lists and let the caller take care of it.
7813 if (restarting) {
7814 return;
7815 }
7816
7817 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007818 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007819 "Removing non-persistent process during cleanup: " + app);
7820 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007821 if (mHeavyWeightProcess == app) {
7822 mHeavyWeightProcess = null;
7823 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
7824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 } else if (!app.removed) {
7826 // This app is persistent, so we need to keep its record around.
7827 // If it is not already on the pending app list, add it there
7828 // and start a new process for it.
7829 app.thread = null;
7830 app.forcingToForeground = null;
7831 app.foregroundServices = false;
7832 if (mPersistentStartingProcesses.indexOf(app) < 0) {
7833 mPersistentStartingProcesses.add(app);
7834 restart = true;
7835 }
7836 }
7837 mProcessesOnHold.remove(app);
7838
The Android Open Source Project4df24232009-03-05 14:34:35 -08007839 if (app == mHomeProcess) {
7840 mHomeProcess = null;
7841 }
7842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007843 if (restart) {
7844 // We have components that still need to be running in the
7845 // process, so re-launch it.
7846 mProcessNames.put(app.processName, app.info.uid, app);
7847 startProcessLocked(app, "restart", app.processName);
7848 } else if (app.pid > 0 && app.pid != MY_PID) {
7849 // Goodbye!
7850 synchronized (mPidsSelfLocked) {
7851 mPidsSelfLocked.remove(app.pid);
7852 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
7853 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007854 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007855 }
7856 }
7857
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007858 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
7859 // Look through the content providers we are waiting to have launched,
7860 // and if any run in this process then either schedule a restart of
7861 // the process or kill the client waiting for it if this process has
7862 // gone bad.
7863 int NL = mLaunchingProviders.size();
7864 boolean restart = false;
7865 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007866 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08007867 if (cpr.launchingApp == app) {
7868 if (!alwaysBad && !app.bad) {
7869 restart = true;
7870 } else {
7871 removeDyingProviderLocked(app, cpr);
7872 NL = mLaunchingProviders.size();
7873 }
7874 }
7875 }
7876 return restart;
7877 }
7878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007879 // =========================================================
7880 // SERVICES
7881 // =========================================================
7882
7883 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
7884 ActivityManager.RunningServiceInfo info =
7885 new ActivityManager.RunningServiceInfo();
7886 info.service = r.name;
7887 if (r.app != null) {
7888 info.pid = r.app.pid;
7889 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007890 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007891 info.process = r.processName;
7892 info.foreground = r.isForeground;
7893 info.activeSince = r.createTime;
7894 info.started = r.startRequested;
7895 info.clientCount = r.connections.size();
7896 info.crashCount = r.crashCount;
7897 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007898 if (r.isForeground) {
7899 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
7900 }
7901 if (r.startRequested) {
7902 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
7903 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007904 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07007905 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
7906 }
7907 if (r.app != null && r.app.persistent) {
7908 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
7909 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007910 for (ConnectionRecord conn : r.connections.values()) {
7911 if (conn.clientLabel != 0) {
7912 info.clientPackage = conn.binding.client.info.packageName;
7913 info.clientLabel = conn.clientLabel;
7914 break;
7915 }
7916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917 return info;
7918 }
7919
7920 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
7921 int flags) {
7922 synchronized (this) {
7923 ArrayList<ActivityManager.RunningServiceInfo> res
7924 = new ArrayList<ActivityManager.RunningServiceInfo>();
7925
7926 if (mServices.size() > 0) {
7927 Iterator<ServiceRecord> it = mServices.values().iterator();
7928 while (it.hasNext() && res.size() < maxNum) {
7929 res.add(makeRunningServiceInfoLocked(it.next()));
7930 }
7931 }
7932
7933 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
7934 ServiceRecord r = mRestartingServices.get(i);
7935 ActivityManager.RunningServiceInfo info =
7936 makeRunningServiceInfoLocked(r);
7937 info.restarting = r.nextRestartTime;
7938 res.add(info);
7939 }
7940
7941 return res;
7942 }
7943 }
7944
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007945 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
7946 synchronized (this) {
7947 ServiceRecord r = mServices.get(name);
7948 if (r != null) {
7949 for (ConnectionRecord conn : r.connections.values()) {
7950 if (conn.clientIntent != null) {
7951 return conn.clientIntent;
7952 }
7953 }
7954 }
7955 }
7956 return null;
7957 }
7958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007959 private final ServiceRecord findServiceLocked(ComponentName name,
7960 IBinder token) {
7961 ServiceRecord r = mServices.get(name);
7962 return r == token ? r : null;
7963 }
7964
7965 private final class ServiceLookupResult {
7966 final ServiceRecord record;
7967 final String permission;
7968
7969 ServiceLookupResult(ServiceRecord _record, String _permission) {
7970 record = _record;
7971 permission = _permission;
7972 }
7973 };
7974
7975 private ServiceLookupResult findServiceLocked(Intent service,
7976 String resolvedType) {
7977 ServiceRecord r = null;
7978 if (service.getComponent() != null) {
7979 r = mServices.get(service.getComponent());
7980 }
7981 if (r == null) {
7982 Intent.FilterComparison filter = new Intent.FilterComparison(service);
7983 r = mServicesByIntent.get(filter);
7984 }
7985
7986 if (r == null) {
7987 try {
7988 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007989 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007990 service, resolvedType, 0);
7991 ServiceInfo sInfo =
7992 rInfo != null ? rInfo.serviceInfo : null;
7993 if (sInfo == null) {
7994 return null;
7995 }
7996
7997 ComponentName name = new ComponentName(
7998 sInfo.applicationInfo.packageName, sInfo.name);
7999 r = mServices.get(name);
8000 } catch (RemoteException ex) {
8001 // pm is in same process, this will never happen.
8002 }
8003 }
8004 if (r != null) {
8005 int callingPid = Binder.getCallingPid();
8006 int callingUid = Binder.getCallingUid();
8007 if (checkComponentPermission(r.permission,
8008 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8009 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008010 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008011 + " from pid=" + callingPid
8012 + ", uid=" + callingUid
8013 + " requires " + r.permission);
8014 return new ServiceLookupResult(null, r.permission);
8015 }
8016 return new ServiceLookupResult(r, null);
8017 }
8018 return null;
8019 }
8020
8021 private class ServiceRestarter implements Runnable {
8022 private ServiceRecord mService;
8023
8024 void setService(ServiceRecord service) {
8025 mService = service;
8026 }
8027
8028 public void run() {
8029 synchronized(ActivityManagerService.this) {
8030 performServiceRestartLocked(mService);
8031 }
8032 }
8033 }
8034
8035 private ServiceLookupResult retrieveServiceLocked(Intent service,
8036 String resolvedType, int callingPid, int callingUid) {
8037 ServiceRecord r = null;
8038 if (service.getComponent() != null) {
8039 r = mServices.get(service.getComponent());
8040 }
8041 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8042 r = mServicesByIntent.get(filter);
8043 if (r == null) {
8044 try {
8045 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008046 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008047 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 ServiceInfo sInfo =
8049 rInfo != null ? rInfo.serviceInfo : null;
8050 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008051 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 ": not found");
8053 return null;
8054 }
8055
8056 ComponentName name = new ComponentName(
8057 sInfo.applicationInfo.packageName, sInfo.name);
8058 r = mServices.get(name);
8059 if (r == null) {
8060 filter = new Intent.FilterComparison(service.cloneFilter());
8061 ServiceRestarter res = new ServiceRestarter();
8062 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8063 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8064 synchronized (stats) {
8065 ss = stats.getServiceStatsLocked(
8066 sInfo.applicationInfo.uid, sInfo.packageName,
8067 sInfo.name);
8068 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008069 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008070 res.setService(r);
8071 mServices.put(name, r);
8072 mServicesByIntent.put(filter, r);
8073
8074 // Make sure this component isn't in the pending list.
8075 int N = mPendingServices.size();
8076 for (int i=0; i<N; i++) {
8077 ServiceRecord pr = mPendingServices.get(i);
8078 if (pr.name.equals(name)) {
8079 mPendingServices.remove(i);
8080 i--;
8081 N--;
8082 }
8083 }
8084 }
8085 } catch (RemoteException ex) {
8086 // pm is in same process, this will never happen.
8087 }
8088 }
8089 if (r != null) {
8090 if (checkComponentPermission(r.permission,
8091 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8092 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008093 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008094 + " from pid=" + Binder.getCallingPid()
8095 + ", uid=" + Binder.getCallingUid()
8096 + " requires " + r.permission);
8097 return new ServiceLookupResult(null, r.permission);
8098 }
8099 return new ServiceLookupResult(r, null);
8100 }
8101 return null;
8102 }
8103
8104 private final void bumpServiceExecutingLocked(ServiceRecord r) {
8105 long now = SystemClock.uptimeMillis();
8106 if (r.executeNesting == 0 && r.app != null) {
8107 if (r.app.executingServices.size() == 0) {
8108 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8109 msg.obj = r.app;
8110 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8111 }
8112 r.app.executingServices.add(r);
8113 }
8114 r.executeNesting++;
8115 r.executingStart = now;
8116 }
8117
8118 private final void sendServiceArgsLocked(ServiceRecord r,
8119 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008120 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 if (N == 0) {
8122 return;
8123 }
8124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008125 int i = 0;
8126 while (i < N) {
8127 try {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008128 ServiceRecord.StartItem si = r.pendingStarts.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008129 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008130 + r.name + " " + r.intent + " args=" + si.intent);
Dianne Hackbornfed534e2009-09-23 00:42:12 -07008131 if (si.intent == null && N > 1) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008132 // If somehow we got a dummy start at the front, then
8133 // just drop it here.
8134 i++;
8135 continue;
8136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 bumpServiceExecutingLocked(r);
8138 if (!oomAdjusted) {
8139 oomAdjusted = true;
8140 updateOomAdjLocked(r.app);
8141 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008142 int flags = 0;
8143 if (si.deliveryCount > 0) {
8144 flags |= Service.START_FLAG_RETRY;
8145 }
8146 if (si.doneExecutingCount > 0) {
8147 flags |= Service.START_FLAG_REDELIVERY;
8148 }
8149 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
8150 si.deliveredTime = SystemClock.uptimeMillis();
8151 r.deliveredStarts.add(si);
8152 si.deliveryCount++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008153 i++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008154 } catch (RemoteException e) {
8155 // Remote process gone... we'll let the normal cleanup take
8156 // care of this.
8157 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008158 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008159 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008160 break;
8161 }
8162 }
8163 if (i == N) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008164 r.pendingStarts.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 } else {
8166 while (i > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008167 i--;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008168 r.pendingStarts.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008169 }
8170 }
8171 }
8172
8173 private final boolean requestServiceBindingLocked(ServiceRecord r,
8174 IntentBindRecord i, boolean rebind) {
8175 if (r.app == null || r.app.thread == null) {
8176 // If service is not currently running, can't yet bind.
8177 return false;
8178 }
8179 if ((!i.requested || rebind) && i.apps.size() > 0) {
8180 try {
8181 bumpServiceExecutingLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008182 if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 + ": shouldUnbind=" + i.hasBound);
8184 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8185 if (!rebind) {
8186 i.requested = true;
8187 }
8188 i.hasBound = true;
8189 i.doRebind = false;
8190 } catch (RemoteException e) {
8191 return false;
8192 }
8193 }
8194 return true;
8195 }
8196
8197 private final void requestServiceBindingsLocked(ServiceRecord r) {
8198 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8199 while (bindings.hasNext()) {
8200 IntentBindRecord i = bindings.next();
8201 if (!requestServiceBindingLocked(r, i, false)) {
8202 break;
8203 }
8204 }
8205 }
8206
8207 private final void realStartServiceLocked(ServiceRecord r,
8208 ProcessRecord app) throws RemoteException {
8209 if (app.thread == null) {
8210 throw new RemoteException();
8211 }
8212
8213 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008214 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008215
8216 app.services.add(r);
8217 bumpServiceExecutingLocked(r);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008218 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008219
8220 boolean created = false;
8221 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008222 if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 + r.name + " " + r.intent);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008224 mStringBuilder.setLength(0);
8225 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008226 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008227 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008228 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008229 synchronized (r.stats.getBatteryStats()) {
8230 r.stats.startLaunchedLocked();
8231 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008232 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008233 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008234 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008235 created = true;
8236 } finally {
8237 if (!created) {
8238 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008239 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240 }
8241 }
8242
8243 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008244
8245 // If the service is in the started state, and there are no
8246 // pending arguments, then fake up one so its onStartCommand() will
8247 // be called.
8248 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8249 r.lastStartId++;
8250 if (r.lastStartId < 1) {
8251 r.lastStartId = 1;
8252 }
8253 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, null));
8254 }
8255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 sendServiceArgsLocked(r, true);
8257 }
8258
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008259 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8260 boolean allowCancel) {
8261 boolean canceled = false;
8262
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008263 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008264 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008265 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008266
8267 // Any delivered but not yet finished starts should be put back
8268 // on the pending list.
8269 final int N = r.deliveredStarts.size();
8270 if (N > 0) {
8271 for (int i=N-1; i>=0; i--) {
8272 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
8273 if (si.intent == null) {
8274 // We'll generate this again if needed.
8275 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8276 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8277 r.pendingStarts.add(0, si);
8278 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8279 dur *= 2;
8280 if (minDuration < dur) minDuration = dur;
8281 if (resetTime < dur) resetTime = dur;
8282 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008283 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008284 + r.name);
8285 canceled = true;
8286 }
8287 }
8288 r.deliveredStarts.clear();
8289 }
8290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008291 r.totalRestartCount++;
8292 if (r.restartDelay == 0) {
8293 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008294 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 } else {
8296 // If it has been a "reasonably long time" since the service
8297 // was started, then reset our restart duration back to
8298 // the beginning, so we don't infinitely increase the duration
8299 // on a service that just occasionally gets killed (which is
8300 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008301 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008302 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008303 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008304 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008305 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008306 if (r.restartDelay < minDuration) {
8307 r.restartDelay = minDuration;
8308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008309 }
8310 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008311
8312 r.nextRestartTime = now + r.restartDelay;
8313
8314 // Make sure that we don't end up restarting a bunch of services
8315 // all at the same time.
8316 boolean repeat;
8317 do {
8318 repeat = false;
8319 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8320 ServiceRecord r2 = mRestartingServices.get(i);
8321 if (r2 != r && r.nextRestartTime
8322 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8323 && r.nextRestartTime
8324 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8325 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8326 r.restartDelay = r.nextRestartTime - now;
8327 repeat = true;
8328 break;
8329 }
8330 }
8331 } while (repeat);
8332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008333 if (!mRestartingServices.contains(r)) {
8334 mRestartingServices.add(r);
8335 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008336
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008337 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008340 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008342 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008343 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008344 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 r.shortName, r.restartDelay);
8346
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008347 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008348 }
8349
8350 final void performServiceRestartLocked(ServiceRecord r) {
8351 if (!mRestartingServices.contains(r)) {
8352 return;
8353 }
8354 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8355 }
8356
8357 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8358 if (r.restartDelay == 0) {
8359 return false;
8360 }
8361 r.resetRestartCounter();
8362 mRestartingServices.remove(r);
8363 mHandler.removeCallbacks(r.restarter);
8364 return true;
8365 }
8366
8367 private final boolean bringUpServiceLocked(ServiceRecord r,
8368 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008369 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008370 //r.dump(" ");
8371
Dianne Hackborn36124872009-10-08 16:22:03 -07008372 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008373 sendServiceArgsLocked(r, false);
8374 return true;
8375 }
8376
8377 if (!whileRestarting && r.restartDelay > 0) {
8378 // If waiting for a restart, then do nothing.
8379 return true;
8380 }
8381
Joe Onorato8a9b2202010-02-26 18:56:32 -08008382 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008383 + " " + r.intent);
8384
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008385 // We are now bringing the service up, so no longer in the
8386 // restarting state.
8387 mRestartingServices.remove(r);
8388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008389 final String appName = r.processName;
8390 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8391 if (app != null && app.thread != null) {
8392 try {
8393 realStartServiceLocked(r, app);
8394 return true;
8395 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008396 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008397 }
8398
8399 // If a dead object exception was thrown -- fall through to
8400 // restart the application.
8401 }
8402
Dianne Hackborn36124872009-10-08 16:22:03 -07008403 // Not running -- get it started, and enqueue this service record
8404 // to be executed when the app comes up.
8405 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8406 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008407 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008408 + r.appInfo.packageName + "/"
8409 + r.appInfo.uid + " for service "
8410 + r.intent.getIntent() + ": process is bad");
8411 bringDownServiceLocked(r, true);
8412 return false;
8413 }
8414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008415 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008416 mPendingServices.add(r);
8417 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008419 return true;
8420 }
8421
8422 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008423 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008424 //r.dump(" ");
8425
8426 // Does it still need to run?
8427 if (!force && r.startRequested) {
8428 return;
8429 }
8430 if (r.connections.size() > 0) {
8431 if (!force) {
8432 // XXX should probably keep a count of the number of auto-create
8433 // connections directly in the service.
8434 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8435 while (it.hasNext()) {
8436 ConnectionRecord cr = it.next();
8437 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
8438 return;
8439 }
8440 }
8441 }
8442
8443 // Report to all of the connections that the service is no longer
8444 // available.
8445 Iterator<ConnectionRecord> it = r.connections.values().iterator();
8446 while (it.hasNext()) {
8447 ConnectionRecord c = it.next();
8448 try {
8449 // todo: shouldn't be a synchronous call!
8450 c.conn.connected(r.name, null);
8451 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008452 Slog.w(TAG, "Failure disconnecting service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008453 " to connection " + c.conn.asBinder() +
8454 " (in " + c.binding.client.processName + ")", e);
8455 }
8456 }
8457 }
8458
8459 // Tell the service that it has been unbound.
8460 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8461 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8462 while (it.hasNext()) {
8463 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008464 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008465 + ": hasBound=" + ibr.hasBound);
8466 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8467 try {
8468 bumpServiceExecutingLocked(r);
8469 updateOomAdjLocked(r.app);
8470 ibr.hasBound = false;
8471 r.app.thread.scheduleUnbindService(r,
8472 ibr.intent.getIntent());
8473 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008474 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475 + r.shortName, e);
8476 serviceDoneExecutingLocked(r, true);
8477 }
8478 }
8479 }
8480 }
8481
Joe Onorato8a9b2202010-02-26 18:56:32 -08008482 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008483 + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008484 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008485 System.identityHashCode(r), r.shortName,
8486 (r.app != null) ? r.app.pid : -1);
8487
8488 mServices.remove(r.name);
8489 mServicesByIntent.remove(r.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008490 if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008491 r.totalRestartCount = 0;
8492 unscheduleServiceRestartLocked(r);
8493
8494 // Also make sure it is not on the pending list.
8495 int N = mPendingServices.size();
8496 for (int i=0; i<N; i++) {
8497 if (mPendingServices.get(i) == r) {
8498 mPendingServices.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008499 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008500 TAG, "Removed pending service: " + r.shortName);
8501 i--;
8502 N--;
8503 }
8504 }
8505
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008506 r.cancelNotification();
8507 r.isForeground = false;
8508 r.foregroundId = 0;
8509 r.foregroundNoti = null;
8510
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008511 // Clear start entries.
8512 r.deliveredStarts.clear();
8513 r.pendingStarts.clear();
8514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 if (r.app != null) {
8516 synchronized (r.stats.getBatteryStats()) {
8517 r.stats.stopLaunchedLocked();
8518 }
8519 r.app.services.remove(r);
8520 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008522 if (DEBUG_SERVICE) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07008523 "Stopping service: " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008524 bumpServiceExecutingLocked(r);
8525 mStoppingServices.add(r);
8526 updateOomAdjLocked(r.app);
8527 r.app.thread.scheduleStopService(r);
8528 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008529 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008530 + r.shortName, e);
8531 serviceDoneExecutingLocked(r, true);
8532 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008533 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008534 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008535 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008536 TAG, "Removed service that has no process: " + r.shortName);
8537 }
8538 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008539 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 TAG, "Removed service that is not running: " + r.shortName);
8541 }
8542 }
8543
8544 ComponentName startServiceLocked(IApplicationThread caller,
8545 Intent service, String resolvedType,
8546 int callingPid, int callingUid) {
8547 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008548 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008549 + " type=" + resolvedType + " args=" + service.getExtras());
8550
8551 if (caller != null) {
8552 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8553 if (callerApp == null) {
8554 throw new SecurityException(
8555 "Unable to find app for caller " + caller
8556 + " (pid=" + Binder.getCallingPid()
8557 + ") when starting service " + service);
8558 }
8559 }
8560
8561 ServiceLookupResult res =
8562 retrieveServiceLocked(service, resolvedType,
8563 callingPid, callingUid);
8564 if (res == null) {
8565 return null;
8566 }
8567 if (res.record == null) {
8568 return new ComponentName("!", res.permission != null
8569 ? res.permission : "private to package");
8570 }
8571 ServiceRecord r = res.record;
8572 if (unscheduleServiceRestartLocked(r)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008573 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008574 + r.shortName);
8575 }
8576 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008577 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008578 r.lastStartId++;
8579 if (r.lastStartId < 1) {
8580 r.lastStartId = 1;
8581 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008582 r.pendingStarts.add(new ServiceRecord.StartItem(r.lastStartId, service));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008583 r.lastActivity = SystemClock.uptimeMillis();
8584 synchronized (r.stats.getBatteryStats()) {
8585 r.stats.startRunningLocked();
8586 }
8587 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
8588 return new ComponentName("!", "Service process is bad");
8589 }
8590 return r.name;
8591 }
8592 }
8593
8594 public ComponentName startService(IApplicationThread caller, Intent service,
8595 String resolvedType) {
8596 // Refuse possible leaked file descriptors
8597 if (service != null && service.hasFileDescriptors() == true) {
8598 throw new IllegalArgumentException("File descriptors passed in Intent");
8599 }
8600
8601 synchronized(this) {
8602 final int callingPid = Binder.getCallingPid();
8603 final int callingUid = Binder.getCallingUid();
8604 final long origId = Binder.clearCallingIdentity();
8605 ComponentName res = startServiceLocked(caller, service,
8606 resolvedType, callingPid, callingUid);
8607 Binder.restoreCallingIdentity(origId);
8608 return res;
8609 }
8610 }
8611
8612 ComponentName startServiceInPackage(int uid,
8613 Intent service, String resolvedType) {
8614 synchronized(this) {
8615 final long origId = Binder.clearCallingIdentity();
8616 ComponentName res = startServiceLocked(null, service,
8617 resolvedType, -1, uid);
8618 Binder.restoreCallingIdentity(origId);
8619 return res;
8620 }
8621 }
8622
8623 public int stopService(IApplicationThread caller, Intent service,
8624 String resolvedType) {
8625 // Refuse possible leaked file descriptors
8626 if (service != null && service.hasFileDescriptors() == true) {
8627 throw new IllegalArgumentException("File descriptors passed in Intent");
8628 }
8629
8630 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008631 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008632 + " type=" + resolvedType);
8633
8634 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8635 if (caller != null && callerApp == null) {
8636 throw new SecurityException(
8637 "Unable to find app for caller " + caller
8638 + " (pid=" + Binder.getCallingPid()
8639 + ") when stopping service " + service);
8640 }
8641
8642 // If this service is active, make sure it is stopped.
8643 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8644 if (r != null) {
8645 if (r.record != null) {
8646 synchronized (r.record.stats.getBatteryStats()) {
8647 r.record.stats.stopRunningLocked();
8648 }
8649 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008650 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008651 final long origId = Binder.clearCallingIdentity();
8652 bringDownServiceLocked(r.record, false);
8653 Binder.restoreCallingIdentity(origId);
8654 return 1;
8655 }
8656 return -1;
8657 }
8658 }
8659
8660 return 0;
8661 }
8662
8663 public IBinder peekService(Intent service, String resolvedType) {
8664 // Refuse possible leaked file descriptors
8665 if (service != null && service.hasFileDescriptors() == true) {
8666 throw new IllegalArgumentException("File descriptors passed in Intent");
8667 }
8668
8669 IBinder ret = null;
8670
8671 synchronized(this) {
8672 ServiceLookupResult r = findServiceLocked(service, resolvedType);
8673
8674 if (r != null) {
8675 // r.record is null if findServiceLocked() failed the caller permission check
8676 if (r.record == null) {
8677 throw new SecurityException(
8678 "Permission Denial: Accessing service " + r.record.name
8679 + " from pid=" + Binder.getCallingPid()
8680 + ", uid=" + Binder.getCallingUid()
8681 + " requires " + r.permission);
8682 }
8683 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
8684 if (ib != null) {
8685 ret = ib.binder;
8686 }
8687 }
8688 }
8689
8690 return ret;
8691 }
8692
8693 public boolean stopServiceToken(ComponentName className, IBinder token,
8694 int startId) {
8695 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008696 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 + " " + token + " startId=" + startId);
8698 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008699 if (r != null) {
8700 if (startId >= 0) {
8701 // Asked to only stop if done with all work. Note that
8702 // to avoid leaks, we will take this as dropping all
8703 // start items up to and including this one.
8704 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
8705 if (si != null) {
8706 while (r.deliveredStarts.size() > 0) {
8707 if (r.deliveredStarts.remove(0) == si) {
8708 break;
8709 }
8710 }
8711 }
8712
8713 if (r.lastStartId != startId) {
8714 return false;
8715 }
8716
8717 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008718 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008719 + " is last, but have " + r.deliveredStarts.size()
8720 + " remaining args");
8721 }
8722 }
8723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008724 synchronized (r.stats.getBatteryStats()) {
8725 r.stats.stopRunningLocked();
8726 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008727 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 }
8729 final long origId = Binder.clearCallingIdentity();
8730 bringDownServiceLocked(r, false);
8731 Binder.restoreCallingIdentity(origId);
8732 return true;
8733 }
8734 }
8735 return false;
8736 }
8737
8738 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008739 int id, Notification notification, boolean removeNotification) {
8740 final long origId = Binder.clearCallingIdentity();
8741 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008742 synchronized(this) {
8743 ServiceRecord r = findServiceLocked(className, token);
8744 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008745 if (id != 0) {
8746 if (notification == null) {
8747 throw new IllegalArgumentException("null notification");
8748 }
8749 if (r.foregroundId != id) {
8750 r.cancelNotification();
8751 r.foregroundId = id;
8752 }
8753 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
8754 r.foregroundNoti = notification;
8755 r.isForeground = true;
8756 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 if (r.app != null) {
8758 updateServiceForegroundLocked(r.app, true);
8759 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008760 } else {
8761 if (r.isForeground) {
8762 r.isForeground = false;
8763 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008764 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008765 updateServiceForegroundLocked(r.app, true);
8766 }
8767 }
8768 if (removeNotification) {
8769 r.cancelNotification();
8770 r.foregroundId = 0;
8771 r.foregroundNoti = null;
8772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008773 }
8774 }
8775 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008776 } finally {
8777 Binder.restoreCallingIdentity(origId);
8778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008779 }
8780
8781 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
8782 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07008783 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008784 if (sr.isForeground) {
8785 anyForeground = true;
8786 break;
8787 }
8788 }
8789 if (anyForeground != proc.foregroundServices) {
8790 proc.foregroundServices = anyForeground;
8791 if (oomAdj) {
8792 updateOomAdjLocked();
8793 }
8794 }
8795 }
8796
8797 public int bindService(IApplicationThread caller, IBinder token,
8798 Intent service, String resolvedType,
8799 IServiceConnection connection, int flags) {
8800 // Refuse possible leaked file descriptors
8801 if (service != null && service.hasFileDescriptors() == true) {
8802 throw new IllegalArgumentException("File descriptors passed in Intent");
8803 }
8804
8805 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008806 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 + " type=" + resolvedType + " conn=" + connection.asBinder()
8808 + " flags=0x" + Integer.toHexString(flags));
8809 final ProcessRecord callerApp = getRecordForAppLocked(caller);
8810 if (callerApp == null) {
8811 throw new SecurityException(
8812 "Unable to find app for caller " + caller
8813 + " (pid=" + Binder.getCallingPid()
8814 + ") when binding service " + service);
8815 }
8816
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008817 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008818 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008819 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008820 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008821 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008822 return 0;
8823 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008824 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008825 }
8826
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008827 int clientLabel = 0;
8828 PendingIntent clientIntent = null;
8829
8830 if (callerApp.info.uid == Process.SYSTEM_UID) {
8831 // Hacky kind of thing -- allow system stuff to tell us
8832 // what they are, so we can report this elsewhere for
8833 // others to know why certain services are running.
8834 try {
8835 clientIntent = (PendingIntent)service.getParcelableExtra(
8836 Intent.EXTRA_CLIENT_INTENT);
8837 } catch (RuntimeException e) {
8838 }
8839 if (clientIntent != null) {
8840 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
8841 if (clientLabel != 0) {
8842 // There are no useful extras in the intent, trash them.
8843 // System code calling with this stuff just needs to know
8844 // this will happen.
8845 service = service.cloneFilter();
8846 }
8847 }
8848 }
8849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008850 ServiceLookupResult res =
8851 retrieveServiceLocked(service, resolvedType,
8852 Binder.getCallingPid(), Binder.getCallingUid());
8853 if (res == null) {
8854 return 0;
8855 }
8856 if (res.record == null) {
8857 return -1;
8858 }
8859 ServiceRecord s = res.record;
8860
8861 final long origId = Binder.clearCallingIdentity();
8862
8863 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008864 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008865 + s.shortName);
8866 }
8867
8868 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
8869 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008870 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008871
8872 IBinder binder = connection.asBinder();
8873 s.connections.put(binder, c);
8874 b.connections.add(c);
8875 if (activity != null) {
8876 if (activity.connections == null) {
8877 activity.connections = new HashSet<ConnectionRecord>();
8878 }
8879 activity.connections.add(c);
8880 }
8881 b.client.connections.add(c);
8882 mServiceConnections.put(binder, c);
8883
8884 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
8885 s.lastActivity = SystemClock.uptimeMillis();
8886 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
8887 return 0;
8888 }
8889 }
8890
8891 if (s.app != null) {
8892 // This could have made the service more important.
8893 updateOomAdjLocked(s.app);
8894 }
8895
Joe Onorato8a9b2202010-02-26 18:56:32 -08008896 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008897 + ": received=" + b.intent.received
8898 + " apps=" + b.intent.apps.size()
8899 + " doRebind=" + b.intent.doRebind);
8900
8901 if (s.app != null && b.intent.received) {
8902 // Service is already running, so we can immediately
8903 // publish the connection.
8904 try {
8905 c.conn.connected(s.name, b.intent.binder);
8906 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008907 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008908 + " to connection " + c.conn.asBinder()
8909 + " (in " + c.binding.client.processName + ")", e);
8910 }
8911
8912 // If this is the first app connected back to this binding,
8913 // and the service had previously asked to be told when
8914 // rebound, then do so.
8915 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
8916 requestServiceBindingLocked(s, b.intent, true);
8917 }
8918 } else if (!b.intent.requested) {
8919 requestServiceBindingLocked(s, b.intent, false);
8920 }
8921
8922 Binder.restoreCallingIdentity(origId);
8923 }
8924
8925 return 1;
8926 }
8927
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008928 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008929 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008930 IBinder binder = c.conn.asBinder();
8931 AppBindRecord b = c.binding;
8932 ServiceRecord s = b.service;
8933 s.connections.remove(binder);
8934 b.connections.remove(c);
8935 if (c.activity != null && c.activity != skipAct) {
8936 if (c.activity.connections != null) {
8937 c.activity.connections.remove(c);
8938 }
8939 }
8940 if (b.client != skipApp) {
8941 b.client.connections.remove(c);
8942 }
8943 mServiceConnections.remove(binder);
8944
8945 if (b.connections.size() == 0) {
8946 b.intent.apps.remove(b.client);
8947 }
8948
Joe Onorato8a9b2202010-02-26 18:56:32 -08008949 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 + ": shouldUnbind=" + b.intent.hasBound);
8951 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
8952 && b.intent.hasBound) {
8953 try {
8954 bumpServiceExecutingLocked(s);
8955 updateOomAdjLocked(s.app);
8956 b.intent.hasBound = false;
8957 // Assume the client doesn't want to know about a rebind;
8958 // we will deal with that later if it asks for one.
8959 b.intent.doRebind = false;
8960 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
8961 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008962 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008963 serviceDoneExecutingLocked(s, true);
8964 }
8965 }
8966
8967 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
8968 bringDownServiceLocked(s, false);
8969 }
8970 }
8971
8972 public boolean unbindService(IServiceConnection connection) {
8973 synchronized (this) {
8974 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008975 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008976 ConnectionRecord r = mServiceConnections.get(binder);
8977 if (r == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008978 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979 + connection.asBinder());
8980 return false;
8981 }
8982
8983 final long origId = Binder.clearCallingIdentity();
8984
8985 removeConnectionLocked(r, null, null);
8986
8987 if (r.binding.service.app != null) {
8988 // This could have made the service less important.
8989 updateOomAdjLocked(r.binding.service.app);
8990 }
8991
8992 Binder.restoreCallingIdentity(origId);
8993 }
8994
8995 return true;
8996 }
8997
8998 public void publishService(IBinder token, Intent intent, IBinder service) {
8999 // Refuse possible leaked file descriptors
9000 if (intent != null && intent.hasFileDescriptors() == true) {
9001 throw new IllegalArgumentException("File descriptors passed in Intent");
9002 }
9003
9004 synchronized(this) {
9005 if (!(token instanceof ServiceRecord)) {
9006 throw new IllegalArgumentException("Invalid service token");
9007 }
9008 ServiceRecord r = (ServiceRecord)token;
9009
9010 final long origId = Binder.clearCallingIdentity();
9011
Joe Onorato8a9b2202010-02-26 18:56:32 -08009012 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009013 + " " + intent + ": " + service);
9014 if (r != null) {
9015 Intent.FilterComparison filter
9016 = new Intent.FilterComparison(intent);
9017 IntentBindRecord b = r.bindings.get(filter);
9018 if (b != null && !b.received) {
9019 b.binder = service;
9020 b.requested = true;
9021 b.received = true;
9022 if (r.connections.size() > 0) {
9023 Iterator<ConnectionRecord> it
9024 = r.connections.values().iterator();
9025 while (it.hasNext()) {
9026 ConnectionRecord c = it.next();
9027 if (!filter.equals(c.binding.intent.intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009028 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009029 TAG, "Not publishing to: " + c);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009030 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 TAG, "Bound intent: " + c.binding.intent.intent);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009032 if (DEBUG_SERVICE) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009033 TAG, "Published intent: " + intent);
9034 continue;
9035 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009036 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009037 try {
9038 c.conn.connected(r.name, service);
9039 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009040 Slog.w(TAG, "Failure sending service " + r.name +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 " to connection " + c.conn.asBinder() +
9042 " (in " + c.binding.client.processName + ")", e);
9043 }
9044 }
9045 }
9046 }
9047
9048 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9049
9050 Binder.restoreCallingIdentity(origId);
9051 }
9052 }
9053 }
9054
9055 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9056 // Refuse possible leaked file descriptors
9057 if (intent != null && intent.hasFileDescriptors() == true) {
9058 throw new IllegalArgumentException("File descriptors passed in Intent");
9059 }
9060
9061 synchronized(this) {
9062 if (!(token instanceof ServiceRecord)) {
9063 throw new IllegalArgumentException("Invalid service token");
9064 }
9065 ServiceRecord r = (ServiceRecord)token;
9066
9067 final long origId = Binder.clearCallingIdentity();
9068
9069 if (r != null) {
9070 Intent.FilterComparison filter
9071 = new Intent.FilterComparison(intent);
9072 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009073 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 + " at " + b + ": apps="
9075 + (b != null ? b.apps.size() : 0));
9076 if (b != null) {
9077 if (b.apps.size() > 0) {
9078 // Applications have already bound since the last
9079 // unbind, so just rebind right here.
9080 requestServiceBindingLocked(r, b, true);
9081 } else {
9082 // Note to tell the service the next time there is
9083 // a new client.
9084 b.doRebind = true;
9085 }
9086 }
9087
9088 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9089
9090 Binder.restoreCallingIdentity(origId);
9091 }
9092 }
9093 }
9094
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009095 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009096 synchronized(this) {
9097 if (!(token instanceof ServiceRecord)) {
9098 throw new IllegalArgumentException("Invalid service token");
9099 }
9100 ServiceRecord r = (ServiceRecord)token;
9101 boolean inStopping = mStoppingServices.contains(token);
9102 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009103 if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 + ": nesting=" + r.executeNesting
9105 + ", inStopping=" + inStopping);
9106 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009107 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108 + " with incorrect token: given " + token
9109 + ", expected " + r);
9110 return;
9111 }
9112
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009113 if (type == 1) {
9114 // This is a call from a service start... take care of
9115 // book-keeping.
9116 r.callStart = true;
9117 switch (res) {
9118 case Service.START_STICKY_COMPATIBILITY:
9119 case Service.START_STICKY: {
9120 // We are done with the associated start arguments.
9121 r.findDeliveredStart(startId, true);
9122 // Don't stop if killed.
9123 r.stopIfKilled = false;
9124 break;
9125 }
9126 case Service.START_NOT_STICKY: {
9127 // We are done with the associated start arguments.
9128 r.findDeliveredStart(startId, true);
9129 if (r.lastStartId == startId) {
9130 // There is no more work, and this service
9131 // doesn't want to hang around if killed.
9132 r.stopIfKilled = true;
9133 }
9134 break;
9135 }
9136 case Service.START_REDELIVER_INTENT: {
9137 // We'll keep this item until they explicitly
9138 // call stop for it, but keep track of the fact
9139 // that it was delivered.
9140 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9141 if (si != null) {
9142 si.deliveryCount = 0;
9143 si.doneExecutingCount++;
9144 // Don't stop if killed.
9145 r.stopIfKilled = true;
9146 }
9147 break;
9148 }
9149 default:
9150 throw new IllegalArgumentException(
9151 "Unknown service start result: " + res);
9152 }
9153 if (res == Service.START_STICKY_COMPATIBILITY) {
9154 r.callStart = false;
9155 }
9156 }
9157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 final long origId = Binder.clearCallingIdentity();
9159 serviceDoneExecutingLocked(r, inStopping);
9160 Binder.restoreCallingIdentity(origId);
9161 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009162 Slog.w(TAG, "Done executing unknown service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009163 + " with token " + token);
9164 }
9165 }
9166 }
9167
9168 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
9169 r.executeNesting--;
9170 if (r.executeNesting <= 0 && r.app != null) {
9171 r.app.executingServices.remove(r);
9172 if (r.app.executingServices.size() == 0) {
9173 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9174 }
9175 if (inStopping) {
9176 mStoppingServices.remove(r);
9177 }
9178 updateOomAdjLocked(r.app);
9179 }
9180 }
9181
9182 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009183 String anrMessage = null;
9184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009185 synchronized(this) {
9186 if (proc.executingServices.size() == 0 || proc.thread == null) {
9187 return;
9188 }
9189 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9190 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9191 ServiceRecord timeout = null;
9192 long nextTime = 0;
9193 while (it.hasNext()) {
9194 ServiceRecord sr = it.next();
9195 if (sr.executingStart < maxTime) {
9196 timeout = sr;
9197 break;
9198 }
9199 if (sr.executingStart > nextTime) {
9200 nextTime = sr.executingStart;
9201 }
9202 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009203 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009204 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009205 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009206 } else {
9207 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9208 msg.obj = proc;
9209 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9210 }
9211 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009212
9213 if (anrMessage != null) {
9214 appNotResponding(proc, null, null, anrMessage);
9215 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009216 }
9217
9218 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009219 // BACKUP AND RESTORE
9220 // =========================================================
9221
9222 // Cause the target app to be launched if necessary and its backup agent
9223 // instantiated. The backup agent will invoke backupAgentCreated() on the
9224 // activity manager to announce its creation.
9225 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009226 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009227 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9228
9229 synchronized(this) {
9230 // !!! TODO: currently no check here that we're already bound
9231 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9232 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9233 synchronized (stats) {
9234 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9235 }
9236
9237 BackupRecord r = new BackupRecord(ss, app, backupMode);
9238 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9239 // startProcessLocked() returns existing proc's record if it's already running
9240 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009241 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009242 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009243 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009244 return false;
9245 }
9246
9247 r.app = proc;
9248 mBackupTarget = r;
9249 mBackupAppName = app.packageName;
9250
Christopher Tate6fa95972009-06-05 18:43:55 -07009251 // Try not to kill the process during backup
9252 updateOomAdjLocked(proc);
9253
Christopher Tate181fafa2009-05-14 11:12:14 -07009254 // If the process is already attached, schedule the creation of the backup agent now.
9255 // If it is not yet live, this will be done when it attaches to the framework.
9256 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009257 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009258 try {
9259 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9260 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009261 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009262 }
9263 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009264 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009265 }
9266 // Invariants: at this point, the target app process exists and the application
9267 // is either already running or in the process of coming up. mBackupTarget and
9268 // mBackupAppName describe the app, so that when it binds back to the AM we
9269 // know that it's scheduled for a backup-agent operation.
9270 }
9271
9272 return true;
9273 }
9274
9275 // A backup agent has just come up
9276 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009277 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009278 + " = " + agent);
9279
9280 synchronized(this) {
9281 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009282 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009283 return;
9284 }
9285
Christopher Tate043dadc2009-06-02 16:11:00 -07009286 long oldIdent = Binder.clearCallingIdentity();
Christopher Tate181fafa2009-05-14 11:12:14 -07009287 try {
9288 IBackupManager bm = IBackupManager.Stub.asInterface(
9289 ServiceManager.getService(Context.BACKUP_SERVICE));
9290 bm.agentConnected(agentPackageName, agent);
9291 } catch (RemoteException e) {
9292 // can't happen; the backup manager service is local
9293 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009294 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07009295 e.printStackTrace();
Christopher Tate043dadc2009-06-02 16:11:00 -07009296 } finally {
9297 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009298 }
9299 }
9300 }
9301
9302 // done with this agent
9303 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009304 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009305 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009306 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009307 return;
9308 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009309
9310 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009311 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009312 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009313 return;
9314 }
9315
Christopher Tate181fafa2009-05-14 11:12:14 -07009316 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009317 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009318 return;
9319 }
9320
Christopher Tate6fa95972009-06-05 18:43:55 -07009321 ProcessRecord proc = mBackupTarget.app;
9322 mBackupTarget = null;
9323 mBackupAppName = null;
9324
9325 // Not backing this app up any more; reset its OOM adjustment
9326 updateOomAdjLocked(proc);
9327
Christopher Tatec7b31e32009-06-10 15:49:30 -07009328 // If the app crashed during backup, 'thread' will be null here
9329 if (proc.thread != null) {
9330 try {
9331 proc.thread.scheduleDestroyBackupAgent(appInfo);
9332 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009333 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009334 e.printStackTrace();
9335 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009336 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009337 }
9338 }
9339 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 // BROADCASTS
9341 // =========================================================
9342
Josh Bartel7f208742010-02-25 11:01:44 -06009343 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009344 List cur) {
9345 final ContentResolver resolver = mContext.getContentResolver();
9346 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9347 if (list == null) {
9348 return cur;
9349 }
9350 int N = list.size();
9351 for (int i=0; i<N; i++) {
9352 Intent intent = list.get(i);
9353 if (filter.match(resolver, intent, true, TAG) >= 0) {
9354 if (cur == null) {
9355 cur = new ArrayList<Intent>();
9356 }
9357 cur.add(intent);
9358 }
9359 }
9360 return cur;
9361 }
9362
9363 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009364 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365 + mBroadcastsScheduled);
9366
9367 if (mBroadcastsScheduled) {
9368 return;
9369 }
9370 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9371 mBroadcastsScheduled = true;
9372 }
9373
9374 public Intent registerReceiver(IApplicationThread caller,
9375 IIntentReceiver receiver, IntentFilter filter, String permission) {
9376 synchronized(this) {
9377 ProcessRecord callerApp = null;
9378 if (caller != null) {
9379 callerApp = getRecordForAppLocked(caller);
9380 if (callerApp == null) {
9381 throw new SecurityException(
9382 "Unable to find app for caller " + caller
9383 + " (pid=" + Binder.getCallingPid()
9384 + ") when registering receiver " + receiver);
9385 }
9386 }
9387
9388 List allSticky = null;
9389
9390 // Look for any matching sticky broadcasts...
9391 Iterator actions = filter.actionsIterator();
9392 if (actions != null) {
9393 while (actions.hasNext()) {
9394 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009395 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009396 }
9397 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009398 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009399 }
9400
9401 // The first sticky in the list is returned directly back to
9402 // the client.
9403 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9404
Joe Onorato8a9b2202010-02-26 18:56:32 -08009405 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009406 + ": " + sticky);
9407
9408 if (receiver == null) {
9409 return sticky;
9410 }
9411
9412 ReceiverList rl
9413 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9414 if (rl == null) {
9415 rl = new ReceiverList(this, callerApp,
9416 Binder.getCallingPid(),
9417 Binder.getCallingUid(), receiver);
9418 if (rl.app != null) {
9419 rl.app.receivers.add(rl);
9420 } else {
9421 try {
9422 receiver.asBinder().linkToDeath(rl, 0);
9423 } catch (RemoteException e) {
9424 return sticky;
9425 }
9426 rl.linkedToDeath = true;
9427 }
9428 mRegisteredReceivers.put(receiver.asBinder(), rl);
9429 }
9430 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9431 rl.add(bf);
9432 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009433 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009434 }
9435 mReceiverResolver.addFilter(bf);
9436
9437 // Enqueue broadcasts for all existing stickies that match
9438 // this filter.
9439 if (allSticky != null) {
9440 ArrayList receivers = new ArrayList();
9441 receivers.add(bf);
9442
9443 int N = allSticky.size();
9444 for (int i=0; i<N; i++) {
9445 Intent intent = (Intent)allSticky.get(i);
9446 BroadcastRecord r = new BroadcastRecord(intent, null,
9447 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009448 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009449 if (mParallelBroadcasts.size() == 0) {
9450 scheduleBroadcastsLocked();
9451 }
9452 mParallelBroadcasts.add(r);
9453 }
9454 }
9455
9456 return sticky;
9457 }
9458 }
9459
9460 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009461 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009462
9463 boolean doNext = false;
9464
9465 synchronized(this) {
9466 ReceiverList rl
9467 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9468 if (rl != null) {
9469 if (rl.curBroadcast != null) {
9470 BroadcastRecord r = rl.curBroadcast;
9471 doNext = finishReceiverLocked(
9472 receiver.asBinder(), r.resultCode, r.resultData,
9473 r.resultExtras, r.resultAbort, true);
9474 }
9475
9476 if (rl.app != null) {
9477 rl.app.receivers.remove(rl);
9478 }
9479 removeReceiverLocked(rl);
9480 if (rl.linkedToDeath) {
9481 rl.linkedToDeath = false;
9482 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9483 }
9484 }
9485 }
9486
9487 if (!doNext) {
9488 return;
9489 }
9490
9491 final long origId = Binder.clearCallingIdentity();
9492 processNextBroadcast(false);
9493 trimApplications();
9494 Binder.restoreCallingIdentity(origId);
9495 }
9496
9497 void removeReceiverLocked(ReceiverList rl) {
9498 mRegisteredReceivers.remove(rl.receiver.asBinder());
9499 int N = rl.size();
9500 for (int i=0; i<N; i++) {
9501 mReceiverResolver.removeFilter(rl.get(i));
9502 }
9503 }
9504
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009505 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9506 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9507 ProcessRecord r = mLruProcesses.get(i);
9508 if (r.thread != null) {
9509 try {
9510 r.thread.dispatchPackageBroadcast(cmd, packages);
9511 } catch (RemoteException ex) {
9512 }
9513 }
9514 }
9515 }
9516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517 private final int broadcastIntentLocked(ProcessRecord callerApp,
9518 String callerPackage, Intent intent, String resolvedType,
9519 IIntentReceiver resultTo, int resultCode, String resultData,
9520 Bundle map, String requiredPermission,
9521 boolean ordered, boolean sticky, int callingPid, int callingUid) {
9522 intent = new Intent(intent);
9523
Joe Onorato8a9b2202010-02-26 18:56:32 -08009524 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009525 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
9526 + " ordered=" + ordered);
9527 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009528 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009529 }
9530
9531 // Handle special intents: if this broadcast is from the package
9532 // manager about a package being removed, we need to remove all of
9533 // its activities from the history stack.
9534 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
9535 intent.getAction());
9536 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
9537 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009538 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 || uidRemoved) {
9540 if (checkComponentPermission(
9541 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
9542 callingPid, callingUid, -1)
9543 == PackageManager.PERMISSION_GRANTED) {
9544 if (uidRemoved) {
9545 final Bundle intentExtras = intent.getExtras();
9546 final int uid = intentExtras != null
9547 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
9548 if (uid >= 0) {
9549 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
9550 synchronized (bs) {
9551 bs.removeUidStatsLocked(uid);
9552 }
9553 }
9554 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009555 // If resources are unvailble just force stop all
9556 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009557 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009558 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
9559 if (list != null && (list.length > 0)) {
9560 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009561 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009562 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009563 sendPackageBroadcastLocked(
9564 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009565 }
9566 } else {
9567 Uri data = intent.getData();
9568 String ssp;
9569 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
9570 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
9571 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08009572 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -07009573 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009574 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
9575 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
9576 new String[] {ssp});
9577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 }
9579 }
9580 }
9581 } else {
9582 String msg = "Permission Denial: " + intent.getAction()
9583 + " broadcast from " + callerPackage + " (pid=" + callingPid
9584 + ", uid=" + callingUid + ")"
9585 + " requires "
9586 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009587 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009588 throw new SecurityException(msg);
9589 }
9590 }
9591
9592 /*
9593 * If this is the time zone changed action, queue up a message that will reset the timezone
9594 * of all currently running processes. This message will get queued up before the broadcast
9595 * happens.
9596 */
9597 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
9598 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
9599 }
9600
Dianne Hackborn854060af2009-07-09 18:14:31 -07009601 /*
9602 * Prevent non-system code (defined here to be non-persistent
9603 * processes) from sending protected broadcasts.
9604 */
9605 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
9606 || callingUid == Process.SHELL_UID || callingUid == 0) {
9607 // Always okay.
9608 } else if (callerApp == null || !callerApp.persistent) {
9609 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009610 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -07009611 intent.getAction())) {
9612 String msg = "Permission Denial: not allowed to send broadcast "
9613 + intent.getAction() + " from pid="
9614 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009615 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009616 throw new SecurityException(msg);
9617 }
9618 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009619 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -07009620 return BROADCAST_SUCCESS;
9621 }
9622 }
9623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009624 // Add to the sticky list if requested.
9625 if (sticky) {
9626 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
9627 callingPid, callingUid)
9628 != PackageManager.PERMISSION_GRANTED) {
9629 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
9630 + callingPid + ", uid=" + callingUid
9631 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009632 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009633 throw new SecurityException(msg);
9634 }
9635 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009636 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009637 + " and enforce permission " + requiredPermission);
9638 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
9639 }
9640 if (intent.getComponent() != null) {
9641 throw new SecurityException(
9642 "Sticky broadcasts can't target a specific component");
9643 }
9644 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9645 if (list == null) {
9646 list = new ArrayList<Intent>();
9647 mStickyBroadcasts.put(intent.getAction(), list);
9648 }
9649 int N = list.size();
9650 int i;
9651 for (i=0; i<N; i++) {
9652 if (intent.filterEquals(list.get(i))) {
9653 // This sticky already exists, replace it.
9654 list.set(i, new Intent(intent));
9655 break;
9656 }
9657 }
9658 if (i >= N) {
9659 list.add(new Intent(intent));
9660 }
9661 }
9662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009663 // Figure out who all will receive this broadcast.
9664 List receivers = null;
9665 List<BroadcastFilter> registeredReceivers = null;
9666 try {
9667 if (intent.getComponent() != null) {
9668 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009669 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07009670 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 if (ai != null) {
9672 receivers = new ArrayList();
9673 ResolveInfo ri = new ResolveInfo();
9674 ri.activityInfo = ai;
9675 receivers.add(ri);
9676 }
9677 } else {
9678 // Need to resolve the intent to interested receivers...
9679 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
9680 == 0) {
9681 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009682 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009683 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 }
Mihai Preda074edef2009-05-18 17:13:31 +02009685 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009686 }
9687 } catch (RemoteException ex) {
9688 // pm is in same process, this will never happen.
9689 }
9690
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009691 final boolean replacePending =
9692 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
9693
Joe Onorato8a9b2202010-02-26 18:56:32 -08009694 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009695 + " replacePending=" + replacePending);
9696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009697 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
9698 if (!ordered && NR > 0) {
9699 // If we are not serializing this broadcast, then send the
9700 // registered receivers separately so they don't wait for the
9701 // components to be launched.
9702 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9703 callerPackage, callingPid, callingUid, requiredPermission,
9704 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009705 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009706 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009707 TAG, "Enqueueing parallel broadcast " + r
9708 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009709 boolean replaced = false;
9710 if (replacePending) {
9711 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
9712 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009713 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009714 "***** DROPPING PARALLEL: " + intent);
9715 mParallelBroadcasts.set(i, r);
9716 replaced = true;
9717 break;
9718 }
9719 }
9720 }
9721 if (!replaced) {
9722 mParallelBroadcasts.add(r);
9723 scheduleBroadcastsLocked();
9724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009725 registeredReceivers = null;
9726 NR = 0;
9727 }
9728
9729 // Merge into one list.
9730 int ir = 0;
9731 if (receivers != null) {
9732 // A special case for PACKAGE_ADDED: do not allow the package
9733 // being added to see this broadcast. This prevents them from
9734 // using this as a back door to get run as soon as they are
9735 // installed. Maybe in the future we want to have a special install
9736 // broadcast or such for apps, but we'd like to deliberately make
9737 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009738 String skipPackages[] = null;
9739 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
9740 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
9741 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
9742 Uri data = intent.getData();
9743 if (data != null) {
9744 String pkgName = data.getSchemeSpecificPart();
9745 if (pkgName != null) {
9746 skipPackages = new String[] { pkgName };
9747 }
9748 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009749 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009750 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -07009751 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009752 if (skipPackages != null && (skipPackages.length > 0)) {
9753 for (String skipPackage : skipPackages) {
9754 if (skipPackage != null) {
9755 int NT = receivers.size();
9756 for (int it=0; it<NT; it++) {
9757 ResolveInfo curt = (ResolveInfo)receivers.get(it);
9758 if (curt.activityInfo.packageName.equals(skipPackage)) {
9759 receivers.remove(it);
9760 it--;
9761 NT--;
9762 }
9763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009764 }
9765 }
9766 }
9767
9768 int NT = receivers != null ? receivers.size() : 0;
9769 int it = 0;
9770 ResolveInfo curt = null;
9771 BroadcastFilter curr = null;
9772 while (it < NT && ir < NR) {
9773 if (curt == null) {
9774 curt = (ResolveInfo)receivers.get(it);
9775 }
9776 if (curr == null) {
9777 curr = registeredReceivers.get(ir);
9778 }
9779 if (curr.getPriority() >= curt.priority) {
9780 // Insert this broadcast record into the final list.
9781 receivers.add(it, curr);
9782 ir++;
9783 curr = null;
9784 it++;
9785 NT++;
9786 } else {
9787 // Skip to the next ResolveInfo in the final list.
9788 it++;
9789 curt = null;
9790 }
9791 }
9792 }
9793 while (ir < NR) {
9794 if (receivers == null) {
9795 receivers = new ArrayList();
9796 }
9797 receivers.add(registeredReceivers.get(ir));
9798 ir++;
9799 }
9800
9801 if ((receivers != null && receivers.size() > 0)
9802 || resultTo != null) {
9803 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
9804 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009805 receivers, resultTo, resultCode, resultData, map, ordered,
9806 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009807 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009808 TAG, "Enqueueing ordered broadcast " + r
9809 + ": prev had " + mOrderedBroadcasts.size());
9810 if (DEBUG_BROADCAST) {
9811 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009812 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009814 boolean replaced = false;
9815 if (replacePending) {
9816 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
9817 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009818 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08009819 "***** DROPPING ORDERED: " + intent);
9820 mOrderedBroadcasts.set(i, r);
9821 replaced = true;
9822 break;
9823 }
9824 }
9825 }
9826 if (!replaced) {
9827 mOrderedBroadcasts.add(r);
9828 scheduleBroadcastsLocked();
9829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 }
9831
9832 return BROADCAST_SUCCESS;
9833 }
9834
9835 public final int broadcastIntent(IApplicationThread caller,
9836 Intent intent, String resolvedType, IIntentReceiver resultTo,
9837 int resultCode, String resultData, Bundle map,
9838 String requiredPermission, boolean serialized, boolean sticky) {
9839 // Refuse possible leaked file descriptors
9840 if (intent != null && intent.hasFileDescriptors() == true) {
9841 throw new IllegalArgumentException("File descriptors passed in Intent");
9842 }
9843
9844 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009845 int flags = intent.getFlags();
9846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009847 if (!mSystemReady) {
9848 // if the caller really truly claims to know what they're doing, go
9849 // ahead and allow the broadcast without launching any receivers
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009850 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
9851 intent = new Intent(intent);
9852 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
9853 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
Joe Onorato8a9b2202010-02-26 18:56:32 -08009854 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009855 + " before boot completion");
9856 throw new IllegalStateException("Cannot broadcast before boot completed");
9857 }
9858 }
9859
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009860 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
9861 throw new IllegalArgumentException(
9862 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
9863 }
9864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9866 final int callingPid = Binder.getCallingPid();
9867 final int callingUid = Binder.getCallingUid();
9868 final long origId = Binder.clearCallingIdentity();
9869 int res = broadcastIntentLocked(callerApp,
9870 callerApp != null ? callerApp.info.packageName : null,
9871 intent, resolvedType, resultTo,
9872 resultCode, resultData, map, requiredPermission, serialized,
9873 sticky, callingPid, callingUid);
9874 Binder.restoreCallingIdentity(origId);
9875 return res;
9876 }
9877 }
9878
9879 int broadcastIntentInPackage(String packageName, int uid,
9880 Intent intent, String resolvedType, IIntentReceiver resultTo,
9881 int resultCode, String resultData, Bundle map,
9882 String requiredPermission, boolean serialized, boolean sticky) {
9883 synchronized(this) {
9884 final long origId = Binder.clearCallingIdentity();
9885 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
9886 resultTo, resultCode, resultData, map, requiredPermission,
9887 serialized, sticky, -1, uid);
9888 Binder.restoreCallingIdentity(origId);
9889 return res;
9890 }
9891 }
9892
9893 public final void unbroadcastIntent(IApplicationThread caller,
9894 Intent intent) {
9895 // Refuse possible leaked file descriptors
9896 if (intent != null && intent.hasFileDescriptors() == true) {
9897 throw new IllegalArgumentException("File descriptors passed in Intent");
9898 }
9899
9900 synchronized(this) {
9901 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
9902 != PackageManager.PERMISSION_GRANTED) {
9903 String msg = "Permission Denial: unbroadcastIntent() from pid="
9904 + Binder.getCallingPid()
9905 + ", uid=" + Binder.getCallingUid()
9906 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009907 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009908 throw new SecurityException(msg);
9909 }
9910 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
9911 if (list != null) {
9912 int N = list.size();
9913 int i;
9914 for (i=0; i<N; i++) {
9915 if (intent.filterEquals(list.get(i))) {
9916 list.remove(i);
9917 break;
9918 }
9919 }
9920 }
9921 }
9922 }
9923
9924 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
9925 String resultData, Bundle resultExtras, boolean resultAbort,
9926 boolean explicit) {
9927 if (mOrderedBroadcasts.size() == 0) {
9928 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009929 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009930 }
9931 return false;
9932 }
9933 BroadcastRecord r = mOrderedBroadcasts.get(0);
9934 if (r.receiver == null) {
9935 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009936 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009937 }
9938 return false;
9939 }
9940 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009941 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009942 return false;
9943 }
9944 int state = r.state;
9945 r.state = r.IDLE;
9946 if (state == r.IDLE) {
9947 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009948 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009949 }
9950 }
9951 r.receiver = null;
9952 r.intent.setComponent(null);
9953 if (r.curApp != null) {
9954 r.curApp.curReceiver = null;
9955 }
9956 if (r.curFilter != null) {
9957 r.curFilter.receiverList.curBroadcast = null;
9958 }
9959 r.curFilter = null;
9960 r.curApp = null;
9961 r.curComponent = null;
9962 r.curReceiver = null;
9963 mPendingBroadcast = null;
9964
9965 r.resultCode = resultCode;
9966 r.resultData = resultData;
9967 r.resultExtras = resultExtras;
9968 r.resultAbort = resultAbort;
9969
9970 // We will process the next receiver right now if this is finishing
9971 // an app receiver (which is always asynchronous) or after we have
9972 // come back from calling a receiver.
9973 return state == BroadcastRecord.APP_RECEIVE
9974 || state == BroadcastRecord.CALL_DONE_RECEIVE;
9975 }
9976
9977 public void finishReceiver(IBinder who, int resultCode, String resultData,
9978 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009979 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009980
9981 // Refuse possible leaked file descriptors
9982 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
9983 throw new IllegalArgumentException("File descriptors passed in Bundle");
9984 }
9985
9986 boolean doNext;
9987
9988 final long origId = Binder.clearCallingIdentity();
9989
9990 synchronized(this) {
9991 doNext = finishReceiverLocked(
9992 who, resultCode, resultData, resultExtras, resultAbort, true);
9993 }
9994
9995 if (doNext) {
9996 processNextBroadcast(false);
9997 }
9998 trimApplications();
9999
10000 Binder.restoreCallingIdentity(origId);
10001 }
10002
10003 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10004 if (r.nextReceiver > 0) {
10005 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10006 if (curReceiver instanceof BroadcastFilter) {
10007 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010008 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010009 System.identityHashCode(r),
10010 r.intent.getAction(),
10011 r.nextReceiver - 1,
10012 System.identityHashCode(bf));
10013 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010014 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010015 System.identityHashCode(r),
10016 r.intent.getAction(),
10017 r.nextReceiver - 1,
10018 ((ResolveInfo)curReceiver).toString());
10019 }
10020 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010021 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010022 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010023 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010024 System.identityHashCode(r),
10025 r.intent.getAction(),
10026 r.nextReceiver,
10027 "NONE");
10028 }
10029 }
10030
10031 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010032 ProcessRecord app = null;
10033 String anrMessage = null;
10034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010035 synchronized (this) {
10036 if (mOrderedBroadcasts.size() == 0) {
10037 return;
10038 }
10039 long now = SystemClock.uptimeMillis();
10040 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010041 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010042 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010043 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010044 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010045 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010046 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 return;
10048 }
10049
Joe Onorato8a9b2202010-02-26 18:56:32 -080010050 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010051 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010052 r.anrCount++;
10053
10054 // Current receiver has passed its expiration date.
10055 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010056 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010057 return;
10058 }
10059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010060 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010061 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010062 logBroadcastReceiverDiscard(r);
10063 if (curReceiver instanceof BroadcastFilter) {
10064 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10065 if (bf.receiverList.pid != 0
10066 && bf.receiverList.pid != MY_PID) {
10067 synchronized (this.mPidsSelfLocked) {
10068 app = this.mPidsSelfLocked.get(
10069 bf.receiverList.pid);
10070 }
10071 }
10072 } else {
10073 app = r.curApp;
10074 }
10075
10076 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010077 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078 }
10079
10080 if (mPendingBroadcast == r) {
10081 mPendingBroadcast = null;
10082 }
10083
10084 // Move on to the next receiver.
10085 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10086 r.resultExtras, r.resultAbort, true);
10087 scheduleBroadcastsLocked();
10088 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010089
10090 if (anrMessage != null) {
10091 appNotResponding(app, null, null, anrMessage);
10092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010093 }
10094
10095 private final void processCurBroadcastLocked(BroadcastRecord r,
10096 ProcessRecord app) throws RemoteException {
10097 if (app.thread == null) {
10098 throw new RemoteException();
10099 }
10100 r.receiver = app.thread.asBinder();
10101 r.curApp = app;
10102 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010103 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010104
10105 // Tell the application to launch this receiver.
10106 r.intent.setComponent(r.curComponent);
10107
10108 boolean started = false;
10109 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010110 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010111 "Delivering to component " + r.curComponent
10112 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010113 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10115 r.resultCode, r.resultData, r.resultExtras, r.ordered);
10116 started = true;
10117 } finally {
10118 if (!started) {
10119 r.receiver = null;
10120 r.curApp = null;
10121 app.curReceiver = null;
10122 }
10123 }
10124
10125 }
10126
10127 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010128 Intent intent, int resultCode, String data, Bundle extras,
10129 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130 if (app != null && app.thread != null) {
10131 // If we have an app thread, do the call through that so it is
10132 // correctly ordered with other one-way calls.
10133 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010134 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010135 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010136 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010137 }
10138 }
10139
10140 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10141 BroadcastFilter filter, boolean ordered) {
10142 boolean skip = false;
10143 if (filter.requiredPermission != null) {
10144 int perm = checkComponentPermission(filter.requiredPermission,
10145 r.callingPid, r.callingUid, -1);
10146 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010147 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010148 + r.intent.toString()
10149 + " from " + r.callerPackage + " (pid="
10150 + r.callingPid + ", uid=" + r.callingUid + ")"
10151 + " requires " + filter.requiredPermission
10152 + " due to registered receiver " + filter);
10153 skip = true;
10154 }
10155 }
10156 if (r.requiredPermission != null) {
10157 int perm = checkComponentPermission(r.requiredPermission,
10158 filter.receiverList.pid, filter.receiverList.uid, -1);
10159 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010160 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010161 + r.intent.toString()
10162 + " to " + filter.receiverList.app
10163 + " (pid=" + filter.receiverList.pid
10164 + ", uid=" + filter.receiverList.uid + ")"
10165 + " requires " + r.requiredPermission
10166 + " due to sender " + r.callerPackage
10167 + " (uid " + r.callingUid + ")");
10168 skip = true;
10169 }
10170 }
10171
10172 if (!skip) {
10173 // If this is not being sent as an ordered broadcast, then we
10174 // don't want to touch the fields that keep track of the current
10175 // state of ordered broadcasts.
10176 if (ordered) {
10177 r.receiver = filter.receiverList.receiver.asBinder();
10178 r.curFilter = filter;
10179 filter.receiverList.curBroadcast = r;
10180 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010181 if (filter.receiverList.app != null) {
10182 // Bump hosting application to no longer be in background
10183 // scheduling class. Note that we can't do that if there
10184 // isn't an app... but we can only be in that case for
10185 // things that directly call the IActivityManager API, which
10186 // are already core system stuff so don't matter for this.
10187 r.curApp = filter.receiverList.app;
10188 filter.receiverList.app.curReceiver = r;
10189 updateOomAdjLocked();
10190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010191 }
10192 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010193 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010194 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010195 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010196 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010197 }
10198 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10199 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010200 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010201 if (ordered) {
10202 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10203 }
10204 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010205 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010206 if (ordered) {
10207 r.receiver = null;
10208 r.curFilter = null;
10209 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010210 if (filter.receiverList.app != null) {
10211 filter.receiverList.app.curReceiver = null;
10212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 }
10214 }
10215 }
10216 }
10217
Dianne Hackborn12527f92009-11-11 17:39:50 -080010218 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10219 if (r.callingUid < 0) {
10220 // This was from a registerReceiver() call; ignore it.
10221 return;
10222 }
10223 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10224 MAX_BROADCAST_HISTORY-1);
10225 r.finishTime = SystemClock.uptimeMillis();
10226 mBroadcastHistory[0] = r;
10227 }
10228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 private final void processNextBroadcast(boolean fromMsg) {
10230 synchronized(this) {
10231 BroadcastRecord r;
10232
Joe Onorato8a9b2202010-02-26 18:56:32 -080010233 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010235 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236
10237 updateCpuStats();
10238
10239 if (fromMsg) {
10240 mBroadcastsScheduled = false;
10241 }
10242
10243 // First, deliver any non-serialized broadcasts right away.
10244 while (mParallelBroadcasts.size() > 0) {
10245 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010246 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010247 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010248 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010249 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010250 for (int i=0; i<N; i++) {
10251 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010252 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010253 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 + target + ": " + r);
10255 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10256 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010257 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010258 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010259 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010260 }
10261
10262 // Now take care of the next serialized one...
10263
10264 // If we are waiting for a process to come up to handle the next
10265 // broadcast, then do nothing at this point. Just in case, we
10266 // check that the process we're waiting for still exists.
10267 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010268 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010269 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010270 + mPendingBroadcast.curApp);
10271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272
10273 boolean isDead;
10274 synchronized (mPidsSelfLocked) {
10275 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10276 }
10277 if (!isDead) {
10278 // It's still alive, so keep waiting
10279 return;
10280 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010281 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010282 + " died before responding to broadcast");
10283 mPendingBroadcast = null;
10284 }
10285 }
10286
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010287 boolean looped = false;
10288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010289 do {
10290 if (mOrderedBroadcasts.size() == 0) {
10291 // No more broadcasts pending, so all done!
10292 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010293 if (looped) {
10294 // If we had finished the last ordered broadcast, then
10295 // make sure all processes have correct oom and sched
10296 // adjustments.
10297 updateOomAdjLocked();
10298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 return;
10300 }
10301 r = mOrderedBroadcasts.get(0);
10302 boolean forceReceive = false;
10303
10304 // Ensure that even if something goes awry with the timeout
10305 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010306 // and continue to make progress.
10307 //
10308 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10309 // receivers don't get executed with with timeouts. They're intended for
10310 // one time heavy lifting after system upgrades and can take
10311 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010312 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010313 if (mSystemReady && r.dispatchTime > 0) {
10314 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 if ((numReceivers > 0) &&
10316 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010317 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010318 + " now=" + now
10319 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010320 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010321 + " intent=" + r.intent
10322 + " numReceivers=" + numReceivers
10323 + " nextReceiver=" + r.nextReceiver
10324 + " state=" + r.state);
10325 broadcastTimeout(); // forcibly finish this broadcast
10326 forceReceive = true;
10327 r.state = BroadcastRecord.IDLE;
10328 }
10329 }
10330
10331 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010332 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010333 "processNextBroadcast() called when not idle (state="
10334 + r.state + ")");
10335 return;
10336 }
10337
10338 if (r.receivers == null || r.nextReceiver >= numReceivers
10339 || r.resultAbort || forceReceive) {
10340 // No more receivers for this broadcast! Send the final
10341 // result if requested...
10342 if (r.resultTo != null) {
10343 try {
10344 if (DEBUG_BROADCAST) {
10345 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010346 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010347 + " seq=" + seq + " app=" + r.callerApp);
10348 }
10349 performReceive(r.callerApp, r.resultTo,
10350 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010351 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010352 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010353 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 }
10355 }
10356
Joe Onorato8a9b2202010-02-26 18:56:32 -080010357 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10359
Joe Onorato8a9b2202010-02-26 18:56:32 -080010360 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010361 + r);
10362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010363 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010364 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010365 mOrderedBroadcasts.remove(0);
10366 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010367 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010368 continue;
10369 }
10370 } while (r == null);
10371
10372 // Get the next receiver...
10373 int recIdx = r.nextReceiver++;
10374
10375 // Keep track of when this receiver started, and make sure there
10376 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010377 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010379 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010380
Joe Onorato8a9b2202010-02-26 18:56:32 -080010381 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010382 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010383 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010384 "Submitting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010385 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010386 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010387 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 }
10389
10390 Object nextReceiver = r.receivers.get(recIdx);
10391 if (nextReceiver instanceof BroadcastFilter) {
10392 // Simple case: this is a registered receiver who gets
10393 // a direct call.
10394 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010395 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010396 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010397 + filter + ": " + r);
10398 deliverToRegisteredReceiver(r, filter, r.ordered);
10399 if (r.receiver == null || !r.ordered) {
10400 // The receiver has already finished, so schedule to
10401 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010402 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10403 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010404 r.state = BroadcastRecord.IDLE;
10405 scheduleBroadcastsLocked();
10406 }
10407 return;
10408 }
10409
10410 // Hard case: need to instantiate the receiver, possibly
10411 // starting its application process to host it.
10412
10413 ResolveInfo info =
10414 (ResolveInfo)nextReceiver;
10415
10416 boolean skip = false;
10417 int perm = checkComponentPermission(info.activityInfo.permission,
10418 r.callingPid, r.callingUid,
10419 info.activityInfo.exported
10420 ? -1 : info.activityInfo.applicationInfo.uid);
10421 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010422 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 + r.intent.toString()
10424 + " from " + r.callerPackage + " (pid=" + r.callingPid
10425 + ", uid=" + r.callingUid + ")"
10426 + " requires " + info.activityInfo.permission
10427 + " due to receiver " + info.activityInfo.packageName
10428 + "/" + info.activityInfo.name);
10429 skip = true;
10430 }
10431 if (r.callingUid != Process.SYSTEM_UID &&
10432 r.requiredPermission != null) {
10433 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010434 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 checkPermission(r.requiredPermission,
10436 info.activityInfo.applicationInfo.packageName);
10437 } catch (RemoteException e) {
10438 perm = PackageManager.PERMISSION_DENIED;
10439 }
10440 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010441 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010442 + r.intent + " to "
10443 + info.activityInfo.applicationInfo.packageName
10444 + " requires " + r.requiredPermission
10445 + " due to sender " + r.callerPackage
10446 + " (uid " + r.callingUid + ")");
10447 skip = true;
10448 }
10449 }
10450 if (r.curApp != null && r.curApp.crashing) {
10451 // If the target process is crashing, just skip it.
10452 skip = true;
10453 }
10454
10455 if (skip) {
10456 r.receiver = null;
10457 r.curFilter = null;
10458 r.state = BroadcastRecord.IDLE;
10459 scheduleBroadcastsLocked();
10460 return;
10461 }
10462
10463 r.state = BroadcastRecord.APP_RECEIVE;
10464 String targetProcess = info.activityInfo.processName;
10465 r.curComponent = new ComponentName(
10466 info.activityInfo.applicationInfo.packageName,
10467 info.activityInfo.name);
10468 r.curReceiver = info.activityInfo;
10469
10470 // Is this receiver's application already running?
10471 ProcessRecord app = getProcessRecordLocked(targetProcess,
10472 info.activityInfo.applicationInfo.uid);
10473 if (app != null && app.thread != null) {
10474 try {
10475 processCurBroadcastLocked(r, app);
10476 return;
10477 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010478 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 + r.curComponent, e);
10480 }
10481
10482 // If a dead object exception was thrown -- fall through to
10483 // restart the application.
10484 }
10485
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010486 // Not running -- get it started, to be executed when the app comes up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010487 if ((r.curApp=startProcessLocked(targetProcess,
10488 info.activityInfo.applicationInfo, true,
10489 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010490 "broadcast", r.curComponent,
10491 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
10492 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010493 // Ah, this recipient is unavailable. Finish it if necessary,
10494 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010495 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010496 + info.activityInfo.applicationInfo.packageName + "/"
10497 + info.activityInfo.applicationInfo.uid + " for broadcast "
10498 + r.intent + ": process is bad");
10499 logBroadcastReceiverDiscard(r);
10500 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10501 r.resultExtras, r.resultAbort, true);
10502 scheduleBroadcastsLocked();
10503 r.state = BroadcastRecord.IDLE;
10504 return;
10505 }
10506
10507 mPendingBroadcast = r;
10508 }
10509 }
10510
10511 // =========================================================
10512 // INSTRUMENTATION
10513 // =========================================================
10514
10515 public boolean startInstrumentation(ComponentName className,
10516 String profileFile, int flags, Bundle arguments,
10517 IInstrumentationWatcher watcher) {
10518 // Refuse possible leaked file descriptors
10519 if (arguments != null && arguments.hasFileDescriptors()) {
10520 throw new IllegalArgumentException("File descriptors passed in Bundle");
10521 }
10522
10523 synchronized(this) {
10524 InstrumentationInfo ii = null;
10525 ApplicationInfo ai = null;
10526 try {
10527 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010528 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010529 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010530 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 } catch (PackageManager.NameNotFoundException e) {
10532 }
10533 if (ii == null) {
10534 reportStartInstrumentationFailure(watcher, className,
10535 "Unable to find instrumentation info for: " + className);
10536 return false;
10537 }
10538 if (ai == null) {
10539 reportStartInstrumentationFailure(watcher, className,
10540 "Unable to find instrumentation target package: " + ii.targetPackage);
10541 return false;
10542 }
10543
10544 int match = mContext.getPackageManager().checkSignatures(
10545 ii.targetPackage, ii.packageName);
10546 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
10547 String msg = "Permission Denial: starting instrumentation "
10548 + className + " from pid="
10549 + Binder.getCallingPid()
10550 + ", uid=" + Binder.getCallingPid()
10551 + " not allowed because package " + ii.packageName
10552 + " does not have a signature matching the target "
10553 + ii.targetPackage;
10554 reportStartInstrumentationFailure(watcher, className, msg);
10555 throw new SecurityException(msg);
10556 }
10557
10558 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010559 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010560 ProcessRecord app = addAppLocked(ai);
10561 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010562 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010563 app.instrumentationProfileFile = profileFile;
10564 app.instrumentationArguments = arguments;
10565 app.instrumentationWatcher = watcher;
10566 app.instrumentationResultClass = className;
10567 Binder.restoreCallingIdentity(origId);
10568 }
10569
10570 return true;
10571 }
10572
10573 /**
10574 * Report errors that occur while attempting to start Instrumentation. Always writes the
10575 * error to the logs, but if somebody is watching, send the report there too. This enables
10576 * the "am" command to report errors with more information.
10577 *
10578 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
10579 * @param cn The component name of the instrumentation.
10580 * @param report The error report.
10581 */
10582 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
10583 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010584 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 try {
10586 if (watcher != null) {
10587 Bundle results = new Bundle();
10588 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
10589 results.putString("Error", report);
10590 watcher.instrumentationStatus(cn, -1, results);
10591 }
10592 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010593 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010594 }
10595 }
10596
10597 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
10598 if (app.instrumentationWatcher != null) {
10599 try {
10600 // NOTE: IInstrumentationWatcher *must* be oneway here
10601 app.instrumentationWatcher.instrumentationFinished(
10602 app.instrumentationClass,
10603 resultCode,
10604 results);
10605 } catch (RemoteException e) {
10606 }
10607 }
10608 app.instrumentationWatcher = null;
10609 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070010610 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 app.instrumentationProfileFile = null;
10612 app.instrumentationArguments = null;
10613
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010614 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 }
10616
10617 public void finishInstrumentation(IApplicationThread target,
10618 int resultCode, Bundle results) {
10619 // Refuse possible leaked file descriptors
10620 if (results != null && results.hasFileDescriptors()) {
10621 throw new IllegalArgumentException("File descriptors passed in Intent");
10622 }
10623
10624 synchronized(this) {
10625 ProcessRecord app = getRecordForAppLocked(target);
10626 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010627 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010628 return;
10629 }
10630 final long origId = Binder.clearCallingIdentity();
10631 finishInstrumentationLocked(app, resultCode, results);
10632 Binder.restoreCallingIdentity(origId);
10633 }
10634 }
10635
10636 // =========================================================
10637 // CONFIGURATION
10638 // =========================================================
10639
10640 public ConfigurationInfo getDeviceConfigurationInfo() {
10641 ConfigurationInfo config = new ConfigurationInfo();
10642 synchronized (this) {
10643 config.reqTouchScreen = mConfiguration.touchscreen;
10644 config.reqKeyboardType = mConfiguration.keyboard;
10645 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010646 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
10647 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
10649 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070010650 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
10651 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
10653 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070010654 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010655 }
10656 return config;
10657 }
10658
10659 public Configuration getConfiguration() {
10660 Configuration ci;
10661 synchronized(this) {
10662 ci = new Configuration(mConfiguration);
10663 }
10664 return ci;
10665 }
10666
10667 public void updateConfiguration(Configuration values) {
10668 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
10669 "updateConfiguration()");
10670
10671 synchronized(this) {
10672 if (values == null && mWindowManager != null) {
10673 // sentinel: fetch the current configuration from the window manager
10674 values = mWindowManager.computeNewConfiguration();
10675 }
10676
10677 final long origId = Binder.clearCallingIdentity();
10678 updateConfigurationLocked(values, null);
10679 Binder.restoreCallingIdentity(origId);
10680 }
10681 }
10682
10683 /**
10684 * Do either or both things: (1) change the current configuration, and (2)
10685 * make sure the given activity is running with the (now) current
10686 * configuration. Returns true if the activity has been left running, or
10687 * false if <var>starting</var> is being destroyed to match the new
10688 * configuration.
10689 */
10690 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010691 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010692 int changes = 0;
10693
10694 boolean kept = true;
10695
10696 if (values != null) {
10697 Configuration newConfig = new Configuration(mConfiguration);
10698 changes = newConfig.updateFrom(values);
10699 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010700 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010701 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010702 }
10703
Doug Zongker2bec3d42009-12-04 12:52:44 -080010704 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705
10706 if (values.locale != null) {
10707 saveLocaleLocked(values.locale,
10708 !values.locale.equals(mConfiguration.locale),
10709 values.userSetLocale);
10710 }
10711
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010712 mConfigurationSeq++;
10713 if (mConfigurationSeq <= 0) {
10714 mConfigurationSeq = 1;
10715 }
10716 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010717 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010718 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080010719
10720 AttributeCache ac = AttributeCache.instance();
10721 if (ac != null) {
10722 ac.updateConfiguration(mConfiguration);
10723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010724
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010725 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
10726 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
10727 msg.obj = new Configuration(mConfiguration);
10728 mHandler.sendMessage(msg);
10729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010730
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010731 for (int i=mLruProcesses.size()-1; i>=0; i--) {
10732 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010733 try {
10734 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010735 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070010736 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010737 app.thread.scheduleConfigurationChanged(mConfiguration);
10738 }
10739 } catch (Exception e) {
10740 }
10741 }
10742 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010743 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
10744 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010745 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
10746 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080010747 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
10748 broadcastIntentLocked(null, null,
10749 new Intent(Intent.ACTION_LOCALE_CHANGED),
10750 null, null, 0, null, null,
10751 null, false, false, MY_PID, Process.SYSTEM_UID);
10752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 }
10754 }
10755
10756 if (changes != 0 && starting == null) {
10757 // If the configuration changed, and the caller is not already
10758 // in the process of starting an activity, then find the top
10759 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010760 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 }
10762
10763 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010764 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 if (kept) {
10766 // If this didn't result in the starting activity being
10767 // destroyed, then we need to make sure at this point that all
10768 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010769 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010770 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010771 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 }
10773 }
10774
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010775 if (values != null && mWindowManager != null) {
10776 mWindowManager.setNewConfiguration(mConfiguration);
10777 }
10778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010779 return kept;
10780 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010781
10782 /**
10783 * Save the locale. You must be inside a synchronized (this) block.
10784 */
10785 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
10786 if(isDiff) {
10787 SystemProperties.set("user.language", l.getLanguage());
10788 SystemProperties.set("user.region", l.getCountry());
10789 }
10790
10791 if(isPersist) {
10792 SystemProperties.set("persist.sys.language", l.getLanguage());
10793 SystemProperties.set("persist.sys.country", l.getCountry());
10794 SystemProperties.set("persist.sys.localevar", l.getVariant());
10795 }
10796 }
10797
10798 // =========================================================
10799 // LIFETIME MANAGEMENT
10800 // =========================================================
10801
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010802 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
10803 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010804 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010805 // This adjustment has already been computed. If we are calling
10806 // from the top, we may have already computed our adjustment with
10807 // an earlier hidden adjustment that isn't really for us... if
10808 // so, use the new hidden adjustment.
10809 if (!recursed && app.hidden) {
10810 app.curAdj = hiddenAdj;
10811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010812 return app.curAdj;
10813 }
10814
10815 if (app.thread == null) {
10816 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010817 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010818 return (app.curAdj=EMPTY_APP_ADJ);
10819 }
10820
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010821 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
10822 // The max adjustment doesn't allow this app to be anything
10823 // below foreground, so it is not worth doing work for it.
10824 app.adjType = "fixed";
10825 app.adjSeq = mAdjSeq;
10826 app.curRawAdj = app.maxAdj;
10827 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
10828 return (app.curAdj=app.maxAdj);
10829 }
10830
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010831 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010832 app.adjSource = null;
10833 app.adjTarget = null;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010834 app.empty = false;
10835 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836
The Android Open Source Project4df24232009-03-05 14:34:35 -080010837 // Determine the importance of the process, starting with most
10838 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010840 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010841 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010842 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010843 // The last app on the list is the foreground app.
10844 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010845 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010846 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010847 } else if (app.instrumentationClass != null) {
10848 // Don't want to kill running instrumentation.
10849 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010850 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010851 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010852 } else if (app.persistentActivities > 0) {
10853 // Special persistent activities... shouldn't be used these days.
10854 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010855 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010856 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010857 } else if (app.curReceiver != null ||
10858 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
10859 // An app that is currently receiving a broadcast also
10860 // counts as being in the foreground.
10861 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010862 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010863 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 } else if (app.executingServices.size() > 0) {
10865 // An app that is currently executing a service callback also
10866 // counts as being in the foreground.
10867 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010868 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010869 app.adjType = "exec-service";
10870 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010871 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010872 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010873 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010874 app.adjType = "foreground-service";
10875 } else if (app.forcingToForeground != null) {
10876 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010877 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010878 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010879 app.adjType = "force-foreground";
10880 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010881 } else if (app == mHeavyWeightProcess) {
10882 // We don't want to kill the current heavy-weight process.
10883 adj = HEAVY_WEIGHT_APP_ADJ;
10884 schedGroup = Process.THREAD_GROUP_DEFAULT;
10885 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080010886 } else if (app == mHomeProcess) {
10887 // This process is hosting what we currently consider to be the
10888 // home app, so we don't want to let it go into the background.
10889 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010890 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010891 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 } else if ((N=app.activities.size()) != 0) {
10893 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010894 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010895 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010896 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010897 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010898 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010899 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010900 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010901 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010902 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010903 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010904 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010905 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 break;
10907 }
10908 }
10909 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010910 // A very not-needed process. If this is lower in the lru list,
10911 // we will push it in to the empty bucket.
10912 app.hidden = true;
10913 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010914 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010915 adj = hiddenAdj;
10916 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 }
10918
Joe Onorato8a9b2202010-02-26 18:56:32 -080010919 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010920
The Android Open Source Project4df24232009-03-05 14:34:35 -080010921 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010922 // there are applications dependent on our services or providers, but
10923 // this gives us a baseline and makes sure we don't get into an
10924 // infinite recursion.
10925 app.adjSeq = mAdjSeq;
10926 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010927
Christopher Tate6fa95972009-06-05 18:43:55 -070010928 if (mBackupTarget != null && app == mBackupTarget.app) {
10929 // If possible we want to avoid killing apps while they're being backed up
10930 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010931 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070010932 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010933 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010934 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070010935 }
10936 }
10937
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010938 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
10939 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010940 final long now = SystemClock.uptimeMillis();
10941 // This process is more important if the top activity is
10942 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010943 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010945 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010946 if (s.startRequested) {
10947 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
10948 // This service has seen some activity within
10949 // recent memory, so we will keep its process ahead
10950 // of the background processes.
10951 if (adj > SECONDARY_SERVER_ADJ) {
10952 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010953 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010954 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010955 }
10956 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080010957 // If we have let the service slide into the background
10958 // state, still have some text describing what it is doing
10959 // even though the service no longer has an impact.
10960 if (adj > SECONDARY_SERVER_ADJ) {
10961 app.adjType = "started-bg-services";
10962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080010964 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
10965 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 Iterator<ConnectionRecord> kt
10967 = s.connections.values().iterator();
10968 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
10969 // XXX should compute this based on the max of
10970 // all connected clients.
10971 ConnectionRecord cr = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070010972 if (cr.binding.client == app) {
10973 // Binding to ourself is not interesting.
10974 continue;
10975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
10977 ProcessRecord client = cr.binding.client;
10978 int myHiddenAdj = hiddenAdj;
10979 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010980 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010981 myHiddenAdj = client.hiddenAdj;
10982 } else {
10983 myHiddenAdj = VISIBLE_APP_ADJ;
10984 }
10985 }
10986 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010987 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010988 if (adj > clientAdj) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -070010989 adj = clientAdj >= VISIBLE_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010990 ? clientAdj : VISIBLE_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010991 if (!client.hidden) {
10992 app.hidden = false;
10993 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010994 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010995 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
10996 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010997 app.adjSource = cr.binding.client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070010998 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010999 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011000 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11001 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11002 schedGroup = Process.THREAD_GROUP_DEFAULT;
11003 }
11004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011005 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011006 ActivityRecord a = cr.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 //if (a != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011008 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011009 //}
11010 if (a != null && adj > FOREGROUND_APP_ADJ &&
11011 (a.state == ActivityState.RESUMED
11012 || a.state == ActivityState.PAUSING)) {
11013 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011014 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011015 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011016 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011017 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11018 .REASON_SERVICE_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011019 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011020 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 }
11022 }
11023 }
11024 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011025
11026 // Finally, f this process has active services running in it, we
11027 // would like to avoid killing it unless it would prevent the current
11028 // application from running. By default we put the process in
11029 // with the rest of the background processes; as we scan through
11030 // its services we may bump it up from there.
11031 if (adj > hiddenAdj) {
11032 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011033 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011034 app.adjType = "bg-services";
11035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 }
11037
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011038 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11039 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011040 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011041 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11042 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011043 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 if (cpr.clients.size() != 0) {
11045 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11046 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11047 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011048 if (client == app) {
11049 // Being our own client is not interesting.
11050 continue;
11051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 int myHiddenAdj = hiddenAdj;
11053 if (myHiddenAdj > client.hiddenAdj) {
11054 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11055 myHiddenAdj = client.hiddenAdj;
11056 } else {
11057 myHiddenAdj = FOREGROUND_APP_ADJ;
11058 }
11059 }
11060 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011061 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 if (adj > clientAdj) {
11063 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011064 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011065 if (!client.hidden) {
11066 app.hidden = false;
11067 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011068 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011069 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11070 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011071 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011072 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011073 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011074 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11075 schedGroup = Process.THREAD_GROUP_DEFAULT;
11076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 }
11078 }
11079 // If the provider has external (non-framework) process
11080 // dependencies, ensure that its adjustment is at least
11081 // FOREGROUND_APP_ADJ.
11082 if (cpr.externals != 0) {
11083 if (adj > FOREGROUND_APP_ADJ) {
11084 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011085 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011086 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011087 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011088 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 }
11090 }
11091 }
11092 }
11093
11094 app.curRawAdj = adj;
11095
Joe Onorato8a9b2202010-02-26 18:56:32 -080011096 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011097 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11098 if (adj > app.maxAdj) {
11099 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011100 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011101 schedGroup = Process.THREAD_GROUP_DEFAULT;
11102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011103 }
11104
11105 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011106 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011108 return adj;
11109 }
11110
11111 /**
11112 * Ask a given process to GC right now.
11113 */
11114 final void performAppGcLocked(ProcessRecord app) {
11115 try {
11116 app.lastRequestedGc = SystemClock.uptimeMillis();
11117 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011118 if (app.reportLowMemory) {
11119 app.reportLowMemory = false;
11120 app.thread.scheduleLowMemory();
11121 } else {
11122 app.thread.processInBackground();
11123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011124 }
11125 } catch (Exception e) {
11126 // whatever.
11127 }
11128 }
11129
11130 /**
11131 * Returns true if things are idle enough to perform GCs.
11132 */
Josh Bartel7f208742010-02-25 11:01:44 -060011133 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 return mParallelBroadcasts.size() == 0
11135 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011136 && (mSleeping || (mMainStack.mResumedActivity != null &&
11137 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011138 }
11139
11140 /**
11141 * Perform GCs on all processes that are waiting for it, but only
11142 * if things are idle.
11143 */
11144 final void performAppGcsLocked() {
11145 final int N = mProcessesToGc.size();
11146 if (N <= 0) {
11147 return;
11148 }
Josh Bartel7f208742010-02-25 11:01:44 -060011149 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 while (mProcessesToGc.size() > 0) {
11151 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011152 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011153 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11154 <= SystemClock.uptimeMillis()) {
11155 // To avoid spamming the system, we will GC processes one
11156 // at a time, waiting a few seconds between each.
11157 performAppGcLocked(proc);
11158 scheduleAppGcsLocked();
11159 return;
11160 } else {
11161 // It hasn't been long enough since we last GCed this
11162 // process... put it in the list to wait for its time.
11163 addProcessToGcListLocked(proc);
11164 break;
11165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011166 }
11167 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011168
11169 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 }
11171 }
11172
11173 /**
11174 * If all looks good, perform GCs on all processes waiting for them.
11175 */
11176 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011177 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011178 performAppGcsLocked();
11179 return;
11180 }
11181 // Still not idle, wait some more.
11182 scheduleAppGcsLocked();
11183 }
11184
11185 /**
11186 * Schedule the execution of all pending app GCs.
11187 */
11188 final void scheduleAppGcsLocked() {
11189 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011190
11191 if (mProcessesToGc.size() > 0) {
11192 // Schedule a GC for the time to the next process.
11193 ProcessRecord proc = mProcessesToGc.get(0);
11194 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11195
11196 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11197 long now = SystemClock.uptimeMillis();
11198 if (when < (now+GC_TIMEOUT)) {
11199 when = now + GC_TIMEOUT;
11200 }
11201 mHandler.sendMessageAtTime(msg, when);
11202 }
11203 }
11204
11205 /**
11206 * Add a process to the array of processes waiting to be GCed. Keeps the
11207 * list in sorted order by the last GC time. The process can't already be
11208 * on the list.
11209 */
11210 final void addProcessToGcListLocked(ProcessRecord proc) {
11211 boolean added = false;
11212 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11213 if (mProcessesToGc.get(i).lastRequestedGc <
11214 proc.lastRequestedGc) {
11215 added = true;
11216 mProcessesToGc.add(i+1, proc);
11217 break;
11218 }
11219 }
11220 if (!added) {
11221 mProcessesToGc.add(0, proc);
11222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011223 }
11224
11225 /**
11226 * Set up to ask a process to GC itself. This will either do it
11227 * immediately, or put it on the list of processes to gc the next
11228 * time things are idle.
11229 */
11230 final void scheduleAppGcLocked(ProcessRecord app) {
11231 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011232 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 return;
11234 }
11235 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011236 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 scheduleAppGcsLocked();
11238 }
11239 }
11240
11241 private final boolean updateOomAdjLocked(
11242 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11243 app.hiddenAdj = hiddenAdj;
11244
11245 if (app.thread == null) {
11246 return true;
11247 }
11248
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011249 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011251 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011252 if (app.curRawAdj != app.setRawAdj) {
11253 if (app.curRawAdj > FOREGROUND_APP_ADJ
11254 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11255 // If this app is transitioning from foreground to
11256 // non-foreground, have it do a gc.
11257 scheduleAppGcLocked(app);
11258 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11259 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11260 // Likewise do a gc when an app is moving in to the
11261 // background (such as a service stopping).
11262 scheduleAppGcLocked(app);
11263 }
11264 app.setRawAdj = app.curRawAdj;
11265 }
11266 if (adj != app.setAdj) {
11267 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011268 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 TAG, "Set app " + app.processName +
11270 " oom adj to " + adj);
11271 app.setAdj = adj;
11272 } else {
11273 return false;
11274 }
11275 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011276 if (app.setSchedGroup != app.curSchedGroup) {
11277 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011278 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011279 "Setting process group of " + app.processName
11280 + " to " + app.curSchedGroup);
11281 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011282 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011283 try {
11284 Process.setProcessGroup(app.pid, app.curSchedGroup);
11285 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011286 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011287 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011288 e.printStackTrace();
11289 } finally {
11290 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011291 }
11292 }
11293 if (false) {
11294 if (app.thread != null) {
11295 try {
11296 app.thread.setSchedulingGroup(app.curSchedGroup);
11297 } catch (RemoteException e) {
11298 }
11299 }
11300 }
11301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011302 }
11303
11304 return true;
11305 }
11306
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011307 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011308 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011309 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011310 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011311 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011312 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 }
11314 }
11315 return resumedActivity;
11316 }
11317
11318 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011319 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011320 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11321 int curAdj = app.curAdj;
11322 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11323 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11324
11325 mAdjSeq++;
11326
11327 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11328 if (res) {
11329 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11330 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11331 if (nowHidden != wasHidden) {
11332 // Changed to/from hidden state, so apps after it in the LRU
11333 // list may also be changed.
11334 updateOomAdjLocked();
11335 }
11336 }
11337 return res;
11338 }
11339
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011340 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011342 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011343 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11344
11345 if (false) {
11346 RuntimeException e = new RuntimeException();
11347 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011348 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011349 }
11350
11351 mAdjSeq++;
11352
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011353 // Let's determine how many processes we have running vs.
11354 // how many slots we have for background processes; we may want
11355 // to put multiple processes in a slot of there are enough of
11356 // them.
11357 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11358 int factor = (mLruProcesses.size()-4)/numSlots;
11359 if (factor < 1) factor = 1;
11360 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070011361 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011363 // First try updating the OOM adjustment for each of the
11364 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011365 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011366 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
11367 while (i > 0) {
11368 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011369 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011370 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011371 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011372 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011373 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011374 step++;
11375 if (step >= factor) {
11376 step = 0;
11377 curHiddenAdj++;
11378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011379 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011380 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070011381 if (!app.killedBackground) {
11382 numHidden++;
11383 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070011384 Slog.i(TAG, "No longer want " + app.processName
11385 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011386 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11387 app.processName, app.setAdj, "too many background");
11388 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070011389 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070011390 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070011391 }
11392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 } else {
11394 didOomAdj = false;
11395 }
11396 }
11397
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011398 // If we return false, we will fall back on killing processes to
11399 // have a fixed limit. Do this if a limit has been requested; else
11400 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011401 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
11402 }
11403
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011404 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 synchronized (this) {
11406 int i;
11407
11408 // First remove any unused application processes whose package
11409 // has been removed.
11410 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
11411 final ProcessRecord app = mRemovedProcesses.get(i);
11412 if (app.activities.size() == 0
11413 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011414 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011415 TAG, "Exiting empty application process "
11416 + app.processName + " ("
11417 + (app.thread != null ? app.thread.asBinder() : null)
11418 + ")\n");
11419 if (app.pid > 0 && app.pid != MY_PID) {
11420 Process.killProcess(app.pid);
11421 } else {
11422 try {
11423 app.thread.scheduleExit();
11424 } catch (Exception e) {
11425 // Ignore exceptions.
11426 }
11427 }
11428 cleanUpApplicationRecordLocked(app, false, -1);
11429 mRemovedProcesses.remove(i);
11430
11431 if (app.persistent) {
11432 if (app.persistent) {
11433 addAppLocked(app.info);
11434 }
11435 }
11436 }
11437 }
11438
11439 // Now try updating the OOM adjustment for each of the
11440 // application processes based on their current state.
11441 // If the setOomAdj() API is not supported, then go with our
11442 // back-up plan...
11443 if (!updateOomAdjLocked()) {
11444
11445 // Count how many processes are running services.
11446 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011447 for (i=mLruProcesses.size()-1; i>=0; i--) {
11448 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011449
11450 if (app.persistent || app.services.size() != 0
11451 || app.curReceiver != null
11452 || app.persistentActivities > 0) {
11453 // Don't count processes holding services against our
11454 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011455 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 TAG, "Not trimming app " + app + " with services: "
11457 + app.services);
11458 numServiceProcs++;
11459 }
11460 }
11461
11462 int curMaxProcs = mProcessLimit;
11463 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
11464 if (mAlwaysFinishActivities) {
11465 curMaxProcs = 1;
11466 }
11467 curMaxProcs += numServiceProcs;
11468
11469 // Quit as many processes as we can to get down to the desired
11470 // process count. First remove any processes that no longer
11471 // have activites running in them.
11472 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011473 i<mLruProcesses.size()
11474 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011475 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011476 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 // Quit an application only if it is not currently
11478 // running any activities.
11479 if (!app.persistent && app.activities.size() == 0
11480 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011481 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011482 TAG, "Exiting empty application process "
11483 + app.processName + " ("
11484 + (app.thread != null ? app.thread.asBinder() : null)
11485 + ")\n");
11486 if (app.pid > 0 && app.pid != MY_PID) {
11487 Process.killProcess(app.pid);
11488 } else {
11489 try {
11490 app.thread.scheduleExit();
11491 } catch (Exception e) {
11492 // Ignore exceptions.
11493 }
11494 }
11495 // todo: For now we assume the application is not buggy
11496 // or evil, and will quit as a result of our request.
11497 // Eventually we need to drive this off of the death
11498 // notification, and kill the process if it takes too long.
11499 cleanUpApplicationRecordLocked(app, false, i);
11500 i--;
11501 }
11502 }
11503
11504 // If we still have too many processes, now from the least
11505 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011506 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011507 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011508 " of " + curMaxProcs + " processes");
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 the application only if we have a state saved for
11515 // all of its activities.
11516 boolean canQuit = !app.persistent && app.curReceiver == null
11517 && app.services.size() == 0
11518 && app.persistentActivities == 0;
11519 int NUMA = app.activities.size();
11520 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011521 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011522 TAG, "Looking to quit " + app.processName);
11523 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011524 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011525 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 TAG, " " + r.intent.getComponent().flattenToShortString()
11527 + ": frozen=" + r.haveState + ", visible=" + r.visible);
11528 canQuit = (r.haveState || !r.stateNotNeeded)
11529 && !r.visible && r.stopped;
11530 }
11531 if (canQuit) {
11532 // Finish all of the activities, and then the app itself.
11533 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011534 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011535 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011536 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011537 }
11538 r.resultTo = null;
11539 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080011540 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 + app.processName + " ("
11542 + (app.thread != null ? app.thread.asBinder() : null)
11543 + ")\n");
11544 if (app.pid > 0 && app.pid != MY_PID) {
11545 Process.killProcess(app.pid);
11546 } else {
11547 try {
11548 app.thread.scheduleExit();
11549 } catch (Exception e) {
11550 // Ignore exceptions.
11551 }
11552 }
11553 // todo: For now we assume the application is not buggy
11554 // or evil, and will quit as a result of our request.
11555 // Eventually we need to drive this off of the death
11556 // notification, and kill the process if it takes too long.
11557 cleanUpApplicationRecordLocked(app, false, i);
11558 i--;
11559 //dump();
11560 }
11561 }
11562
11563 }
11564
11565 int curMaxActivities = MAX_ACTIVITIES;
11566 if (mAlwaysFinishActivities) {
11567 curMaxActivities = 1;
11568 }
11569
11570 // Finally, if there are too many activities now running, try to
11571 // finish as many as we can to get back down to the limit.
11572 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011573 i<mMainStack.mLRUActivities.size()
11574 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011575 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011576 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011577 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578
11579 // We can finish this one if we have its icicle saved and
11580 // it is not persistent.
11581 if ((r.haveState || !r.stateNotNeeded) && !r.visible
11582 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011583 final int origSize = mMainStack.mLRUActivities.size();
11584 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011585
11586 // This will remove it from the LRU list, so keep
11587 // our index at the same value. Note that this check to
11588 // see if the size changes is just paranoia -- if
11589 // something unexpected happens, we don't want to end up
11590 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011591 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011592 i--;
11593 }
11594 }
11595 }
11596 }
11597 }
11598
11599 /** This method sends the specified signal to each of the persistent apps */
11600 public void signalPersistentProcesses(int sig) throws RemoteException {
11601 if (sig != Process.SIGNAL_USR1) {
11602 throw new SecurityException("Only SIGNAL_USR1 is allowed");
11603 }
11604
11605 synchronized (this) {
11606 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
11607 != PackageManager.PERMISSION_GRANTED) {
11608 throw new SecurityException("Requires permission "
11609 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
11610 }
11611
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011612 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11613 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 if (r.thread != null && r.persistent) {
11615 Process.sendSignal(r.pid, sig);
11616 }
11617 }
11618 }
11619 }
11620
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011621 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011622 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011623
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011624 try {
11625 synchronized (this) {
11626 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
11627 // its own permission.
11628 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
11629 != PackageManager.PERMISSION_GRANTED) {
11630 throw new SecurityException("Requires permission "
11631 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011632 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011633
11634 if (start && fd == null) {
11635 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011636 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011637
11638 ProcessRecord proc = null;
11639 try {
11640 int pid = Integer.parseInt(process);
11641 synchronized (mPidsSelfLocked) {
11642 proc = mPidsSelfLocked.get(pid);
11643 }
11644 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011645 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011646
11647 if (proc == null) {
11648 HashMap<String, SparseArray<ProcessRecord>> all
11649 = mProcessNames.getMap();
11650 SparseArray<ProcessRecord> procs = all.get(process);
11651 if (procs != null && procs.size() > 0) {
11652 proc = procs.valueAt(0);
11653 }
11654 }
11655
11656 if (proc == null || proc.thread == null) {
11657 throw new IllegalArgumentException("Unknown process: " + process);
11658 }
11659
11660 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
11661 if (isSecure) {
11662 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
11663 throw new SecurityException("Process not debuggable: " + proc);
11664 }
11665 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011666
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011667 proc.thread.profilerControl(start, path, fd);
11668 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011669 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070011670 }
11671 } catch (RemoteException e) {
11672 throw new IllegalStateException("Process disappeared");
11673 } finally {
11674 if (fd != null) {
11675 try {
11676 fd.close();
11677 } catch (IOException e) {
11678 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080011679 }
11680 }
11681 }
11682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
11684 public void monitor() {
11685 synchronized (this) { }
11686 }
11687}