blob: 7eb295b7fc3c7f42c7c90d5993c815361101e54a [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
58import android.content.Intent;
59import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070060import android.content.IIntentReceiver;
61import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070062import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.content.pm.ActivityInfo;
64import android.content.pm.ApplicationInfo;
65import android.content.pm.ConfigurationInfo;
66import android.content.pm.IPackageDataObserver;
67import android.content.pm.IPackageManager;
68import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080069import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070071import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.ProviderInfo;
73import android.content.pm.ResolveInfo;
74import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070075import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.res.Configuration;
77import android.graphics.Bitmap;
78import android.net.Uri;
79import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080080import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070082import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.FileUtils;
87import android.os.Handler;
88import android.os.IBinder;
89import android.os.IPermissionController;
90import android.os.Looper;
91import android.os.Message;
92import android.os.Parcel;
93import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070095import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.RemoteException;
97import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070098import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.SystemClock;
100import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.Config;
103import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800104import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800105import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.util.PrintWriterPrinter;
107import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700108import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.view.Gravity;
110import android.view.LayoutInflater;
111import android.view.View;
112import android.view.WindowManager;
113import android.view.WindowManagerPolicy;
114
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700115import java.io.BufferedInputStream;
116import java.io.BufferedOutputStream;
117import java.io.DataInputStream;
118import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119import java.io.File;
120import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700121import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700123import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200124import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800125import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126import java.io.PrintWriter;
127import java.lang.IllegalStateException;
128import java.lang.ref.WeakReference;
129import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700130import java.util.Collections;
131import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132import java.util.HashMap;
133import java.util.HashSet;
134import java.util.Iterator;
135import java.util.List;
136import java.util.Locale;
137import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700138import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700139import java.util.concurrent.atomic.AtomicBoolean;
140import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700142public final class ActivityManagerService extends ActivityManagerNative
143 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 static final String TAG = "ActivityManager";
145 static final boolean DEBUG = false;
146 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
147 static final boolean DEBUG_SWITCH = localLOGV || false;
148 static final boolean DEBUG_TASKS = localLOGV || false;
149 static final boolean DEBUG_PAUSE = localLOGV || false;
150 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
151 static final boolean DEBUG_TRANSITION = localLOGV || false;
152 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700153 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700155 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 static final boolean DEBUG_VISBILITY = localLOGV || false;
157 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700158 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800159 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700161 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700162 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700163 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700164 static final boolean DEBUG_POWER = localLOGV || false;
165 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 static final boolean VALIDATE_TOKENS = false;
167 static final boolean SHOW_ACTIVITY_START_TIME = true;
168
169 // Control over CPU and battery monitoring.
170 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
171 static final boolean MONITOR_CPU_USAGE = true;
172 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
173 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
174 static final boolean MONITOR_THREAD_CPU_USAGE = false;
175
Dianne Hackborn1655be42009-05-08 14:29:01 -0700176 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700177 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 private static final String SYSTEM_SECURE = "ro.secure";
180
181 // This is the maximum number of application processes we would like
182 // to have running. Due to the asynchronous nature of things, we can
183 // temporarily go beyond this limit.
184 static final int MAX_PROCESSES = 2;
185
186 // Set to false to leave processes running indefinitely, relying on
187 // the kernel killing them as resources are required.
188 static final boolean ENFORCE_PROCESS_LIMIT = false;
189
190 // This is the maximum number of activities that we would like to have
191 // running at a given time.
192 static final int MAX_ACTIVITIES = 20;
193
194 // Maximum number of recent tasks that we can remember.
195 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700196
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700197 // Amount of time after a call to stopAppSwitches() during which we will
198 // prevent further untrusted switches from happening.
199 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
201 // How long we wait for a launched process to attach to the activity manager
202 // before we decide it's never going to come up for real.
203 static final int PROC_START_TIMEOUT = 10*1000;
204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 // How long to wait after going idle before forcing apps to GC.
206 static final int GC_TIMEOUT = 5*1000;
207
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700208 // The minimum amount of time between successive GC requests for a process.
209 static final int GC_MIN_INTERVAL = 60*1000;
210
Dianne Hackborn287952c2010-09-22 22:34:31 -0700211 // The rate at which we check for apps using excessive power -- 15 mins.
212 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
213
214 // The minimum sample duration we will allow before deciding we have
215 // enough data on wake locks to start killing things.
216 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
217
218 // The minimum sample duration we will allow before deciding we have
219 // enough data on CPU usage to start killing things.
220 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 // How long we allow a receiver to run before giving up on it.
223 static final int BROADCAST_TIMEOUT = 10*1000;
224
225 // How long we wait for a service to finish executing.
226 static final int SERVICE_TIMEOUT = 20*1000;
227
228 // How long a service needs to be running until restarting its process
229 // is no longer considered to be a relaunch of the service.
230 static final int SERVICE_RESTART_DURATION = 5*1000;
231
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700232 // How long a service needs to be running until it will start back at
233 // SERVICE_RESTART_DURATION after being killed.
234 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
235
236 // Multiplying factor to increase restart duration time by, for each time
237 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
238 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
239
240 // The minimum amount of time between restarting services that we allow.
241 // That is, when multiple services are restarting, we won't allow each
242 // to restart less than this amount of time from the last one.
243 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 // Maximum amount of time for there to be no activity on a service before
246 // we consider it non-essential and allow its process to go on the
247 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700248 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249
250 // How long we wait until we timeout on key dispatching.
251 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
252
253 // The minimum time we allow between crashes, for us to consider this
254 // application to be bad and stop and its services and reject broadcasts.
255 static final int MIN_CRASH_INTERVAL = 60*1000;
256
257 // How long we wait until we timeout on key dispatching during instrumentation.
258 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
259
260 // OOM adjustments for processes in various states:
261
262 // This is a process without anything currently running in it. Definitely
263 // the first to go! Value set in system/rootdir/init.rc on startup.
264 // This value is initalized in the constructor, careful when refering to
265 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800266 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
268 // This is a process only hosting activities that are not visible,
269 // so it can be killed without any disruption. Value set in
270 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800271 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 static int HIDDEN_APP_MIN_ADJ;
273
The Android Open Source Project4df24232009-03-05 14:34:35 -0800274 // This is a process holding the home application -- we want to try
275 // avoiding killing it, even if it would normally be in the background,
276 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800277 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800278
Christopher Tate6fa95972009-06-05 18:43:55 -0700279 // This is a process currently hosting a backup operation. Killing it
280 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800281 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 // This is a process holding a secondary server -- killing it will not
284 // have much of an impact as far as the user is concerned. Value set in
285 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800286 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700288 // This is a process with a heavy-weight application. It is in the
289 // background, but we want to try to avoid killing it. Value set in
290 // system/rootdir/init.rc on startup.
291 static final int HEAVY_WEIGHT_APP_ADJ;
292
293 // This is a process only hosting components that are perceptible to the
294 // user, and we really want to avoid killing them, but they are not
295 // immediately visible. An example is background music playback. Value set in
296 // system/rootdir/init.rc on startup.
297 static final int PERCEPTIBLE_APP_ADJ;
298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 // This is a process only hosting activities that are visible to the
300 // user, so we'd prefer they don't disappear. Value set in
301 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800302 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303
304 // This is the process running the current foreground app. We'd really
305 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307
308 // This is a process running a core server, such as telephony. Definitely
309 // don't want to kill it, but doing so is not completely fatal.
310 static final int CORE_SERVER_ADJ = -12;
311
312 // The system process runs at the default adjustment.
313 static final int SYSTEM_ADJ = -16;
314
315 // Memory pages are 4K.
316 static final int PAGE_SIZE = 4*1024;
317
318 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800319 static final int EMPTY_APP_MEM;
320 static final int HIDDEN_APP_MEM;
321 static final int HOME_APP_MEM;
322 static final int BACKUP_APP_MEM;
323 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700324 static final int HEAVY_WEIGHT_APP_MEM;
325 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800326 static final int VISIBLE_APP_MEM;
327 static final int FOREGROUND_APP_MEM;
328
329 // The minimum number of hidden apps we want to be able to keep around,
330 // without empty apps being able to push them out of memory.
331 static final int MIN_HIDDEN_APPS = 2;
332
Dianne Hackborn8633e682010-04-22 16:03:41 -0700333 // The maximum number of hidden processes we will keep around before
334 // killing them; this is just a control to not let us go too crazy with
335 // keeping around processes on devices with large amounts of RAM.
336 static final int MAX_HIDDEN_APPS = 15;
337
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800338 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700339 // been idle for less than 15 seconds.
340 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800341
342 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700343 // been idle for less than 120 seconds.
344 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800345
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700346 static int getIntProp(String name, boolean allowZero) {
347 String str = SystemProperties.get(name);
348 if (str == null) {
349 throw new IllegalArgumentException("Property not defined: " + name);
350 }
351 int val = Integer.valueOf(str);
352 if (val == 0 && !allowZero) {
353 throw new IllegalArgumentException("Property must not be zero: " + name);
354 }
355 return val;
356 }
357
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800358 static {
359 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700360 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
361 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
362 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
363 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
364 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
365 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
366 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
367 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
368 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
369 // These days we use the last empty slot for hidden apps as well.
370 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
371 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
372 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
373 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
374 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
375 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
376 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
377 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
378 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
379 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381
Dan Egnor42471dd2010-01-07 17:25:22 -0800382 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383
384 static final String[] EMPTY_STRING_ARRAY = new String[0];
385
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700386 public ActivityStack mMainStack;
387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700389 * Description of a request to start a new activity, which has been held
390 * due to app switches being disabled.
391 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700392 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700393 ActivityRecord r;
394 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700395 Uri[] grantedUriPermissions;
396 int grantedMode;
397 boolean onlyIfNeeded;
398 }
399
400 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
401 = new ArrayList<PendingActivityLaunch>();
402
403 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 * List of all active broadcasts that are to be executed immediately
405 * (without waiting for another broadcast to finish). Currently this only
406 * contains broadcasts to registered receivers, to avoid spinning up
407 * a bunch of processes to execute IntentReceiver components.
408 */
409 final ArrayList<BroadcastRecord> mParallelBroadcasts
410 = new ArrayList<BroadcastRecord>();
411
412 /**
413 * List of all active broadcasts that are to be executed one at a time.
414 * The object at the top of the list is the currently activity broadcasts;
415 * those after it are waiting for the top to finish..
416 */
417 final ArrayList<BroadcastRecord> mOrderedBroadcasts
418 = new ArrayList<BroadcastRecord>();
419
420 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800421 * Historical data of past broadcasts, for debugging.
422 */
423 static final int MAX_BROADCAST_HISTORY = 100;
424 final BroadcastRecord[] mBroadcastHistory
425 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
426
427 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 * Set when we current have a BROADCAST_INTENT_MSG in flight.
429 */
430 boolean mBroadcastsScheduled = false;
431
432 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 * Activity we have told the window manager to have key focus.
434 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700435 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * List of intents that were used to start the most recent tasks.
438 */
439 final ArrayList<TaskRecord> mRecentTasks
440 = new ArrayList<TaskRecord>();
441
442 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 * All of the applications we currently have running organized by name.
444 * The keys are strings of the application package name (as
445 * returned by the package manager), and the keys are ApplicationRecord
446 * objects.
447 */
448 final ProcessMap<ProcessRecord> mProcessNames
449 = new ProcessMap<ProcessRecord>();
450
451 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700452 * The currently running heavy-weight process, if any.
453 */
454 ProcessRecord mHeavyWeightProcess = null;
455
456 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 * The last time that various processes have crashed.
458 */
459 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
460
461 /**
462 * Set of applications that we consider to be bad, and will reject
463 * incoming broadcasts from (which the user has no control over).
464 * Processes are added to this set when they have crashed twice within
465 * a minimum amount of time; they are removed from it when they are
466 * later restarted (hopefully due to some user action). The value is the
467 * time it was added to the list.
468 */
469 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
470
471 /**
472 * All of the processes we currently have running organized by pid.
473 * The keys are the pid running the application.
474 *
475 * <p>NOTE: This object is protected by its own lock, NOT the global
476 * activity manager lock!
477 */
478 final SparseArray<ProcessRecord> mPidsSelfLocked
479 = new SparseArray<ProcessRecord>();
480
481 /**
482 * All of the processes that have been forced to be foreground. The key
483 * is the pid of the caller who requested it (we hold a death
484 * link on it).
485 */
486 abstract class ForegroundToken implements IBinder.DeathRecipient {
487 int pid;
488 IBinder token;
489 }
490 final SparseArray<ForegroundToken> mForegroundProcesses
491 = new SparseArray<ForegroundToken>();
492
493 /**
494 * List of records for processes that someone had tried to start before the
495 * system was ready. We don't start them at that point, but ensure they
496 * are started by the time booting is complete.
497 */
498 final ArrayList<ProcessRecord> mProcessesOnHold
499 = new ArrayList<ProcessRecord>();
500
501 /**
502 * List of records for processes that we have started and are waiting
503 * for them to call back. This is really only needed when running in
504 * single processes mode, in which case we do not have a unique pid for
505 * each process.
506 */
507 final ArrayList<ProcessRecord> mStartingProcesses
508 = new ArrayList<ProcessRecord>();
509
510 /**
511 * List of persistent applications that are in the process
512 * of being started.
513 */
514 final ArrayList<ProcessRecord> mPersistentStartingProcesses
515 = new ArrayList<ProcessRecord>();
516
517 /**
518 * Processes that are being forcibly torn down.
519 */
520 final ArrayList<ProcessRecord> mRemovedProcesses
521 = new ArrayList<ProcessRecord>();
522
523 /**
524 * List of running applications, sorted by recent usage.
525 * The first entry in the list is the least recently used.
526 * It contains ApplicationRecord objects. This list does NOT include
527 * any persistent application records (since we never want to exit them).
528 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800529 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 = new ArrayList<ProcessRecord>();
531
532 /**
533 * List of processes that should gc as soon as things are idle.
534 */
535 final ArrayList<ProcessRecord> mProcessesToGc
536 = new ArrayList<ProcessRecord>();
537
538 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800539 * This is the process holding what we currently consider to be
540 * the "home" activity.
541 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700542 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800543
544 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 * Set of PendingResultRecord objects that are currently active.
546 */
547 final HashSet mPendingResultRecords = new HashSet();
548
549 /**
550 * Set of IntentSenderRecord objects that are currently active.
551 */
552 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
553 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
554
555 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700556 * Fingerprints (String.hashCode()) of stack traces that we've
557 * already logged DropBox entries for. Guarded by itself. If
558 * something (rogue user app) forces this over
559 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
560 */
561 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
562 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
563
564 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700565 * Strict Mode background batched logging state.
566 *
567 * The string buffer is guarded by itself, and its lock is also
568 * used to determine if another batched write is already
569 * in-flight.
570 */
571 private final StringBuilder mStrictModeBuffer = new StringBuilder();
572
573 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700574 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
575 */
576 private boolean mPendingBroadcastTimeoutMessage;
577
578 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 * Intent broadcast that we have tried to start, but are
580 * waiting for its application's process to be created. We only
581 * need one (instead of a list) because we always process broadcasts
582 * one at a time, so no others can be started while waiting for this
583 * one.
584 */
585 BroadcastRecord mPendingBroadcast = null;
586
587 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700588 * The receiver index that is pending, to restart the broadcast if needed.
589 */
590 int mPendingBroadcastRecvIndex;
591
592 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 * Keeps track of all IIntentReceivers that have been registered for
594 * broadcasts. Hash keys are the receiver IBinder, hash value is
595 * a ReceiverList.
596 */
597 final HashMap mRegisteredReceivers = new HashMap();
598
599 /**
600 * Resolver for broadcast intents to registered receivers.
601 * Holds BroadcastFilter (subclass of IntentFilter).
602 */
603 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
604 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
605 @Override
606 protected boolean allowFilterResult(
607 BroadcastFilter filter, List<BroadcastFilter> dest) {
608 IBinder target = filter.receiverList.receiver.asBinder();
609 for (int i=dest.size()-1; i>=0; i--) {
610 if (dest.get(i).receiverList.receiver.asBinder() == target) {
611 return false;
612 }
613 }
614 return true;
615 }
616 };
617
618 /**
619 * State of all active sticky broadcasts. Keys are the action of the
620 * sticky Intent, values are an ArrayList of all broadcasted intents with
621 * that action (which should usually be one).
622 */
623 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
624 new HashMap<String, ArrayList<Intent>>();
625
626 /**
627 * All currently running services.
628 */
629 final HashMap<ComponentName, ServiceRecord> mServices =
630 new HashMap<ComponentName, ServiceRecord>();
631
632 /**
633 * All currently running services indexed by the Intent used to start them.
634 */
635 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
636 new HashMap<Intent.FilterComparison, ServiceRecord>();
637
638 /**
639 * All currently bound service connections. Keys are the IBinder of
640 * the client's IServiceConnection.
641 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700642 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
643 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644
645 /**
646 * List of services that we have been asked to start,
647 * but haven't yet been able to. It is used to hold start requests
648 * while waiting for their corresponding application thread to get
649 * going.
650 */
651 final ArrayList<ServiceRecord> mPendingServices
652 = new ArrayList<ServiceRecord>();
653
654 /**
655 * List of services that are scheduled to restart following a crash.
656 */
657 final ArrayList<ServiceRecord> mRestartingServices
658 = new ArrayList<ServiceRecord>();
659
660 /**
661 * List of services that are in the process of being stopped.
662 */
663 final ArrayList<ServiceRecord> mStoppingServices
664 = new ArrayList<ServiceRecord>();
665
666 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700667 * Backup/restore process management
668 */
669 String mBackupAppName = null;
670 BackupRecord mBackupTarget = null;
671
672 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 * List of PendingThumbnailsRecord objects of clients who are still
674 * waiting to receive all of the thumbnails for a task.
675 */
676 final ArrayList mPendingThumbnails = new ArrayList();
677
678 /**
679 * List of HistoryRecord objects that have been finished and must
680 * still report back to a pending thumbnail receiver.
681 */
682 final ArrayList mCancelledThumbnails = new ArrayList();
683
684 /**
685 * All of the currently running global content providers. Keys are a
686 * string containing the provider name and values are a
687 * ContentProviderRecord object containing the data about it. Note
688 * that a single provider may be published under multiple names, so
689 * there may be multiple entries here for a single one in mProvidersByClass.
690 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700691 final HashMap<String, ContentProviderRecord> mProvidersByName
692 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693
694 /**
695 * All of the currently running global content providers. Keys are a
696 * string containing the provider's implementation class and values are a
697 * ContentProviderRecord object containing the data about it.
698 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700699 final HashMap<String, ContentProviderRecord> mProvidersByClass
700 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701
702 /**
703 * List of content providers who have clients waiting for them. The
704 * application is currently being launched and the provider will be
705 * removed from this list once it is published.
706 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700707 final ArrayList<ContentProviderRecord> mLaunchingProviders
708 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709
710 /**
711 * Global set of specific Uri permissions that have been granted.
712 */
713 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
714 = new SparseArray<HashMap<Uri, UriPermission>>();
715
716 /**
717 * Thread-local storage used to carry caller permissions over through
718 * indirect content-provider access.
719 * @see #ActivityManagerService.openContentUri()
720 */
721 private class Identity {
722 public int pid;
723 public int uid;
724
725 Identity(int _pid, int _uid) {
726 pid = _pid;
727 uid = _uid;
728 }
729 }
730 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
731
732 /**
733 * All information we have collected about the runtime performance of
734 * any user id that can impact battery performance.
735 */
736 final BatteryStatsService mBatteryStatsService;
737
738 /**
739 * information about component usage
740 */
741 final UsageStatsService mUsageStatsService;
742
743 /**
744 * Current configuration information. HistoryRecord objects are given
745 * a reference to this object to indicate which configuration they are
746 * currently running in, so this object must be kept immutable.
747 */
748 Configuration mConfiguration = new Configuration();
749
750 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800751 * Current sequencing integer of the configuration, for skipping old
752 * configurations.
753 */
754 int mConfigurationSeq = 0;
755
756 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700757 * Hardware-reported OpenGLES version.
758 */
759 final int GL_ES_VERSION;
760
761 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 * List of initialization arguments to pass to all processes when binding applications to them.
763 * For example, references to the commonly used services.
764 */
765 HashMap<String, IBinder> mAppBindArgs;
766
767 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700768 * Temporary to avoid allocations. Protected by main lock.
769 */
770 final StringBuilder mStringBuilder = new StringBuilder(256);
771
772 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 * Used to control how we initialize the service.
774 */
775 boolean mStartRunning = false;
776 ComponentName mTopComponent;
777 String mTopAction;
778 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700779 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 boolean mSystemReady = false;
781 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700782 boolean mWaitingUpdate = false;
783 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700784 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700785 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786
787 Context mContext;
788
789 int mFactoryTest;
790
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700791 boolean mCheckedForSetup;
792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700794 * The time at which we will allow normal application switches again,
795 * after a call to {@link #stopAppSwitches()}.
796 */
797 long mAppSwitchesAllowedTime;
798
799 /**
800 * This is set to true after the first switch after mAppSwitchesAllowedTime
801 * is set; any switches after that will clear the time.
802 */
803 boolean mDidAppSwitch;
804
805 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700806 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700807 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700808 long mLastPowerCheckRealtime;
809
810 /**
811 * Last time (in uptime) at which we checked for power usage.
812 */
813 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700814
815 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 * Set while we are wanting to sleep, to prevent any
817 * activities from being started/resumed.
818 */
819 boolean mSleeping = false;
820
821 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700822 * Set if we are shutting down the system, similar to sleeping.
823 */
824 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825
826 /**
827 * Task identifier that activities are currently being started
828 * in. Incremented each time a new task is created.
829 * todo: Replace this with a TokenSpace class that generates non-repeating
830 * integers that won't wrap.
831 */
832 int mCurTask = 1;
833
834 /**
835 * Current sequence id for oom_adj computation traversal.
836 */
837 int mAdjSeq = 0;
838
839 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700840 * Current sequence id for process LRU updating.
841 */
842 int mLruSeq = 0;
843
844 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
846 * is set, indicating the user wants processes started in such a way
847 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
848 * running in each process (thus no pre-initialized process, etc).
849 */
850 boolean mSimpleProcessManagement = false;
851
852 /**
853 * System monitoring: number of processes that died since the last
854 * N procs were started.
855 */
856 int[] mProcDeaths = new int[20];
857
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700858 /**
859 * This is set if we had to do a delayed dexopt of an app before launching
860 * it, to increasing the ANR timeouts in that case.
861 */
862 boolean mDidDexOpt;
863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 String mDebugApp = null;
865 boolean mWaitForDebugger = false;
866 boolean mDebugTransient = false;
867 String mOrigDebugApp = null;
868 boolean mOrigWaitForDebugger = false;
869 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700870 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700872 final RemoteCallbackList<IActivityWatcher> mWatchers
873 = new RemoteCallbackList<IActivityWatcher>();
874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 /**
876 * Callback of last caller to {@link #requestPss}.
877 */
878 Runnable mRequestPssCallback;
879
880 /**
881 * Remaining processes for which we are waiting results from the last
882 * call to {@link #requestPss}.
883 */
884 final ArrayList<ProcessRecord> mRequestPssList
885 = new ArrayList<ProcessRecord>();
886
887 /**
888 * Runtime statistics collection thread. This object's lock is used to
889 * protect all related state.
890 */
891 final Thread mProcessStatsThread;
892
893 /**
894 * Used to collect process stats when showing not responding dialog.
895 * Protected by mProcessStatsThread.
896 */
897 final ProcessStats mProcessStats = new ProcessStats(
898 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700899 final AtomicLong mLastCpuTime = new AtomicLong(0);
900 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 long mLastWriteTime = 0;
903
904 /**
905 * Set to true after the system has finished booting.
906 */
907 boolean mBooted = false;
908
909 int mProcessLimit = 0;
910
911 WindowManagerService mWindowManager;
912
913 static ActivityManagerService mSelf;
914 static ActivityThread mSystemThread;
915
916 private final class AppDeathRecipient implements IBinder.DeathRecipient {
917 final ProcessRecord mApp;
918 final int mPid;
919 final IApplicationThread mAppThread;
920
921 AppDeathRecipient(ProcessRecord app, int pid,
922 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800923 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 TAG, "New death recipient " + this
925 + " for thread " + thread.asBinder());
926 mApp = app;
927 mPid = pid;
928 mAppThread = thread;
929 }
930
931 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800932 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 TAG, "Death received in " + this
934 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 synchronized(ActivityManagerService.this) {
936 appDiedLocked(mApp, mPid, mAppThread);
937 }
938 }
939 }
940
941 static final int SHOW_ERROR_MSG = 1;
942 static final int SHOW_NOT_RESPONDING_MSG = 2;
943 static final int SHOW_FACTORY_ERROR_MSG = 3;
944 static final int UPDATE_CONFIGURATION_MSG = 4;
945 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
946 static final int WAIT_FOR_DEBUGGER_MSG = 6;
947 static final int BROADCAST_INTENT_MSG = 7;
948 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 static final int SERVICE_TIMEOUT_MSG = 12;
950 static final int UPDATE_TIME_ZONE = 13;
951 static final int SHOW_UID_ERROR_MSG = 14;
952 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700954 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700955 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800956 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700957 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
958 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700959 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700960 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961
962 AlertDialog mUidAlert;
963
964 final Handler mHandler = new Handler() {
965 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800966 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 //}
968
969 public void handleMessage(Message msg) {
970 switch (msg.what) {
971 case SHOW_ERROR_MSG: {
972 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 synchronized (ActivityManagerService.this) {
974 ProcessRecord proc = (ProcessRecord)data.get("app");
975 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800976 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 return;
978 }
979 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700980 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800981 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 d.show();
983 proc.crashDialog = d;
984 } else {
985 // The device is asleep, so just pretend that the user
986 // saw a crash dialog and hit "force quit".
987 res.set(0);
988 }
989 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700990
991 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 } break;
993 case SHOW_NOT_RESPONDING_MSG: {
994 synchronized (ActivityManagerService.this) {
995 HashMap data = (HashMap) msg.obj;
996 ProcessRecord proc = (ProcessRecord)data.get("app");
997 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800998 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 return;
1000 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001001
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001002 Intent intent = new Intent("android.intent.action.ANR");
1003 if (!mProcessesReady) {
1004 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1005 }
1006 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001007 null, null, 0, null, null, null,
1008 false, false, MY_PID, Process.SYSTEM_UID);
1009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001011 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 d.show();
1013 proc.anrDialog = d;
1014 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001015
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001016 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001018 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1019 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1020 synchronized (ActivityManagerService.this) {
1021 ProcessRecord proc = (ProcessRecord) data.get("app");
1022 if (proc == null) {
1023 Slog.e(TAG, "App not found when showing strict mode dialog.");
1024 break;
1025 }
1026 if (proc.crashDialog != null) {
1027 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1028 return;
1029 }
1030 AppErrorResult res = (AppErrorResult) data.get("result");
1031 if (!mSleeping && !mShuttingDown) {
1032 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1033 d.show();
1034 proc.crashDialog = d;
1035 } else {
1036 // The device is asleep, so just pretend that the user
1037 // saw a crash dialog and hit "force quit".
1038 res.set(0);
1039 }
1040 }
1041 ensureBootCompleted();
1042 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 case SHOW_FACTORY_ERROR_MSG: {
1044 Dialog d = new FactoryErrorDialog(
1045 mContext, msg.getData().getCharSequence("msg"));
1046 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001047 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 } break;
1049 case UPDATE_CONFIGURATION_MSG: {
1050 final ContentResolver resolver = mContext.getContentResolver();
1051 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1052 } break;
1053 case GC_BACKGROUND_PROCESSES_MSG: {
1054 synchronized (ActivityManagerService.this) {
1055 performAppGcsIfAppropriateLocked();
1056 }
1057 } break;
1058 case WAIT_FOR_DEBUGGER_MSG: {
1059 synchronized (ActivityManagerService.this) {
1060 ProcessRecord app = (ProcessRecord)msg.obj;
1061 if (msg.arg1 != 0) {
1062 if (!app.waitedForDebugger) {
1063 Dialog d = new AppWaitingForDebuggerDialog(
1064 ActivityManagerService.this,
1065 mContext, app);
1066 app.waitDialog = d;
1067 app.waitedForDebugger = true;
1068 d.show();
1069 }
1070 } else {
1071 if (app.waitDialog != null) {
1072 app.waitDialog.dismiss();
1073 app.waitDialog = null;
1074 }
1075 }
1076 }
1077 } break;
1078 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001079 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 TAG, "Received BROADCAST_INTENT_MSG");
1081 processNextBroadcast(true);
1082 } break;
1083 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001084 synchronized (ActivityManagerService.this) {
1085 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001089 if (mDidDexOpt) {
1090 mDidDexOpt = false;
1091 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1092 nmsg.obj = msg.obj;
1093 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1094 return;
1095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 serviceTimeout((ProcessRecord)msg.obj);
1097 } break;
1098 case UPDATE_TIME_ZONE: {
1099 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001100 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1101 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 if (r.thread != null) {
1103 try {
1104 r.thread.updateTimeZone();
1105 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001106 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 }
1108 }
1109 }
1110 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001111 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 case SHOW_UID_ERROR_MSG: {
1113 // XXX This is a temporary dialog, no need to localize.
1114 AlertDialog d = new BaseErrorDialog(mContext);
1115 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1116 d.setCancelable(false);
1117 d.setTitle("System UIDs Inconsistent");
1118 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1119 d.setButton("I'm Feeling Lucky",
1120 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1121 mUidAlert = d;
1122 d.show();
1123 } break;
1124 case IM_FEELING_LUCKY_MSG: {
1125 if (mUidAlert != null) {
1126 mUidAlert.dismiss();
1127 mUidAlert = null;
1128 }
1129 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001131 if (mDidDexOpt) {
1132 mDidDexOpt = false;
1133 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1134 nmsg.obj = msg.obj;
1135 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1136 return;
1137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 ProcessRecord app = (ProcessRecord)msg.obj;
1139 synchronized (ActivityManagerService.this) {
1140 processStartTimedOutLocked(app);
1141 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001142 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001143 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1144 synchronized (ActivityManagerService.this) {
1145 doPendingActivityLaunchesLocked(true);
1146 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001147 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001148 case KILL_APPLICATION_MSG: {
1149 synchronized (ActivityManagerService.this) {
1150 int uid = msg.arg1;
1151 boolean restart = (msg.arg2 == 1);
1152 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001153 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001154 }
1155 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001156 case FINALIZE_PENDING_INTENT_MSG: {
1157 ((PendingIntentRecord)msg.obj).completeFinalize();
1158 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001159 case POST_HEAVY_NOTIFICATION_MSG: {
1160 INotificationManager inm = NotificationManager.getService();
1161 if (inm == null) {
1162 return;
1163 }
1164
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001165 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001166 ProcessRecord process = root.app;
1167 if (process == null) {
1168 return;
1169 }
1170
1171 try {
1172 Context context = mContext.createPackageContext(process.info.packageName, 0);
1173 String text = mContext.getString(R.string.heavy_weight_notification,
1174 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1175 Notification notification = new Notification();
1176 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1177 notification.when = 0;
1178 notification.flags = Notification.FLAG_ONGOING_EVENT;
1179 notification.tickerText = text;
1180 notification.defaults = 0; // please be quiet
1181 notification.sound = null;
1182 notification.vibrate = null;
1183 notification.setLatestEventInfo(context, text,
1184 mContext.getText(R.string.heavy_weight_notification_detail),
1185 PendingIntent.getActivity(mContext, 0, root.intent,
1186 PendingIntent.FLAG_CANCEL_CURRENT));
1187
1188 try {
1189 int[] outId = new int[1];
1190 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1191 notification, outId);
1192 } catch (RuntimeException e) {
1193 Slog.w(ActivityManagerService.TAG,
1194 "Error showing notification for heavy-weight app", e);
1195 } catch (RemoteException e) {
1196 }
1197 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001198 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001199 }
1200 } break;
1201 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1202 INotificationManager inm = NotificationManager.getService();
1203 if (inm == null) {
1204 return;
1205 }
1206 try {
1207 inm.cancelNotification("android",
1208 R.string.heavy_weight_notification);
1209 } catch (RuntimeException e) {
1210 Slog.w(ActivityManagerService.TAG,
1211 "Error canceling notification for service", e);
1212 } catch (RemoteException e) {
1213 }
1214 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001215 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1216 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001217 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001218 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001219 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1220 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001221 }
1222 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 }
1224 }
1225 };
1226
1227 public static void setSystemProcess() {
1228 try {
1229 ActivityManagerService m = mSelf;
1230
1231 ServiceManager.addService("activity", m);
1232 ServiceManager.addService("meminfo", new MemBinder(m));
1233 if (MONITOR_CPU_USAGE) {
1234 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 ServiceManager.addService("permission", new PermissionController(m));
1237
1238 ApplicationInfo info =
1239 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001240 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001241 mSystemThread.installSystemApplicationInfo(info);
1242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 synchronized (mSelf) {
1244 ProcessRecord app = mSelf.newProcessRecordLocked(
1245 mSystemThread.getApplicationThread(), info,
1246 info.processName);
1247 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001248 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 app.maxAdj = SYSTEM_ADJ;
1250 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1251 synchronized (mSelf.mPidsSelfLocked) {
1252 mSelf.mPidsSelfLocked.put(app.pid, app);
1253 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001254 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 }
1256 } catch (PackageManager.NameNotFoundException e) {
1257 throw new RuntimeException(
1258 "Unable to find android system package", e);
1259 }
1260 }
1261
1262 public void setWindowManager(WindowManagerService wm) {
1263 mWindowManager = wm;
1264 }
1265
1266 public static final Context main(int factoryTest) {
1267 AThread thr = new AThread();
1268 thr.start();
1269
1270 synchronized (thr) {
1271 while (thr.mService == null) {
1272 try {
1273 thr.wait();
1274 } catch (InterruptedException e) {
1275 }
1276 }
1277 }
1278
1279 ActivityManagerService m = thr.mService;
1280 mSelf = m;
1281 ActivityThread at = ActivityThread.systemMain();
1282 mSystemThread = at;
1283 Context context = at.getSystemContext();
1284 m.mContext = context;
1285 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001286 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287
1288 m.mBatteryStatsService.publish(context);
1289 m.mUsageStatsService.publish(context);
1290
1291 synchronized (thr) {
1292 thr.mReady = true;
1293 thr.notifyAll();
1294 }
1295
1296 m.startRunning(null, null, null, null);
1297
1298 return context;
1299 }
1300
1301 public static ActivityManagerService self() {
1302 return mSelf;
1303 }
1304
1305 static class AThread extends Thread {
1306 ActivityManagerService mService;
1307 boolean mReady = false;
1308
1309 public AThread() {
1310 super("ActivityManager");
1311 }
1312
1313 public void run() {
1314 Looper.prepare();
1315
1316 android.os.Process.setThreadPriority(
1317 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001318 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319
1320 ActivityManagerService m = new ActivityManagerService();
1321
1322 synchronized (this) {
1323 mService = m;
1324 notifyAll();
1325 }
1326
1327 synchronized (this) {
1328 while (!mReady) {
1329 try {
1330 wait();
1331 } catch (InterruptedException e) {
1332 }
1333 }
1334 }
1335
1336 Looper.loop();
1337 }
1338 }
1339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 static class MemBinder extends Binder {
1341 ActivityManagerService mActivityManagerService;
1342 MemBinder(ActivityManagerService activityManagerService) {
1343 mActivityManagerService = activityManagerService;
1344 }
1345
1346 @Override
1347 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1348 ActivityManagerService service = mActivityManagerService;
1349 ArrayList<ProcessRecord> procs;
1350 synchronized (mActivityManagerService) {
1351 if (args != null && args.length > 0
1352 && args[0].charAt(0) != '-') {
1353 procs = new ArrayList<ProcessRecord>();
1354 int pid = -1;
1355 try {
1356 pid = Integer.parseInt(args[0]);
1357 } catch (NumberFormatException e) {
1358
1359 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001360 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1361 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 if (proc.pid == pid) {
1363 procs.add(proc);
1364 } else if (proc.processName.equals(args[0])) {
1365 procs.add(proc);
1366 }
1367 }
1368 if (procs.size() <= 0) {
1369 pw.println("No process found for: " + args[0]);
1370 return;
1371 }
1372 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001373 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 }
1375 }
1376 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1377 }
1378 }
1379
1380 static class CpuBinder extends Binder {
1381 ActivityManagerService mActivityManagerService;
1382 CpuBinder(ActivityManagerService activityManagerService) {
1383 mActivityManagerService = activityManagerService;
1384 }
1385
1386 @Override
1387 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1388 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001389 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1390 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1391 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 }
1393 }
1394 }
1395
1396 private ActivityManagerService() {
1397 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1398 if (v != null && Integer.getInteger(v) != 0) {
1399 mSimpleProcessManagement = true;
1400 }
1401 v = System.getenv("ANDROID_DEBUG_APP");
1402 if (v != null) {
1403 mSimpleProcessManagement = true;
1404 }
1405
Joe Onorato8a9b2202010-02-26 18:56:32 -08001406 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 File dataDir = Environment.getDataDirectory();
1409 File systemDir = new File(dataDir, "system");
1410 systemDir.mkdirs();
1411 mBatteryStatsService = new BatteryStatsService(new File(
1412 systemDir, "batterystats.bin").toString());
1413 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001414 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001415 mOnBattery = DEBUG_POWER ? true
1416 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001417 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001419 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001420 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421
Jack Palevichb90d28c2009-07-22 15:35:24 -07001422 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1423 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1424
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001425 mConfiguration.setToDefaults();
1426 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 mProcessStats.init();
1428
1429 // Add ourself to the Watchdog monitors.
1430 Watchdog.getInstance().addMonitor(this);
1431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 mProcessStatsThread = new Thread("ProcessStats") {
1433 public void run() {
1434 while (true) {
1435 try {
1436 try {
1437 synchronized(this) {
1438 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001439 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001441 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 // + ", write delay=" + nextWriteDelay);
1443 if (nextWriteDelay < nextCpuDelay) {
1444 nextCpuDelay = nextWriteDelay;
1445 }
1446 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001447 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 this.wait(nextCpuDelay);
1449 }
1450 }
1451 } catch (InterruptedException e) {
1452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 updateCpuStatsNow();
1454 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001455 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 }
1457 }
1458 }
1459 };
1460 mProcessStatsThread.start();
1461 }
1462
1463 @Override
1464 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1465 throws RemoteException {
1466 try {
1467 return super.onTransact(code, data, reply, flags);
1468 } catch (RuntimeException e) {
1469 // The activity manager only throws security exceptions, so let's
1470 // log all others.
1471 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001472 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 }
1474 throw e;
1475 }
1476 }
1477
1478 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001479 final long now = SystemClock.uptimeMillis();
1480 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1481 return;
1482 }
1483 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1484 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 mProcessStatsThread.notify();
1486 }
1487 }
1488 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 void updateCpuStatsNow() {
1491 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001492 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 final long now = SystemClock.uptimeMillis();
1494 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001497 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1498 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 haveNewCpuStats = true;
1500 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001501 //Slog.i(TAG, mProcessStats.printCurrentState());
1502 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 // + mProcessStats.getTotalCpuPercent() + "%");
1504
Joe Onorato8a9b2202010-02-26 18:56:32 -08001505 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 if ("true".equals(SystemProperties.get("events.cpu"))) {
1507 int user = mProcessStats.getLastUserTime();
1508 int system = mProcessStats.getLastSystemTime();
1509 int iowait = mProcessStats.getLastIoWaitTime();
1510 int irq = mProcessStats.getLastIrqTime();
1511 int softIrq = mProcessStats.getLastSoftIrqTime();
1512 int idle = mProcessStats.getLastIdleTime();
1513
1514 int total = user + system + iowait + irq + softIrq + idle;
1515 if (total == 0) total = 1;
1516
Doug Zongker2bec3d42009-12-04 12:52:44 -08001517 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 ((user+system+iowait+irq+softIrq) * 100) / total,
1519 (user * 100) / total,
1520 (system * 100) / total,
1521 (iowait * 100) / total,
1522 (irq * 100) / total,
1523 (softIrq * 100) / total);
1524 }
1525 }
1526
Amith Yamasanie43530a2009-08-21 13:11:37 -07001527 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001528 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001529 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 synchronized(mPidsSelfLocked) {
1531 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001532 if (mOnBattery) {
1533 int perc = bstats.startAddingCpuLocked();
1534 int totalUTime = 0;
1535 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001536 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001538 ProcessStats.Stats st = mProcessStats.getStats(i);
1539 if (!st.working) {
1540 continue;
1541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001543 int otherUTime = (st.rel_utime*perc)/100;
1544 int otherSTime = (st.rel_stime*perc)/100;
1545 totalUTime += otherUTime;
1546 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 if (pr != null) {
1548 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001549 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1550 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001551 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001552 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001553 } else {
1554 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001555 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001556 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001557 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1558 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001559 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 }
1562 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001563 bstats.finishAddingCpuLocked(perc, totalUTime,
1564 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 }
1566 }
1567 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1570 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001571 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 }
1573 }
1574 }
1575 }
1576
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001577 @Override
1578 public void batteryNeedsCpuUpdate() {
1579 updateCpuStatsNow();
1580 }
1581
1582 @Override
1583 public void batteryPowerChanged(boolean onBattery) {
1584 // When plugging in, update the CPU stats first before changing
1585 // the plug state.
1586 updateCpuStatsNow();
1587 synchronized (this) {
1588 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001589 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001590 }
1591 }
1592 }
1593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 /**
1595 * Initialize the application bind args. These are passed to each
1596 * process when the bindApplication() IPC is sent to the process. They're
1597 * lazily setup to make sure the services are running when they're asked for.
1598 */
1599 private HashMap<String, IBinder> getCommonServicesLocked() {
1600 if (mAppBindArgs == null) {
1601 mAppBindArgs = new HashMap<String, IBinder>();
1602
1603 // Setup the application init args
1604 mAppBindArgs.put("package", ServiceManager.getService("package"));
1605 mAppBindArgs.put("window", ServiceManager.getService("window"));
1606 mAppBindArgs.put(Context.ALARM_SERVICE,
1607 ServiceManager.getService(Context.ALARM_SERVICE));
1608 }
1609 return mAppBindArgs;
1610 }
1611
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001612 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 if (mFocusedActivity != r) {
1614 mFocusedActivity = r;
1615 mWindowManager.setFocusedApp(r, true);
1616 }
1617 }
1618
Dianne Hackborn906497c2010-05-10 15:57:38 -07001619 private final void updateLruProcessInternalLocked(ProcessRecord app,
1620 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001622 int lrui = mLruProcesses.indexOf(app);
1623 if (lrui >= 0) mLruProcesses.remove(lrui);
1624
1625 int i = mLruProcesses.size()-1;
1626 int skipTop = 0;
1627
Dianne Hackborn906497c2010-05-10 15:57:38 -07001628 app.lruSeq = mLruSeq;
1629
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001630 // compute the new weight for this process.
1631 if (updateActivityTime) {
1632 app.lastActivityTime = SystemClock.uptimeMillis();
1633 }
1634 if (app.activities.size() > 0) {
1635 // If this process has activities, we more strongly want to keep
1636 // it around.
1637 app.lruWeight = app.lastActivityTime;
1638 } else if (app.pubProviders.size() > 0) {
1639 // If this process contains content providers, we want to keep
1640 // it a little more strongly.
1641 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1642 // Also don't let it kick out the first few "real" hidden processes.
1643 skipTop = MIN_HIDDEN_APPS;
1644 } else {
1645 // If this process doesn't have activities, we less strongly
1646 // want to keep it around, and generally want to avoid getting
1647 // in front of any very recently used activities.
1648 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1649 // Also don't let it kick out the first few "real" hidden processes.
1650 skipTop = MIN_HIDDEN_APPS;
1651 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001652
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001653 while (i >= 0) {
1654 ProcessRecord p = mLruProcesses.get(i);
1655 // If this app shouldn't be in front of the first N background
1656 // apps, then skip over that many that are currently hidden.
1657 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1658 skipTop--;
1659 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001660 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001661 mLruProcesses.add(i+1, app);
1662 break;
1663 }
1664 i--;
1665 }
1666 if (i < 0) {
1667 mLruProcesses.add(0, app);
1668 }
1669
Dianne Hackborn906497c2010-05-10 15:57:38 -07001670 // If the app is currently using a content provider or service,
1671 // bump those processes as well.
1672 if (app.connections.size() > 0) {
1673 for (ConnectionRecord cr : app.connections) {
1674 if (cr.binding != null && cr.binding.service != null
1675 && cr.binding.service.app != null
1676 && cr.binding.service.app.lruSeq != mLruSeq) {
1677 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1678 updateActivityTime, i+1);
1679 }
1680 }
1681 }
1682 if (app.conProviders.size() > 0) {
1683 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1684 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1685 updateLruProcessInternalLocked(cpr.app, oomAdj,
1686 updateActivityTime, i+1);
1687 }
1688 }
1689 }
1690
Joe Onorato8a9b2202010-02-26 18:56:32 -08001691 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 if (oomAdj) {
1693 updateOomAdjLocked();
1694 }
1695 }
1696
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001697 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001698 boolean oomAdj, boolean updateActivityTime) {
1699 mLruSeq++;
1700 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1701 }
1702
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001703 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 String processName, int uid) {
1705 if (uid == Process.SYSTEM_UID) {
1706 // The system gets to run in any process. If there are multiple
1707 // processes with the same uid, just pick the first (this
1708 // should never happen).
1709 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1710 processName);
1711 return procs != null ? procs.valueAt(0) : null;
1712 }
1713 ProcessRecord proc = mProcessNames.get(processName, uid);
1714 return proc;
1715 }
1716
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001717 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001718 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001719 try {
1720 if (pm.performDexOpt(packageName)) {
1721 mDidDexOpt = true;
1722 }
1723 } catch (RemoteException e) {
1724 }
1725 }
1726
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001727 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 int transit = mWindowManager.getPendingAppTransition();
1729 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1730 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1731 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1732 }
1733
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001734 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001736 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1738 // We don't have to do anything more if:
1739 // (1) There is an existing application record; and
1740 // (2) The caller doesn't think it is dead, OR there is no thread
1741 // object attached to it so we know it couldn't have crashed; and
1742 // (3) There is a pid assigned to it, so it is either starting or
1743 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001744 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 + " app=" + app + " knownToBeDead=" + knownToBeDead
1746 + " thread=" + (app != null ? app.thread : null)
1747 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001748 if (app != null && app.pid > 0) {
1749 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001750 // We already have the app running, or are waiting for it to
1751 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001752 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001753 return app;
1754 } else {
1755 // An application record is attached to a previous process,
1756 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001757 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001758 handleAppDiedLocked(app, true);
1759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 String hostingNameStr = hostingName != null
1763 ? hostingName.flattenToShortString() : null;
1764
1765 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1766 // If we are in the background, then check to see if this process
1767 // is bad. If so, we will just silently fail.
1768 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001769 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1770 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 return null;
1772 }
1773 } else {
1774 // When the user is explicitly starting a process, then clear its
1775 // crash count so that we won't make it bad until they see at
1776 // least one crash dialog again, and make the process good again
1777 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001778 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1779 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 mProcessCrashTimes.remove(info.processName, info.uid);
1781 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001782 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 info.processName);
1784 mBadProcesses.remove(info.processName, info.uid);
1785 if (app != null) {
1786 app.bad = false;
1787 }
1788 }
1789 }
1790
1791 if (app == null) {
1792 app = newProcessRecordLocked(null, info, processName);
1793 mProcessNames.put(processName, info.uid, app);
1794 } else {
1795 // If this is a new package in the process, add the package to the list
1796 app.addPackage(info.packageName);
1797 }
1798
1799 // If the system is not ready yet, then hold off on starting this
1800 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001801 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001802 && !isAllowedWhileBooting(info)
1803 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 if (!mProcessesOnHold.contains(app)) {
1805 mProcessesOnHold.add(app);
1806 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001807 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 return app;
1809 }
1810
1811 startProcessLocked(app, hostingType, hostingNameStr);
1812 return (app.pid != 0) ? app : null;
1813 }
1814
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001815 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1816 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1817 }
1818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 private final void startProcessLocked(ProcessRecord app,
1820 String hostingType, String hostingNameStr) {
1821 if (app.pid > 0 && app.pid != MY_PID) {
1822 synchronized (mPidsSelfLocked) {
1823 mPidsSelfLocked.remove(app.pid);
1824 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1825 }
1826 app.pid = 0;
1827 }
1828
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001829 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1830 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 mProcessesOnHold.remove(app);
1832
1833 updateCpuStats();
1834
1835 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1836 mProcDeaths[0] = 0;
1837
1838 try {
1839 int uid = app.info.uid;
1840 int[] gids = null;
1841 try {
1842 gids = mContext.getPackageManager().getPackageGids(
1843 app.info.packageName);
1844 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001845 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 }
1847 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1848 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1849 && mTopComponent != null
1850 && app.processName.equals(mTopComponent.getPackageName())) {
1851 uid = 0;
1852 }
1853 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1854 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1855 uid = 0;
1856 }
1857 }
1858 int debugFlags = 0;
1859 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1860 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1861 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001862 // Run the app in safe mode if its manifest requests so or the
1863 // system is booted in safe mode.
1864 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1865 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001866 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1869 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1870 }
1871 if ("1".equals(SystemProperties.get("debug.assert"))) {
1872 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1873 }
1874 int pid = Process.start("android.app.ActivityThread",
1875 mSimpleProcessManagement ? app.processName : null, uid, uid,
1876 gids, debugFlags, null);
1877 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1878 synchronized (bs) {
1879 if (bs.isOnBattery()) {
1880 app.batteryStats.incStartsLocked();
1881 }
1882 }
1883
Doug Zongker2bec3d42009-12-04 12:52:44 -08001884 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 app.processName, hostingType,
1886 hostingNameStr != null ? hostingNameStr : "");
1887
1888 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001889 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 }
1891
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001892 StringBuilder buf = mStringBuilder;
1893 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 buf.append("Start proc ");
1895 buf.append(app.processName);
1896 buf.append(" for ");
1897 buf.append(hostingType);
1898 if (hostingNameStr != null) {
1899 buf.append(" ");
1900 buf.append(hostingNameStr);
1901 }
1902 buf.append(": pid=");
1903 buf.append(pid);
1904 buf.append(" uid=");
1905 buf.append(uid);
1906 buf.append(" gids={");
1907 if (gids != null) {
1908 for (int gi=0; gi<gids.length; gi++) {
1909 if (gi != 0) buf.append(", ");
1910 buf.append(gids[gi]);
1911
1912 }
1913 }
1914 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001915 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 if (pid == 0 || pid == MY_PID) {
1917 // Processes are being emulated with threads.
1918 app.pid = MY_PID;
1919 app.removed = false;
1920 mStartingProcesses.add(app);
1921 } else if (pid > 0) {
1922 app.pid = pid;
1923 app.removed = false;
1924 synchronized (mPidsSelfLocked) {
1925 this.mPidsSelfLocked.put(pid, app);
1926 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1927 msg.obj = app;
1928 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1929 }
1930 } else {
1931 app.pid = 0;
1932 RuntimeException e = new RuntimeException(
1933 "Failure starting process " + app.processName
1934 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001935 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 }
1937 } catch (RuntimeException e) {
1938 // XXX do better error recovery.
1939 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001940 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 }
1942 }
1943
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001944 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 if (resumed) {
1946 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1947 } else {
1948 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1949 }
1950 }
1951
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001952 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001953 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1954 && mTopAction == null) {
1955 // We are running in factory test mode, but unable to find
1956 // the factory test app, so just sit around displaying the
1957 // error message and don't try to start anything.
1958 return false;
1959 }
1960 Intent intent = new Intent(
1961 mTopAction,
1962 mTopData != null ? Uri.parse(mTopData) : null);
1963 intent.setComponent(mTopComponent);
1964 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1965 intent.addCategory(Intent.CATEGORY_HOME);
1966 }
1967 ActivityInfo aInfo =
1968 intent.resolveActivityInfo(mContext.getPackageManager(),
1969 STOCK_PM_FLAGS);
1970 if (aInfo != null) {
1971 intent.setComponent(new ComponentName(
1972 aInfo.applicationInfo.packageName, aInfo.name));
1973 // Don't do this if the home app is currently being
1974 // instrumented.
1975 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1976 aInfo.applicationInfo.uid);
1977 if (app == null || app.instrumentationClass == null) {
1978 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001979 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001980 null, null, 0, 0, 0, false, false);
1981 }
1982 }
1983
1984
1985 return true;
1986 }
1987
1988 /**
1989 * Starts the "new version setup screen" if appropriate.
1990 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001991 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001992 // Only do this once per boot.
1993 if (mCheckedForSetup) {
1994 return;
1995 }
1996
1997 // We will show this screen if the current one is a different
1998 // version than the last one shown, and we are not running in
1999 // low-level factory test mode.
2000 final ContentResolver resolver = mContext.getContentResolver();
2001 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2002 Settings.Secure.getInt(resolver,
2003 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2004 mCheckedForSetup = true;
2005
2006 // See if we should be showing the platform update setup UI.
2007 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2008 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2009 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2010
2011 // We don't allow third party apps to replace this.
2012 ResolveInfo ri = null;
2013 for (int i=0; ris != null && i<ris.size(); i++) {
2014 if ((ris.get(i).activityInfo.applicationInfo.flags
2015 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2016 ri = ris.get(i);
2017 break;
2018 }
2019 }
2020
2021 if (ri != null) {
2022 String vers = ri.activityInfo.metaData != null
2023 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2024 : null;
2025 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2026 vers = ri.activityInfo.applicationInfo.metaData.getString(
2027 Intent.METADATA_SETUP_VERSION);
2028 }
2029 String lastVers = Settings.Secure.getString(
2030 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2031 if (vers != null && !vers.equals(lastVers)) {
2032 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2033 intent.setComponent(new ComponentName(
2034 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002035 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002036 null, null, 0, 0, 0, false, false);
2037 }
2038 }
2039 }
2040 }
2041
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002042 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002043 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002044
2045 final int identHash = System.identityHashCode(r);
2046 updateUsageStats(r, true);
2047
2048 int i = mWatchers.beginBroadcast();
2049 while (i > 0) {
2050 i--;
2051 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2052 if (w != null) {
2053 try {
2054 w.activityResuming(identHash);
2055 } catch (RemoteException e) {
2056 }
2057 }
2058 }
2059 mWatchers.finishBroadcast();
2060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002062 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002063 final int N = mPendingActivityLaunches.size();
2064 if (N <= 0) {
2065 return;
2066 }
2067 for (int i=0; i<N; i++) {
2068 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002069 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002070 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2071 doResume && i == (N-1));
2072 }
2073 mPendingActivityLaunches.clear();
2074 }
2075
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002076 public final int startActivity(IApplicationThread caller,
2077 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2078 int grantedMode, IBinder resultTo,
2079 String resultWho, int requestCode, boolean onlyIfNeeded,
2080 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002081 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002082 grantedUriPermissions, grantedMode, resultTo, resultWho,
2083 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002084 }
2085
2086 public final WaitResult startActivityAndWait(IApplicationThread caller,
2087 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2088 int grantedMode, IBinder resultTo,
2089 String resultWho, int requestCode, boolean onlyIfNeeded,
2090 boolean debug) {
2091 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002092 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002093 grantedUriPermissions, grantedMode, resultTo, resultWho,
2094 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002095 return res;
2096 }
2097
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002098 public final int startActivityWithConfig(IApplicationThread caller,
2099 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2100 int grantedMode, IBinder resultTo,
2101 String resultWho, int requestCode, boolean onlyIfNeeded,
2102 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002103 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002104 grantedUriPermissions, grantedMode, resultTo, resultWho,
2105 requestCode, onlyIfNeeded, debug, null, config);
2106 }
2107
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002108 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002109 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002110 IBinder resultTo, String resultWho, int requestCode,
2111 int flagsMask, int flagsValues) {
2112 // Refuse possible leaked file descriptors
2113 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2114 throw new IllegalArgumentException("File descriptors passed in Intent");
2115 }
2116
2117 IIntentSender sender = intent.getTarget();
2118 if (!(sender instanceof PendingIntentRecord)) {
2119 throw new IllegalArgumentException("Bad PendingIntent object");
2120 }
2121
2122 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002123
2124 synchronized (this) {
2125 // If this is coming from the currently resumed activity, it is
2126 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002127 if (mMainStack.mResumedActivity != null
2128 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002129 Binder.getCallingUid()) {
2130 mAppSwitchesAllowedTime = 0;
2131 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002132 }
2133
2134 return pir.sendInner(0, fillInIntent, resolvedType,
2135 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2136 }
2137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 public boolean startNextMatchingActivity(IBinder callingActivity,
2139 Intent intent) {
2140 // Refuse possible leaked file descriptors
2141 if (intent != null && intent.hasFileDescriptors() == true) {
2142 throw new IllegalArgumentException("File descriptors passed in Intent");
2143 }
2144
2145 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002146 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 if (index < 0) {
2148 return false;
2149 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002150 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 if (r.app == null || r.app.thread == null) {
2152 // The caller is not running... d'oh!
2153 return false;
2154 }
2155 intent = new Intent(intent);
2156 // The caller is not allowed to change the data.
2157 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2158 // And we are resetting to find the next component...
2159 intent.setComponent(null);
2160
2161 ActivityInfo aInfo = null;
2162 try {
2163 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002164 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002166 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167
2168 // Look for the original activity in the list...
2169 final int N = resolves != null ? resolves.size() : 0;
2170 for (int i=0; i<N; i++) {
2171 ResolveInfo rInfo = resolves.get(i);
2172 if (rInfo.activityInfo.packageName.equals(r.packageName)
2173 && rInfo.activityInfo.name.equals(r.info.name)) {
2174 // We found the current one... the next matching is
2175 // after it.
2176 i++;
2177 if (i<N) {
2178 aInfo = resolves.get(i).activityInfo;
2179 }
2180 break;
2181 }
2182 }
2183 } catch (RemoteException e) {
2184 }
2185
2186 if (aInfo == null) {
2187 // Nobody who is next!
2188 return false;
2189 }
2190
2191 intent.setComponent(new ComponentName(
2192 aInfo.applicationInfo.packageName, aInfo.name));
2193 intent.setFlags(intent.getFlags()&~(
2194 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2195 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2196 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2197 Intent.FLAG_ACTIVITY_NEW_TASK));
2198
2199 // Okay now we need to start the new activity, replacing the
2200 // currently running activity. This is a little tricky because
2201 // we want to start the new one as if the current one is finished,
2202 // but not finish the current one first so that there is no flicker.
2203 // And thus...
2204 final boolean wasFinishing = r.finishing;
2205 r.finishing = true;
2206
2207 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002208 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002209 final String resultWho = r.resultWho;
2210 final int requestCode = r.requestCode;
2211 r.resultTo = null;
2212 if (resultTo != null) {
2213 resultTo.removeResultsLocked(r, resultWho, requestCode);
2214 }
2215
2216 final long origId = Binder.clearCallingIdentity();
2217 // XXX we are not dealing with propagating grantedUriPermissions...
2218 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002219 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002221 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 Binder.restoreCallingIdentity(origId);
2223
2224 r.finishing = wasFinishing;
2225 if (res != START_SUCCESS) {
2226 return false;
2227 }
2228 return true;
2229 }
2230 }
2231
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002232 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 Intent intent, String resolvedType, IBinder resultTo,
2234 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002235
2236 // This is so super not safe, that only the system (or okay root)
2237 // can do it.
2238 final int callingUid = Binder.getCallingUid();
2239 if (callingUid != 0 && callingUid != Process.myUid()) {
2240 throw new SecurityException(
2241 "startActivityInPackage only available to the system");
2242 }
2243
The Android Open Source Project4df24232009-03-05 14:34:35 -08002244 final boolean componentSpecified = intent.getComponent() != null;
2245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002246 // Don't modify the client's object!
2247 intent = new Intent(intent);
2248
2249 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 ActivityInfo aInfo;
2251 try {
2252 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002253 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002255 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 aInfo = rInfo != null ? rInfo.activityInfo : null;
2257 } catch (RemoteException e) {
2258 aInfo = null;
2259 }
2260
2261 if (aInfo != null) {
2262 // Store the found target back into the intent, because now that
2263 // we have it we never want to do this again. For example, if the
2264 // user navigates back to this point in the history, we should
2265 // always restart the exact same activity.
2266 intent.setComponent(new ComponentName(
2267 aInfo.applicationInfo.packageName, aInfo.name));
2268 }
2269
2270 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002271 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002273 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 }
2275 }
2276
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002277 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002278 // Remove any existing entries that are the same kind of task.
2279 int N = mRecentTasks.size();
2280 for (int i=0; i<N; i++) {
2281 TaskRecord tr = mRecentTasks.get(i);
2282 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2283 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2284 mRecentTasks.remove(i);
2285 i--;
2286 N--;
2287 if (task.intent == null) {
2288 // If the new recent task we are adding is not fully
2289 // specified, then replace it with the existing recent task.
2290 task = tr;
2291 }
2292 }
2293 }
2294 if (N >= MAX_RECENT_TASKS) {
2295 mRecentTasks.remove(N-1);
2296 }
2297 mRecentTasks.add(0, task);
2298 }
2299
2300 public void setRequestedOrientation(IBinder token,
2301 int requestedOrientation) {
2302 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002303 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002304 if (index < 0) {
2305 return;
2306 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002307 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308 final long origId = Binder.clearCallingIdentity();
2309 mWindowManager.setAppOrientation(r, requestedOrientation);
2310 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002311 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 r.mayFreezeScreenLocked(r.app) ? r : null);
2313 if (config != null) {
2314 r.frozenBeforeDestroy = true;
2315 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002316 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 }
2318 }
2319 Binder.restoreCallingIdentity(origId);
2320 }
2321 }
2322
2323 public int getRequestedOrientation(IBinder token) {
2324 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002325 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 if (index < 0) {
2327 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2328 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002329 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002330 return mWindowManager.getAppOrientation(r);
2331 }
2332 }
2333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 /**
2335 * This is the internal entry point for handling Activity.finish().
2336 *
2337 * @param token The Binder token referencing the Activity we want to finish.
2338 * @param resultCode Result code, if any, from this Activity.
2339 * @param resultData Result data (Intent), if any, from this Activity.
2340 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002341 * @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 -08002342 */
2343 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2344 // Refuse possible leaked file descriptors
2345 if (resultData != null && resultData.hasFileDescriptors() == true) {
2346 throw new IllegalArgumentException("File descriptors passed in Intent");
2347 }
2348
2349 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002350 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002352 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 if (next != null) {
2354 // ask watcher if this is allowed
2355 boolean resumeOK = true;
2356 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002357 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002359 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 }
2361
2362 if (!resumeOK) {
2363 return false;
2364 }
2365 }
2366 }
2367 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002368 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 resultData, "app-request");
2370 Binder.restoreCallingIdentity(origId);
2371 return res;
2372 }
2373 }
2374
Dianne Hackborn860755f2010-06-03 18:47:52 -07002375 public final void finishHeavyWeightApp() {
2376 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2377 != PackageManager.PERMISSION_GRANTED) {
2378 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2379 + Binder.getCallingPid()
2380 + ", uid=" + Binder.getCallingUid()
2381 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2382 Slog.w(TAG, msg);
2383 throw new SecurityException(msg);
2384 }
2385
2386 synchronized(this) {
2387 if (mHeavyWeightProcess == null) {
2388 return;
2389 }
2390
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002391 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002392 mHeavyWeightProcess.activities);
2393 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002394 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002395 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002396 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002397 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002398 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002399 null, "finish-heavy");
2400 }
2401 }
2402 }
2403
2404 mHeavyWeightProcess = null;
2405 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2406 }
2407 }
2408
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002409 public void crashApplication(int uid, int initialPid, String packageName,
2410 String message) {
2411 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2412 != PackageManager.PERMISSION_GRANTED) {
2413 String msg = "Permission Denial: crashApplication() from pid="
2414 + Binder.getCallingPid()
2415 + ", uid=" + Binder.getCallingUid()
2416 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2417 Slog.w(TAG, msg);
2418 throw new SecurityException(msg);
2419 }
2420
2421 synchronized(this) {
2422 ProcessRecord proc = null;
2423
2424 // Figure out which process to kill. We don't trust that initialPid
2425 // still has any relation to current pids, so must scan through the
2426 // list.
2427 synchronized (mPidsSelfLocked) {
2428 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2429 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2430 if (p.info.uid != uid) {
2431 continue;
2432 }
2433 if (p.pid == initialPid) {
2434 proc = p;
2435 break;
2436 }
2437 for (String str : p.pkgList) {
2438 if (str.equals(packageName)) {
2439 proc = p;
2440 }
2441 }
2442 }
2443 }
2444
2445 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002446 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002447 + " initialPid=" + initialPid
2448 + " packageName=" + packageName);
2449 return;
2450 }
2451
2452 if (proc.thread != null) {
2453 long ident = Binder.clearCallingIdentity();
2454 try {
2455 proc.thread.scheduleCrash(message);
2456 } catch (RemoteException e) {
2457 }
2458 Binder.restoreCallingIdentity(ident);
2459 }
2460 }
2461 }
2462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002463 public final void finishSubActivity(IBinder token, String resultWho,
2464 int requestCode) {
2465 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002466 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 if (index < 0) {
2468 return;
2469 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002470 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471
2472 final long origId = Binder.clearCallingIdentity();
2473
2474 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002475 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2476 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 if (r.resultTo == self && r.requestCode == requestCode) {
2478 if ((r.resultWho == null && resultWho == null) ||
2479 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002480 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 Activity.RESULT_CANCELED, null, "request-sub");
2482 }
2483 }
2484 }
2485
2486 Binder.restoreCallingIdentity(origId);
2487 }
2488 }
2489
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002490 public boolean willActivityBeVisible(IBinder token) {
2491 synchronized(this) {
2492 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002493 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2494 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002495 if (r == token) {
2496 return true;
2497 }
2498 if (r.fullscreen && !r.finishing) {
2499 return false;
2500 }
2501 }
2502 return true;
2503 }
2504 }
2505
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002506 public void overridePendingTransition(IBinder token, String packageName,
2507 int enterAnim, int exitAnim) {
2508 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002509 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002510 if (index < 0) {
2511 return;
2512 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002513 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002514
2515 final long origId = Binder.clearCallingIdentity();
2516
2517 if (self.state == ActivityState.RESUMED
2518 || self.state == ActivityState.PAUSING) {
2519 mWindowManager.overridePendingAppTransition(packageName,
2520 enterAnim, exitAnim);
2521 }
2522
2523 Binder.restoreCallingIdentity(origId);
2524 }
2525 }
2526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 * Main function for removing an existing process from the activity manager
2529 * as a result of that process going away. Clears out all connections
2530 * to the process.
2531 */
2532 private final void handleAppDiedLocked(ProcessRecord app,
2533 boolean restarting) {
2534 cleanUpApplicationRecordLocked(app, restarting, -1);
2535 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002536 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 }
2538
2539 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002540 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2541 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2542 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002544 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2545 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 }
2547
2548 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002549 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550
2551 boolean atTop = true;
2552 boolean hasVisibleActivities = false;
2553
2554 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002555 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002556 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 TAG, "Removing app " + app + " from history with " + i + " entries");
2558 while (i > 0) {
2559 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002560 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002561 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2563 if (r.app == app) {
2564 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002565 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 TAG, "Removing this entry! frozen=" + r.haveState
2567 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002568 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569
2570 r.inHistory = false;
2571 mWindowManager.removeAppToken(r);
2572 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002573 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002575 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576
2577 } else {
2578 // We have the current state for this activity, so
2579 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002580 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 TAG, "Keeping entry, setting app to null");
2582 if (r.visible) {
2583 hasVisibleActivities = true;
2584 }
2585 r.app = null;
2586 r.nowVisible = false;
2587 if (!r.haveState) {
2588 r.icicle = null;
2589 }
2590 }
2591
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002592 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 r.state = ActivityState.STOPPED;
2594 }
2595 atTop = false;
2596 }
2597
2598 app.activities.clear();
2599
2600 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002601 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002602 + " running instrumentation " + app.instrumentationClass);
2603 Bundle info = new Bundle();
2604 info.putString("shortMsg", "Process crashed.");
2605 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2606 }
2607
2608 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002609 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 // If there was nothing to resume, and we are not already
2611 // restarting this process, but there is a visible activity that
2612 // is hosted by the process... then make sure all visible
2613 // activities are running, taking care of restarting this
2614 // process.
2615 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002616 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617 }
2618 }
2619 }
2620 }
2621
2622 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2623 IBinder threadBinder = thread.asBinder();
2624
2625 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002626 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2627 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2629 return i;
2630 }
2631 }
2632 return -1;
2633 }
2634
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002635 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002636 IApplicationThread thread) {
2637 if (thread == null) {
2638 return null;
2639 }
2640
2641 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002642 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 }
2644
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002645 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002646 IApplicationThread thread) {
2647
2648 mProcDeaths[0]++;
2649
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002650 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2651 synchronized (stats) {
2652 stats.noteProcessDiedLocked(app.info.uid, pid);
2653 }
2654
Magnus Edlund7bb25812010-02-24 15:45:06 +01002655 // Clean up already done if the process has been re-started.
2656 if (app.pid == pid && app.thread != null &&
2657 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002658 if (!app.killedBackground) {
2659 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2660 + ") has died.");
2661 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002662 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002663 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 TAG, "Dying app: " + app + ", pid: " + pid
2665 + ", thread: " + thread.asBinder());
2666 boolean doLowMem = app.instrumentationClass == null;
2667 handleAppDiedLocked(app, false);
2668
2669 if (doLowMem) {
2670 // If there are no longer any background processes running,
2671 // and the app that died was not running instrumentation,
2672 // then tell everyone we are now low on memory.
2673 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002674 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2675 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2677 haveBg = true;
2678 break;
2679 }
2680 }
2681
2682 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002683 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002684 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002685 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002686 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2687 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002688 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002689 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2690 // The low memory report is overriding any current
2691 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002692 // heavy/important/visible/foreground processes first.
2693 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002694 rec.lastRequestedGc = 0;
2695 } else {
2696 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002698 rec.reportLowMemory = true;
2699 rec.lastLowMemory = now;
2700 mProcessesToGc.remove(rec);
2701 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 }
2703 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002704 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 }
2706 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002707 } else if (app.pid != pid) {
2708 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002709 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002710 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002711 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002712 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002713 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 + thread.asBinder());
2715 }
2716 }
2717
Dan Egnor42471dd2010-01-07 17:25:22 -08002718 /**
2719 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002720 * @param clearTraces causes the dump file to be erased prior to the new
2721 * traces being written, if true; when false, the new traces will be
2722 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002723 * @param firstPids of dalvik VM processes to dump stack traces for first
2724 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002725 * @return file containing stack traces, or null if no dump file is configured
2726 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002727 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2728 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002729 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2730 if (tracesPath == null || tracesPath.length() == 0) {
2731 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002733
2734 File tracesFile = new File(tracesPath);
2735 try {
2736 File tracesDir = tracesFile.getParentFile();
2737 if (!tracesDir.exists()) tracesFile.mkdirs();
2738 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2739
Christopher Tate6ee412d2010-05-28 12:01:56 -07002740 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002741 tracesFile.createNewFile();
2742 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2743 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002744 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002745 return null;
2746 }
2747
2748 // Use a FileObserver to detect when traces finish writing.
2749 // The order of traces is considered important to maintain for legibility.
2750 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2751 public synchronized void onEvent(int event, String path) { notify(); }
2752 };
2753
2754 try {
2755 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002756
2757 // First collect all of the stacks of the most important pids.
2758 try {
2759 int num = firstPids.size();
2760 for (int i = 0; i < num; i++) {
2761 synchronized (observer) {
2762 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2763 observer.wait(200); // Wait for write-close, give up after 200msec
2764 }
2765 }
2766 } catch (InterruptedException e) {
2767 Log.wtf(TAG, e);
2768 }
2769
2770 // Next measure CPU usage.
2771 if (processStats != null) {
2772 processStats.init();
2773 System.gc();
2774 processStats.update();
2775 try {
2776 synchronized (processStats) {
2777 processStats.wait(500); // measure over 1/2 second.
2778 }
2779 } catch (InterruptedException e) {
2780 }
2781 processStats.update();
2782
2783 // We'll take the stack crawls of just the top apps using CPU.
2784 final int N = processStats.countWorkingStats();
2785 int numProcs = 0;
2786 for (int i=0; i<N && numProcs<5; i++) {
2787 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2788 if (lastPids.indexOfKey(stats.pid) >= 0) {
2789 numProcs++;
2790 try {
2791 synchronized (observer) {
2792 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2793 observer.wait(200); // Wait for write-close, give up after 200msec
2794 }
2795 } catch (InterruptedException e) {
2796 Log.wtf(TAG, e);
2797 }
2798
2799 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002800 }
2801 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002802
2803 return tracesFile;
2804
Dan Egnor42471dd2010-01-07 17:25:22 -08002805 } finally {
2806 observer.stopWatching();
2807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 }
2809
Jeff Brown4d94a762010-09-23 11:33:28 -07002810 private final class AppNotResponding implements Runnable {
2811 private final ProcessRecord mApp;
2812 private final String mAnnotation;
2813
2814 public AppNotResponding(ProcessRecord app, String annotation) {
2815 mApp = app;
2816 mAnnotation = annotation;
2817 }
2818
2819 @Override
2820 public void run() {
2821 appNotResponding(mApp, null, null, mAnnotation);
2822 }
2823 }
2824
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002825 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2826 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002827 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2828 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2829
Dianne Hackborn287952c2010-09-22 22:34:31 -07002830 if (mController != null) {
2831 try {
2832 // 0 == continue, -1 = kill process immediately
2833 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2834 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2835 } catch (RemoteException e) {
2836 mController = null;
2837 }
2838 }
2839
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002840 long anrTime = SystemClock.uptimeMillis();
2841 if (MONITOR_CPU_USAGE) {
2842 updateCpuStatsNow();
2843 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002844
2845 synchronized (this) {
2846 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2847 if (mShuttingDown) {
2848 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2849 return;
2850 } else if (app.notResponding) {
2851 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2852 return;
2853 } else if (app.crashing) {
2854 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2855 return;
2856 }
2857
2858 // In case we come through here for the same app before completing
2859 // this one, mark as anring now so we will bail out.
2860 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002861
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002862 // Log the ANR to the event log.
2863 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2864 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002865
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002866 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002867 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002868
2869 int parentPid = app.pid;
2870 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002871 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002872
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002873 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002874
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002875 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2876 ProcessRecord r = mLruProcesses.get(i);
2877 if (r != null && r.thread != null) {
2878 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002879 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2880 if (r.persistent) {
2881 firstPids.add(pid);
2882 } else {
2883 lastPids.put(pid, Boolean.TRUE);
2884 }
2885 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 }
2888 }
2889
Dan Egnor42471dd2010-01-07 17:25:22 -08002890 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002891 StringBuilder info = mStringBuilder;
2892 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002893 info.append("ANR in ").append(app.processName);
2894 if (activity != null && activity.shortComponentName != null) {
2895 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002896 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002897 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002899 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002901 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002902 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904
Dianne Hackborn287952c2010-09-22 22:34:31 -07002905 final ProcessStats processStats = new ProcessStats(true);
2906
2907 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2908
Dan Egnor42471dd2010-01-07 17:25:22 -08002909 String cpuInfo = null;
2910 if (MONITOR_CPU_USAGE) {
2911 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002912 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002913 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002914 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002915 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002916 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 }
2918
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002919 info.append(processStats.printCurrentState(anrTime));
2920
Joe Onorato8a9b2202010-02-26 18:56:32 -08002921 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002922 if (tracesFile == null) {
2923 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2924 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2925 }
2926
2927 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2928
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002929 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002931 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2932 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002934 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2935 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 }
2937 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002938 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 }
2940 }
2941
Dan Egnor42471dd2010-01-07 17:25:22 -08002942 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2943 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2944 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002945
2946 synchronized (this) {
2947 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2948 Process.killProcess(app.pid);
2949 return;
2950 }
2951
2952 // Set the app's notResponding state, and look up the errorReportReceiver
2953 makeAppNotRespondingLocked(app,
2954 activity != null ? activity.shortComponentName : null,
2955 annotation != null ? "ANR " + annotation : "ANR",
2956 info.toString());
2957
2958 // Bring up the infamous App Not Responding dialog
2959 Message msg = Message.obtain();
2960 HashMap map = new HashMap();
2961 msg.what = SHOW_NOT_RESPONDING_MSG;
2962 msg.obj = map;
2963 map.put("app", app);
2964 if (activity != null) {
2965 map.put("activity", activity);
2966 }
2967
2968 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 }
2971
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002972 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2973 if (!mLaunchWarningShown) {
2974 mLaunchWarningShown = true;
2975 mHandler.post(new Runnable() {
2976 @Override
2977 public void run() {
2978 synchronized (ActivityManagerService.this) {
2979 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2980 d.show();
2981 mHandler.postDelayed(new Runnable() {
2982 @Override
2983 public void run() {
2984 synchronized (ActivityManagerService.this) {
2985 d.dismiss();
2986 mLaunchWarningShown = false;
2987 }
2988 }
2989 }, 4000);
2990 }
2991 }
2992 });
2993 }
2994 }
2995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 public boolean clearApplicationUserData(final String packageName,
2997 final IPackageDataObserver observer) {
2998 int uid = Binder.getCallingUid();
2999 int pid = Binder.getCallingPid();
3000 long callingId = Binder.clearCallingIdentity();
3001 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003002 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 int pkgUid = -1;
3004 synchronized(this) {
3005 try {
3006 pkgUid = pm.getPackageUid(packageName);
3007 } catch (RemoteException e) {
3008 }
3009 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003010 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003011 return false;
3012 }
3013 if (uid == pkgUid || checkComponentPermission(
3014 android.Manifest.permission.CLEAR_APP_USER_DATA,
3015 pid, uid, -1)
3016 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003017 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 } else {
3019 throw new SecurityException(pid+" does not have permission:"+
3020 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3021 "for process:"+packageName);
3022 }
3023 }
3024
3025 try {
3026 //clear application user data
3027 pm.clearApplicationUserData(packageName, observer);
3028 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3029 Uri.fromParts("package", packageName, null));
3030 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003031 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3032 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 } catch (RemoteException e) {
3034 }
3035 } finally {
3036 Binder.restoreCallingIdentity(callingId);
3037 }
3038 return true;
3039 }
3040
Dianne Hackborn03abb812010-01-04 18:43:19 -08003041 public void killBackgroundProcesses(final String packageName) {
3042 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3043 != PackageManager.PERMISSION_GRANTED &&
3044 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3045 != PackageManager.PERMISSION_GRANTED) {
3046 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 + Binder.getCallingPid()
3048 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003049 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003050 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 throw new SecurityException(msg);
3052 }
3053
3054 long callingId = Binder.clearCallingIdentity();
3055 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003056 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 int pkgUid = -1;
3058 synchronized(this) {
3059 try {
3060 pkgUid = pm.getPackageUid(packageName);
3061 } catch (RemoteException e) {
3062 }
3063 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003064 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 return;
3066 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003067 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003068 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003069 }
3070 } finally {
3071 Binder.restoreCallingIdentity(callingId);
3072 }
3073 }
3074
3075 public void forceStopPackage(final String packageName) {
3076 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3077 != PackageManager.PERMISSION_GRANTED) {
3078 String msg = "Permission Denial: forceStopPackage() from pid="
3079 + Binder.getCallingPid()
3080 + ", uid=" + Binder.getCallingUid()
3081 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003082 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003083 throw new SecurityException(msg);
3084 }
3085
3086 long callingId = Binder.clearCallingIdentity();
3087 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003088 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003089 int pkgUid = -1;
3090 synchronized(this) {
3091 try {
3092 pkgUid = pm.getPackageUid(packageName);
3093 } catch (RemoteException e) {
3094 }
3095 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003096 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003097 return;
3098 }
3099 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 }
3101 } finally {
3102 Binder.restoreCallingIdentity(callingId);
3103 }
3104 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003105
3106 /*
3107 * The pkg name and uid have to be specified.
3108 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3109 */
3110 public void killApplicationWithUid(String pkg, int uid) {
3111 if (pkg == null) {
3112 return;
3113 }
3114 // Make sure the uid is valid.
3115 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003116 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003117 return;
3118 }
3119 int callerUid = Binder.getCallingUid();
3120 // Only the system server can kill an application
3121 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003122 // Post an aysnc message to kill the application
3123 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3124 msg.arg1 = uid;
3125 msg.arg2 = 0;
3126 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003127 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003128 } else {
3129 throw new SecurityException(callerUid + " cannot kill pkg: " +
3130 pkg);
3131 }
3132 }
3133
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003134 public void closeSystemDialogs(String reason) {
3135 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003136 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003137 if (reason != null) {
3138 intent.putExtra("reason", reason);
3139 }
3140
3141 final int uid = Binder.getCallingUid();
3142 final long origId = Binder.clearCallingIdentity();
3143 synchronized (this) {
3144 int i = mWatchers.beginBroadcast();
3145 while (i > 0) {
3146 i--;
3147 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3148 if (w != null) {
3149 try {
3150 w.closingSystemDialogs(reason);
3151 } catch (RemoteException e) {
3152 }
3153 }
3154 }
3155 mWatchers.finishBroadcast();
3156
Dianne Hackbornffa42482009-09-23 22:20:11 -07003157 mWindowManager.closeSystemDialogs(reason);
3158
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003159 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3160 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003161 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003162 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003163 Activity.RESULT_CANCELED, null, "close-sys");
3164 }
3165 }
3166
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003167 broadcastIntentLocked(null, null, intent, null,
3168 null, 0, null, null, null, false, false, -1, uid);
3169 }
3170 Binder.restoreCallingIdentity(origId);
3171 }
3172
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003173 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003174 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003175 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3176 for (int i=pids.length-1; i>=0; i--) {
3177 infos[i] = new Debug.MemoryInfo();
3178 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003179 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003180 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003181 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003182
3183 public void killApplicationProcess(String processName, int uid) {
3184 if (processName == null) {
3185 return;
3186 }
3187
3188 int callerUid = Binder.getCallingUid();
3189 // Only the system server can kill an application
3190 if (callerUid == Process.SYSTEM_UID) {
3191 synchronized (this) {
3192 ProcessRecord app = getProcessRecordLocked(processName, uid);
3193 if (app != null) {
3194 try {
3195 app.thread.scheduleSuicide();
3196 } catch (RemoteException e) {
3197 // If the other end already died, then our work here is done.
3198 }
3199 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003200 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003201 + processName + " / " + uid);
3202 }
3203 }
3204 } else {
3205 throw new SecurityException(callerUid + " cannot kill app process: " +
3206 processName);
3207 }
3208 }
3209
Dianne Hackborn03abb812010-01-04 18:43:19 -08003210 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003211 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3213 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003214 if (!mProcessesReady) {
3215 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 intent.putExtra(Intent.EXTRA_UID, uid);
3218 broadcastIntentLocked(null, null, intent,
3219 null, null, 0, null, null, null,
3220 false, false, MY_PID, Process.SYSTEM_UID);
3221 }
3222
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003223 private final boolean killPackageProcessesLocked(String packageName, int uid,
3224 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003225 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226
Dianne Hackborn03abb812010-01-04 18:43:19 -08003227 // Remove all processes this package may have touched: all with the
3228 // same UID (except for the system or root user), and all whose name
3229 // matches the package name.
3230 final String procNamePrefix = packageName + ":";
3231 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3232 final int NA = apps.size();
3233 for (int ia=0; ia<NA; ia++) {
3234 ProcessRecord app = apps.valueAt(ia);
3235 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003236 if (doit) {
3237 procs.add(app);
3238 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003239 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3240 || app.processName.equals(packageName)
3241 || app.processName.startsWith(procNamePrefix)) {
3242 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003243 if (!doit) {
3244 return true;
3245 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003246 app.removed = true;
3247 procs.add(app);
3248 }
3249 }
3250 }
3251 }
3252
3253 int N = procs.size();
3254 for (int i=0; i<N; i++) {
3255 removeProcessLocked(procs.get(i), callerWillRestart);
3256 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003257 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003258 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003259
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003260 private final boolean forceStopPackageLocked(String name, int uid,
3261 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 int i, N;
3263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 if (uid < 0) {
3265 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003266 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 } catch (RemoteException e) {
3268 }
3269 }
3270
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003271 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003272 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003273
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003274 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3275 while (badApps.hasNext()) {
3276 SparseArray<Long> ba = badApps.next();
3277 if (ba.get(uid) != null) {
3278 badApps.remove();
3279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003280 }
3281 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003282
3283 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3284 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003286 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3287 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003289 if (!doit) {
3290 return true;
3291 }
3292 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003293 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 if (r.app != null) {
3295 r.app.removed = true;
3296 }
3297 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003298 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 }
3300 }
3301
3302 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3303 for (ServiceRecord service : mServices.values()) {
3304 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003305 if (!doit) {
3306 return true;
3307 }
3308 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003309 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 if (service.app != null) {
3311 service.app.removed = true;
3312 }
3313 service.app = null;
3314 services.add(service);
3315 }
3316 }
3317
3318 N = services.size();
3319 for (i=0; i<N; i++) {
3320 bringDownServiceLocked(services.get(i), true);
3321 }
3322
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003323 if (doit) {
3324 if (purgeCache) {
3325 AttributeCache ac = AttributeCache.instance();
3326 if (ac != null) {
3327 ac.removePackage(name);
3328 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003329 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003330 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003331 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003332
3333 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003334 }
3335
3336 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3337 final String name = app.processName;
3338 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003339 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 TAG, "Force removing process " + app + " (" + name
3341 + "/" + uid + ")");
3342
3343 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003344 if (mHeavyWeightProcess == app) {
3345 mHeavyWeightProcess = null;
3346 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 boolean needRestart = false;
3349 if (app.pid > 0 && app.pid != MY_PID) {
3350 int pid = app.pid;
3351 synchronized (mPidsSelfLocked) {
3352 mPidsSelfLocked.remove(pid);
3353 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3354 }
3355 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003356 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 Process.killProcess(pid);
3358
3359 if (app.persistent) {
3360 if (!callerWillRestart) {
3361 addAppLocked(app.info);
3362 } else {
3363 needRestart = true;
3364 }
3365 }
3366 } else {
3367 mRemovedProcesses.add(app);
3368 }
3369
3370 return needRestart;
3371 }
3372
3373 private final void processStartTimedOutLocked(ProcessRecord app) {
3374 final int pid = app.pid;
3375 boolean gone = false;
3376 synchronized (mPidsSelfLocked) {
3377 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3378 if (knownApp != null && knownApp.thread == null) {
3379 mPidsSelfLocked.remove(pid);
3380 gone = true;
3381 }
3382 }
3383
3384 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003385 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003386 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003387 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003389 if (mHeavyWeightProcess == app) {
3390 mHeavyWeightProcess = null;
3391 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3392 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003393 // Take care of any launching providers waiting for this process.
3394 checkAppInLaunchingProvidersLocked(app, true);
3395 // Take care of any services that are waiting for the process.
3396 for (int i=0; i<mPendingServices.size(); i++) {
3397 ServiceRecord sr = mPendingServices.get(i);
3398 if (app.info.uid == sr.appInfo.uid
3399 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003400 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003401 mPendingServices.remove(i);
3402 i--;
3403 bringDownServiceLocked(sr, true);
3404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003406 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003407 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003408 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003409 try {
3410 IBackupManager bm = IBackupManager.Stub.asInterface(
3411 ServiceManager.getService(Context.BACKUP_SERVICE));
3412 bm.agentDisconnected(app.info.packageName);
3413 } catch (RemoteException e) {
3414 // Can't happen; the backup manager is local
3415 }
3416 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003417 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003418 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003419 mPendingBroadcast.state = BroadcastRecord.IDLE;
3420 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003421 mPendingBroadcast = null;
3422 scheduleBroadcastsLocked();
3423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003425 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 }
3427 }
3428
3429 private final boolean attachApplicationLocked(IApplicationThread thread,
3430 int pid) {
3431
3432 // Find the application record that is being attached... either via
3433 // the pid if we are running in multiple processes, or just pull the
3434 // next app record if we are emulating process with anonymous threads.
3435 ProcessRecord app;
3436 if (pid != MY_PID && pid >= 0) {
3437 synchronized (mPidsSelfLocked) {
3438 app = mPidsSelfLocked.get(pid);
3439 }
3440 } else if (mStartingProcesses.size() > 0) {
3441 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003442 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443 } else {
3444 app = null;
3445 }
3446
3447 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003448 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003450 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 if (pid > 0 && pid != MY_PID) {
3452 Process.killProcess(pid);
3453 } else {
3454 try {
3455 thread.scheduleExit();
3456 } catch (Exception e) {
3457 // Ignore exceptions.
3458 }
3459 }
3460 return false;
3461 }
3462
3463 // If this application record is still attached to a previous
3464 // process, clean it up now.
3465 if (app.thread != null) {
3466 handleAppDiedLocked(app, true);
3467 }
3468
3469 // Tell the process all about itself.
3470
Joe Onorato8a9b2202010-02-26 18:56:32 -08003471 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 TAG, "Binding process pid " + pid + " to record " + app);
3473
3474 String processName = app.processName;
3475 try {
3476 thread.asBinder().linkToDeath(new AppDeathRecipient(
3477 app, pid, thread), 0);
3478 } catch (RemoteException e) {
3479 app.resetPackageList();
3480 startProcessLocked(app, "link fail", processName);
3481 return false;
3482 }
3483
Doug Zongker2bec3d42009-12-04 12:52:44 -08003484 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485
3486 app.thread = thread;
3487 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003488 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3489 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003490 app.forcingToForeground = null;
3491 app.foregroundServices = false;
3492 app.debugging = false;
3493
3494 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3495
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003496 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003497 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003499 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003500 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003501 }
3502
Joe Onorato8a9b2202010-02-26 18:56:32 -08003503 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 TAG, "New app record " + app
3505 + " thread=" + thread.asBinder() + " pid=" + pid);
3506 try {
3507 int testMode = IApplicationThread.DEBUG_OFF;
3508 if (mDebugApp != null && mDebugApp.equals(processName)) {
3509 testMode = mWaitForDebugger
3510 ? IApplicationThread.DEBUG_WAIT
3511 : IApplicationThread.DEBUG_ON;
3512 app.debugging = true;
3513 if (mDebugTransient) {
3514 mDebugApp = mOrigDebugApp;
3515 mWaitForDebugger = mOrigWaitForDebugger;
3516 }
3517 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003518
Christopher Tate181fafa2009-05-14 11:12:14 -07003519 // If the app is being launched for restore or full backup, set it up specially
3520 boolean isRestrictedBackupMode = false;
3521 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3522 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3523 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3524 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003525
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003526 ensurePackageDexOpt(app.instrumentationInfo != null
3527 ? app.instrumentationInfo.packageName
3528 : app.info.packageName);
3529 if (app.instrumentationClass != null) {
3530 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003531 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003532 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003533 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003534 thread.bindApplication(processName, app.instrumentationInfo != null
3535 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 app.instrumentationClass, app.instrumentationProfileFile,
3537 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003538 isRestrictedBackupMode || !normalMode,
3539 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003540 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003541 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 } catch (Exception e) {
3543 // todo: Yikes! What should we do? For now we will try to
3544 // start another process, but that could easily get us in
3545 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003546 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547
3548 app.resetPackageList();
3549 startProcessLocked(app, "bind fail", processName);
3550 return false;
3551 }
3552
3553 // Remove this record from the list of starting applications.
3554 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003555 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3556 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 mProcessesOnHold.remove(app);
3558
3559 boolean badApp = false;
3560 boolean didSomething = false;
3561
3562 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003563 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003564 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3566 && processName.equals(hr.processName)) {
3567 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003568 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003569 didSomething = true;
3570 }
3571 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003572 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 + hr.intent.getComponent().flattenToShortString(), e);
3574 badApp = true;
3575 }
3576 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003577 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 }
3579 }
3580
3581 // Find any services that should be running in this process...
3582 if (!badApp && mPendingServices.size() > 0) {
3583 ServiceRecord sr = null;
3584 try {
3585 for (int i=0; i<mPendingServices.size(); i++) {
3586 sr = mPendingServices.get(i);
3587 if (app.info.uid != sr.appInfo.uid
3588 || !processName.equals(sr.processName)) {
3589 continue;
3590 }
3591
3592 mPendingServices.remove(i);
3593 i--;
3594 realStartServiceLocked(sr, app);
3595 didSomething = true;
3596 }
3597 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003598 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 + sr.shortName, e);
3600 badApp = true;
3601 }
3602 }
3603
3604 // Check if the next broadcast receiver is in this process...
3605 BroadcastRecord br = mPendingBroadcast;
3606 if (!badApp && br != null && br.curApp == app) {
3607 try {
3608 mPendingBroadcast = null;
3609 processCurBroadcastLocked(br, app);
3610 didSomething = true;
3611 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003612 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 + br.curComponent.flattenToShortString(), e);
3614 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003615 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3617 br.resultExtras, br.resultAbort, true);
3618 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003619 // We need to reset the state if we fails to start the receiver.
3620 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 }
3622 }
3623
Christopher Tate181fafa2009-05-14 11:12:14 -07003624 // Check whether the next backup agent is in this process...
3625 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003626 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003627 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003628 try {
3629 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3630 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003631 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003632 e.printStackTrace();
3633 }
3634 }
3635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 if (badApp) {
3637 // todo: Also need to kill application to deal with all
3638 // kinds of exceptions.
3639 handleAppDiedLocked(app, false);
3640 return false;
3641 }
3642
3643 if (!didSomething) {
3644 updateOomAdjLocked();
3645 }
3646
3647 return true;
3648 }
3649
3650 public final void attachApplication(IApplicationThread thread) {
3651 synchronized (this) {
3652 int callingPid = Binder.getCallingPid();
3653 final long origId = Binder.clearCallingIdentity();
3654 attachApplicationLocked(thread, callingPid);
3655 Binder.restoreCallingIdentity(origId);
3656 }
3657 }
3658
Dianne Hackborne88846e2009-09-30 21:34:25 -07003659 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003661 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 Binder.restoreCallingIdentity(origId);
3663 }
3664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003666 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003667 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 mWindowManager.enableScreenAfterBoot();
3669 }
3670
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003671 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003672 IntentFilter pkgFilter = new IntentFilter();
3673 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3674 pkgFilter.addDataScheme("package");
3675 mContext.registerReceiver(new BroadcastReceiver() {
3676 @Override
3677 public void onReceive(Context context, Intent intent) {
3678 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3679 if (pkgs != null) {
3680 for (String pkg : pkgs) {
3681 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3682 setResultCode(Activity.RESULT_OK);
3683 return;
3684 }
3685 }
3686 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003687 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003688 }, pkgFilter);
3689
3690 synchronized (this) {
3691 // Ensure that any processes we had put on hold are now started
3692 // up.
3693 final int NP = mProcessesOnHold.size();
3694 if (NP > 0) {
3695 ArrayList<ProcessRecord> procs =
3696 new ArrayList<ProcessRecord>(mProcessesOnHold);
3697 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003698 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3699 + procs.get(ip));
3700 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003701 }
3702 }
3703
3704 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003705 // Start looking for apps that are abusing wake locks.
3706 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003707 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003708 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003709 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003710 broadcastIntentLocked(null, null,
3711 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3712 null, null, 0, null, null,
3713 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3714 false, false, MY_PID, Process.SYSTEM_UID);
3715 }
3716 }
3717 }
3718
3719 final void ensureBootCompleted() {
3720 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003721 boolean enableScreen;
3722 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003723 booting = mBooting;
3724 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003725 enableScreen = !mBooted;
3726 mBooted = true;
3727 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003728
3729 if (booting) {
3730 finishBooting();
3731 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003732
3733 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003734 enableScreenAfterBoot();
3735 }
3736 }
3737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003738 public final void activityPaused(IBinder token, Bundle icicle) {
3739 // Refuse possible leaked file descriptors
3740 if (icicle != null && icicle.hasFileDescriptors()) {
3741 throw new IllegalArgumentException("File descriptors passed in Bundle");
3742 }
3743
3744 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003745 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003746 Binder.restoreCallingIdentity(origId);
3747 }
3748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 public final void activityStopped(IBinder token, Bitmap thumbnail,
3750 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003751 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 TAG, "Activity stopped: token=" + token);
3753
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003754 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755
3756 final long origId = Binder.clearCallingIdentity();
3757
3758 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003759 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003761 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003762 r.thumbnail = thumbnail;
3763 r.description = description;
3764 r.stopped = true;
3765 r.state = ActivityState.STOPPED;
3766 if (!r.finishing) {
3767 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003768 r.stack.destroyActivityLocked(r, true);
3769 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003770 }
3771 }
3772 }
3773 }
3774
3775 if (r != null) {
3776 sendPendingThumbnail(r, null, null, null, false);
3777 }
3778
3779 trimApplications();
3780
3781 Binder.restoreCallingIdentity(origId);
3782 }
3783
3784 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003785 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003786 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 }
3788
3789 public String getCallingPackage(IBinder token) {
3790 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003791 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003792 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003793 }
3794 }
3795
3796 public ComponentName getCallingActivity(IBinder token) {
3797 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003798 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 return r != null ? r.intent.getComponent() : null;
3800 }
3801 }
3802
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003803 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003804 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003806 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 if (r != null) {
3808 return r.resultTo;
3809 }
3810 }
3811 return null;
3812 }
3813
3814 public ComponentName getActivityClassForToken(IBinder token) {
3815 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003816 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003818 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 return r.intent.getComponent();
3820 }
3821 return null;
3822 }
3823 }
3824
3825 public String getPackageForToken(IBinder token) {
3826 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003827 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003829 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 return r.packageName;
3831 }
3832 return null;
3833 }
3834 }
3835
3836 public IIntentSender getIntentSender(int type,
3837 String packageName, IBinder token, String resultWho,
3838 int requestCode, Intent intent, String resolvedType, int flags) {
3839 // Refuse possible leaked file descriptors
3840 if (intent != null && intent.hasFileDescriptors() == true) {
3841 throw new IllegalArgumentException("File descriptors passed in Intent");
3842 }
3843
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003844 if (type == INTENT_SENDER_BROADCAST) {
3845 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3846 throw new IllegalArgumentException(
3847 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3848 }
3849 }
3850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003851 synchronized(this) {
3852 int callingUid = Binder.getCallingUid();
3853 try {
3854 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3855 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003856 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857 .getPackageUid(packageName);
3858 if (uid != Binder.getCallingUid()) {
3859 String msg = "Permission Denial: getIntentSender() from pid="
3860 + Binder.getCallingPid()
3861 + ", uid=" + Binder.getCallingUid()
3862 + ", (need uid=" + uid + ")"
3863 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003864 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 throw new SecurityException(msg);
3866 }
3867 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003868
3869 return getIntentSenderLocked(type, packageName, callingUid,
3870 token, resultWho, requestCode, intent, resolvedType, flags);
3871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 } catch (RemoteException e) {
3873 throw new SecurityException(e);
3874 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003875 }
3876 }
3877
3878 IIntentSender getIntentSenderLocked(int type,
3879 String packageName, int callingUid, IBinder token, String resultWho,
3880 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003881 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003882 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003883 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003884 if (index < 0) {
3885 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003887 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003888 if (activity.finishing) {
3889 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003891 }
3892
3893 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3894 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3895 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3896 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3897 |PendingIntent.FLAG_UPDATE_CURRENT);
3898
3899 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3900 type, packageName, activity, resultWho,
3901 requestCode, intent, resolvedType, flags);
3902 WeakReference<PendingIntentRecord> ref;
3903 ref = mIntentSenderRecords.get(key);
3904 PendingIntentRecord rec = ref != null ? ref.get() : null;
3905 if (rec != null) {
3906 if (!cancelCurrent) {
3907 if (updateCurrent) {
3908 rec.key.requestIntent.replaceExtras(intent);
3909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 return rec;
3911 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003912 rec.canceled = true;
3913 mIntentSenderRecords.remove(key);
3914 }
3915 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 return rec;
3917 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003918 rec = new PendingIntentRecord(this, key, callingUid);
3919 mIntentSenderRecords.put(key, rec.ref);
3920 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3921 if (activity.pendingResults == null) {
3922 activity.pendingResults
3923 = new HashSet<WeakReference<PendingIntentRecord>>();
3924 }
3925 activity.pendingResults.add(rec.ref);
3926 }
3927 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 }
3929
3930 public void cancelIntentSender(IIntentSender sender) {
3931 if (!(sender instanceof PendingIntentRecord)) {
3932 return;
3933 }
3934 synchronized(this) {
3935 PendingIntentRecord rec = (PendingIntentRecord)sender;
3936 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003937 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 .getPackageUid(rec.key.packageName);
3939 if (uid != Binder.getCallingUid()) {
3940 String msg = "Permission Denial: cancelIntentSender() from pid="
3941 + Binder.getCallingPid()
3942 + ", uid=" + Binder.getCallingUid()
3943 + " is not allowed to cancel packges "
3944 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003945 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003946 throw new SecurityException(msg);
3947 }
3948 } catch (RemoteException e) {
3949 throw new SecurityException(e);
3950 }
3951 cancelIntentSenderLocked(rec, true);
3952 }
3953 }
3954
3955 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
3956 rec.canceled = true;
3957 mIntentSenderRecords.remove(rec.key);
3958 if (cleanActivity && rec.key.activity != null) {
3959 rec.key.activity.pendingResults.remove(rec.ref);
3960 }
3961 }
3962
3963 public String getPackageForIntentSender(IIntentSender pendingResult) {
3964 if (!(pendingResult instanceof PendingIntentRecord)) {
3965 return null;
3966 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07003967 try {
3968 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
3969 return res.key.packageName;
3970 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 }
3972 return null;
3973 }
3974
3975 public void setProcessLimit(int max) {
3976 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
3977 "setProcessLimit()");
3978 mProcessLimit = max;
3979 }
3980
3981 public int getProcessLimit() {
3982 return mProcessLimit;
3983 }
3984
3985 void foregroundTokenDied(ForegroundToken token) {
3986 synchronized (ActivityManagerService.this) {
3987 synchronized (mPidsSelfLocked) {
3988 ForegroundToken cur
3989 = mForegroundProcesses.get(token.pid);
3990 if (cur != token) {
3991 return;
3992 }
3993 mForegroundProcesses.remove(token.pid);
3994 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
3995 if (pr == null) {
3996 return;
3997 }
3998 pr.forcingToForeground = null;
3999 pr.foregroundServices = false;
4000 }
4001 updateOomAdjLocked();
4002 }
4003 }
4004
4005 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4006 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4007 "setProcessForeground()");
4008 synchronized(this) {
4009 boolean changed = false;
4010
4011 synchronized (mPidsSelfLocked) {
4012 ProcessRecord pr = mPidsSelfLocked.get(pid);
4013 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004014 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 return;
4016 }
4017 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4018 if (oldToken != null) {
4019 oldToken.token.unlinkToDeath(oldToken, 0);
4020 mForegroundProcesses.remove(pid);
4021 pr.forcingToForeground = null;
4022 changed = true;
4023 }
4024 if (isForeground && token != null) {
4025 ForegroundToken newToken = new ForegroundToken() {
4026 public void binderDied() {
4027 foregroundTokenDied(this);
4028 }
4029 };
4030 newToken.pid = pid;
4031 newToken.token = token;
4032 try {
4033 token.linkToDeath(newToken, 0);
4034 mForegroundProcesses.put(pid, newToken);
4035 pr.forcingToForeground = token;
4036 changed = true;
4037 } catch (RemoteException e) {
4038 // If the process died while doing this, we will later
4039 // do the cleanup with the process death link.
4040 }
4041 }
4042 }
4043
4044 if (changed) {
4045 updateOomAdjLocked();
4046 }
4047 }
4048 }
4049
4050 // =========================================================
4051 // PERMISSIONS
4052 // =========================================================
4053
4054 static class PermissionController extends IPermissionController.Stub {
4055 ActivityManagerService mActivityManagerService;
4056 PermissionController(ActivityManagerService activityManagerService) {
4057 mActivityManagerService = activityManagerService;
4058 }
4059
4060 public boolean checkPermission(String permission, int pid, int uid) {
4061 return mActivityManagerService.checkPermission(permission, pid,
4062 uid) == PackageManager.PERMISSION_GRANTED;
4063 }
4064 }
4065
4066 /**
4067 * This can be called with or without the global lock held.
4068 */
4069 int checkComponentPermission(String permission, int pid, int uid,
4070 int reqUid) {
4071 // We might be performing an operation on behalf of an indirect binder
4072 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4073 // client identity accordingly before proceeding.
4074 Identity tlsIdentity = sCallerIdentity.get();
4075 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004076 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4078 uid = tlsIdentity.uid;
4079 pid = tlsIdentity.pid;
4080 }
4081
4082 // Root, system server and our own process get to do everything.
4083 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4084 !Process.supportsProcesses()) {
4085 return PackageManager.PERMISSION_GRANTED;
4086 }
4087 // If the target requires a specific UID, always fail for others.
4088 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004089 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004090 return PackageManager.PERMISSION_DENIED;
4091 }
4092 if (permission == null) {
4093 return PackageManager.PERMISSION_GRANTED;
4094 }
4095 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004096 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 .checkUidPermission(permission, uid);
4098 } catch (RemoteException e) {
4099 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004100 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 }
4102 return PackageManager.PERMISSION_DENIED;
4103 }
4104
4105 /**
4106 * As the only public entry point for permissions checking, this method
4107 * can enforce the semantic that requesting a check on a null global
4108 * permission is automatically denied. (Internally a null permission
4109 * string is used when calling {@link #checkComponentPermission} in cases
4110 * when only uid-based security is needed.)
4111 *
4112 * This can be called with or without the global lock held.
4113 */
4114 public int checkPermission(String permission, int pid, int uid) {
4115 if (permission == null) {
4116 return PackageManager.PERMISSION_DENIED;
4117 }
4118 return checkComponentPermission(permission, pid, uid, -1);
4119 }
4120
4121 /**
4122 * Binder IPC calls go through the public entry point.
4123 * This can be called with or without the global lock held.
4124 */
4125 int checkCallingPermission(String permission) {
4126 return checkPermission(permission,
4127 Binder.getCallingPid(),
4128 Binder.getCallingUid());
4129 }
4130
4131 /**
4132 * This can be called with or without the global lock held.
4133 */
4134 void enforceCallingPermission(String permission, String func) {
4135 if (checkCallingPermission(permission)
4136 == PackageManager.PERMISSION_GRANTED) {
4137 return;
4138 }
4139
4140 String msg = "Permission Denial: " + func + " from pid="
4141 + Binder.getCallingPid()
4142 + ", uid=" + Binder.getCallingUid()
4143 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004144 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004145 throw new SecurityException(msg);
4146 }
4147
4148 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004149 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4150 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4151 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4152 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4153 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004154 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004155 // Is the component private from the target uid?
4156 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4157
4158 // Acceptable if the there is no read permission needed from the
4159 // target or the target is holding the read permission.
4160 if (!readPerm) {
4161 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004163 == PackageManager.PERMISSION_GRANTED)) {
4164 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165 }
4166 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004167
4168 // Acceptable if the there is no write permission needed from the
4169 // target or the target is holding the read permission.
4170 if (!writePerm) {
4171 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004173 == PackageManager.PERMISSION_GRANTED)) {
4174 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004175 }
4176 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004177
4178 // Acceptable if there is a path permission matching the URI that
4179 // the target holds the permission on.
4180 PathPermission[] pps = pi.pathPermissions;
4181 if (pps != null && (!readPerm || !writePerm)) {
4182 final String path = uri.getPath();
4183 int i = pps.length;
4184 while (i > 0 && (!readPerm || !writePerm)) {
4185 i--;
4186 PathPermission pp = pps[i];
4187 if (!readPerm) {
4188 final String pprperm = pp.getReadPermission();
4189 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4190 + pprperm + " for " + pp.getPath()
4191 + ": match=" + pp.match(path)
4192 + " check=" + pm.checkUidPermission(pprperm, uid));
4193 if (pprperm != null && pp.match(path) &&
4194 (pm.checkUidPermission(pprperm, uid)
4195 == PackageManager.PERMISSION_GRANTED)) {
4196 readPerm = true;
4197 }
4198 }
4199 if (!writePerm) {
4200 final String ppwperm = pp.getWritePermission();
4201 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4202 + ppwperm + " for " + pp.getPath()
4203 + ": match=" + pp.match(path)
4204 + " check=" + pm.checkUidPermission(ppwperm, uid));
4205 if (ppwperm != null && pp.match(path) &&
4206 (pm.checkUidPermission(ppwperm, uid)
4207 == PackageManager.PERMISSION_GRANTED)) {
4208 writePerm = true;
4209 }
4210 }
4211 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004213 } catch (RemoteException e) {
4214 return false;
4215 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004216
4217 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 }
4219
4220 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4221 int modeFlags) {
4222 // Root gets to do everything.
4223 if (uid == 0 || !Process.supportsProcesses()) {
4224 return true;
4225 }
4226 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4227 if (perms == null) return false;
4228 UriPermission perm = perms.get(uri);
4229 if (perm == null) return false;
4230 return (modeFlags&perm.modeFlags) == modeFlags;
4231 }
4232
4233 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4234 // Another redirected-binder-call permissions check as in
4235 // {@link checkComponentPermission}.
4236 Identity tlsIdentity = sCallerIdentity.get();
4237 if (tlsIdentity != null) {
4238 uid = tlsIdentity.uid;
4239 pid = tlsIdentity.pid;
4240 }
4241
4242 // Our own process gets to do everything.
4243 if (pid == MY_PID) {
4244 return PackageManager.PERMISSION_GRANTED;
4245 }
4246 synchronized(this) {
4247 return checkUriPermissionLocked(uri, uid, modeFlags)
4248 ? PackageManager.PERMISSION_GRANTED
4249 : PackageManager.PERMISSION_DENIED;
4250 }
4251 }
4252
Dianne Hackborn39792d22010-08-19 18:01:52 -07004253 /**
4254 * Check if the targetPkg can be granted permission to access uri by
4255 * the callingUid using the given modeFlags. Throws a security exception
4256 * if callingUid is not allowed to do this. Returns the uid of the target
4257 * if the URI permission grant should be performed; returns -1 if it is not
4258 * needed (for example targetPkg already has permission to access the URI).
4259 */
4260 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4261 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004262 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4263 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4264 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004265 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004266 }
4267
Joe Onorato8a9b2202010-02-26 18:56:32 -08004268 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004269 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004270
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004271 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272
4273 // If this is not a content: uri, we can't do anything with it.
4274 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004275 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004276 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004277 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 }
4279
4280 String name = uri.getAuthority();
4281 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004282 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 if (cpr != null) {
4284 pi = cpr.info;
4285 } else {
4286 try {
4287 pi = pm.resolveContentProvider(name,
4288 PackageManager.GET_URI_PERMISSION_PATTERNS);
4289 } catch (RemoteException ex) {
4290 }
4291 }
4292 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004293 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004294 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 }
4296
4297 int targetUid;
4298 try {
4299 targetUid = pm.getPackageUid(targetPkg);
4300 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004301 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004302 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004303 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 }
4305 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004306 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 }
4308
4309 // First... does the target actually need this permission?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004310 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004312 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004313 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004314 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004315 }
4316
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004317 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 if (!pi.grantUriPermissions) {
4319 throw new SecurityException("Provider " + pi.packageName
4320 + "/" + pi.name
4321 + " does not allow granting of Uri permissions (uri "
4322 + uri + ")");
4323 }
4324 if (pi.uriPermissionPatterns != null) {
4325 final int N = pi.uriPermissionPatterns.length;
4326 boolean allowed = false;
4327 for (int i=0; i<N; i++) {
4328 if (pi.uriPermissionPatterns[i] != null
4329 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4330 allowed = true;
4331 break;
4332 }
4333 }
4334 if (!allowed) {
4335 throw new SecurityException("Provider " + pi.packageName
4336 + "/" + pi.name
4337 + " does not allow granting of permission to path of Uri "
4338 + uri);
4339 }
4340 }
4341
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004342 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 // this uri?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004344 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4346 throw new SecurityException("Uid " + callingUid
4347 + " does not have permission to uri " + uri);
4348 }
4349 }
4350
Dianne Hackborn39792d22010-08-19 18:01:52 -07004351 return targetUid;
4352 }
4353
4354 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4355 Uri uri, int modeFlags, UriPermissionOwner owner) {
4356 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4357 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4358 if (modeFlags == 0) {
4359 return;
4360 }
4361
4362 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 // to the uri, and the target doesn't. Let's now give this to
4364 // the target.
4365
Joe Onorato8a9b2202010-02-26 18:56:32 -08004366 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004367 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369 HashMap<Uri, UriPermission> targetUris
4370 = mGrantedUriPermissions.get(targetUid);
4371 if (targetUris == null) {
4372 targetUris = new HashMap<Uri, UriPermission>();
4373 mGrantedUriPermissions.put(targetUid, targetUris);
4374 }
4375
4376 UriPermission perm = targetUris.get(uri);
4377 if (perm == null) {
4378 perm = new UriPermission(targetUid, uri);
4379 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004382 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004383 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 perm.globalModeFlags |= modeFlags;
4385 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004386 perm.readOwners.add(owner);
4387 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004388 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004389 perm.writeOwners.add(owner);
4390 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 }
4392 }
4393
Dianne Hackborn39792d22010-08-19 18:01:52 -07004394 void grantUriPermissionLocked(int callingUid,
4395 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4396 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4397 if (targetUid < 0) {
4398 return;
4399 }
4400
4401 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4402 }
4403
4404 /**
4405 * Like checkGrantUriPermissionLocked, but takes an Intent.
4406 */
4407 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4408 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004409 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004410 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004411 + " from " + intent + "; flags=0x"
4412 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004415 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 }
4417 Uri data = intent.getData();
4418 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004419 return -1;
4420 }
4421 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4422 intent.getFlags());
4423 }
4424
4425 /**
4426 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4427 */
4428 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4429 String targetPkg, Intent intent, UriPermissionOwner owner) {
4430 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4431 intent.getFlags(), owner);
4432 }
4433
4434 void grantUriPermissionFromIntentLocked(int callingUid,
4435 String targetPkg, Intent intent, UriPermissionOwner owner) {
4436 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4437 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004438 return;
4439 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004440
4441 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442 }
4443
4444 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4445 Uri uri, int modeFlags) {
4446 synchronized(this) {
4447 final ProcessRecord r = getRecordForAppLocked(caller);
4448 if (r == null) {
4449 throw new SecurityException("Unable to find app for caller "
4450 + caller
4451 + " when granting permission to uri " + uri);
4452 }
4453 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004454 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 }
4456 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004457 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 }
4459
4460 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4461 null);
4462 }
4463 }
4464
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004465 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4467 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4468 HashMap<Uri, UriPermission> perms
4469 = mGrantedUriPermissions.get(perm.uid);
4470 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004471 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004472 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 perms.remove(perm.uri);
4474 if (perms.size() == 0) {
4475 mGrantedUriPermissions.remove(perm.uid);
4476 }
4477 }
4478 }
4479 }
4480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004481 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4482 int modeFlags) {
4483 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4484 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4485 if (modeFlags == 0) {
4486 return;
4487 }
4488
Joe Onorato8a9b2202010-02-26 18:56:32 -08004489 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004490 "Revoking all granted permissions to " + uri);
4491
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004492 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493
4494 final String authority = uri.getAuthority();
4495 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004496 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 if (cpr != null) {
4498 pi = cpr.info;
4499 } else {
4500 try {
4501 pi = pm.resolveContentProvider(authority,
4502 PackageManager.GET_URI_PERMISSION_PATTERNS);
4503 } catch (RemoteException ex) {
4504 }
4505 }
4506 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004507 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 return;
4509 }
4510
4511 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004512 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 // Right now, if you are not the original owner of the permission,
4514 // you are not allowed to revoke it.
4515 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4516 throw new SecurityException("Uid " + callingUid
4517 + " does not have permission to uri " + uri);
4518 //}
4519 }
4520
4521 // Go through all of the permissions and remove any that match.
4522 final List<String> SEGMENTS = uri.getPathSegments();
4523 if (SEGMENTS != null) {
4524 final int NS = SEGMENTS.size();
4525 int N = mGrantedUriPermissions.size();
4526 for (int i=0; i<N; i++) {
4527 HashMap<Uri, UriPermission> perms
4528 = mGrantedUriPermissions.valueAt(i);
4529 Iterator<UriPermission> it = perms.values().iterator();
4530 toploop:
4531 while (it.hasNext()) {
4532 UriPermission perm = it.next();
4533 Uri targetUri = perm.uri;
4534 if (!authority.equals(targetUri.getAuthority())) {
4535 continue;
4536 }
4537 List<String> targetSegments = targetUri.getPathSegments();
4538 if (targetSegments == null) {
4539 continue;
4540 }
4541 if (targetSegments.size() < NS) {
4542 continue;
4543 }
4544 for (int j=0; j<NS; j++) {
4545 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4546 continue toploop;
4547 }
4548 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004549 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004550 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 perm.clearModes(modeFlags);
4552 if (perm.modeFlags == 0) {
4553 it.remove();
4554 }
4555 }
4556 if (perms.size() == 0) {
4557 mGrantedUriPermissions.remove(
4558 mGrantedUriPermissions.keyAt(i));
4559 N--;
4560 i--;
4561 }
4562 }
4563 }
4564 }
4565
4566 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4567 int modeFlags) {
4568 synchronized(this) {
4569 final ProcessRecord r = getRecordForAppLocked(caller);
4570 if (r == null) {
4571 throw new SecurityException("Unable to find app for caller "
4572 + caller
4573 + " when revoking permission to uri " + uri);
4574 }
4575 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004576 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004577 return;
4578 }
4579
4580 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4581 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4582 if (modeFlags == 0) {
4583 return;
4584 }
4585
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004586 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587
4588 final String authority = uri.getAuthority();
4589 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004590 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 if (cpr != null) {
4592 pi = cpr.info;
4593 } else {
4594 try {
4595 pi = pm.resolveContentProvider(authority,
4596 PackageManager.GET_URI_PERMISSION_PATTERNS);
4597 } catch (RemoteException ex) {
4598 }
4599 }
4600 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004601 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 return;
4603 }
4604
4605 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4606 }
4607 }
4608
Dianne Hackborn7e269642010-08-25 19:50:20 -07004609 @Override
4610 public IBinder newUriPermissionOwner(String name) {
4611 synchronized(this) {
4612 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4613 return owner.getExternalTokenLocked();
4614 }
4615 }
4616
4617 @Override
4618 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4619 Uri uri, int modeFlags) {
4620 synchronized(this) {
4621 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4622 if (owner == null) {
4623 throw new IllegalArgumentException("Unknown owner: " + token);
4624 }
4625 if (fromUid != Binder.getCallingUid()) {
4626 if (Binder.getCallingUid() != Process.myUid()) {
4627 // Only system code can grant URI permissions on behalf
4628 // of other users.
4629 throw new SecurityException("nice try");
4630 }
4631 }
4632 if (targetPkg == null) {
4633 throw new IllegalArgumentException("null target");
4634 }
4635 if (uri == null) {
4636 throw new IllegalArgumentException("null uri");
4637 }
4638
4639 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4640 }
4641 }
4642
4643 @Override
4644 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4645 synchronized(this) {
4646 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4647 if (owner == null) {
4648 throw new IllegalArgumentException("Unknown owner: " + token);
4649 }
4650
4651 if (uri == null) {
4652 owner.removeUriPermissionsLocked(mode);
4653 } else {
4654 owner.removeUriPermissionLocked(uri, mode);
4655 }
4656 }
4657 }
4658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4660 synchronized (this) {
4661 ProcessRecord app =
4662 who != null ? getRecordForAppLocked(who) : null;
4663 if (app == null) return;
4664
4665 Message msg = Message.obtain();
4666 msg.what = WAIT_FOR_DEBUGGER_MSG;
4667 msg.obj = app;
4668 msg.arg1 = waiting ? 1 : 0;
4669 mHandler.sendMessage(msg);
4670 }
4671 }
4672
4673 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4674 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004675 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004676 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004677 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 }
4679
4680 // =========================================================
4681 // TASK MANAGEMENT
4682 // =========================================================
4683
4684 public List getTasks(int maxNum, int flags,
4685 IThumbnailReceiver receiver) {
4686 ArrayList list = new ArrayList();
4687
4688 PendingThumbnailsRecord pending = null;
4689 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004690 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691
4692 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004693 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4695 + ", receiver=" + receiver);
4696
4697 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4698 != PackageManager.PERMISSION_GRANTED) {
4699 if (receiver != null) {
4700 // If the caller wants to wait for pending thumbnails,
4701 // it ain't gonna get them.
4702 try {
4703 receiver.finished();
4704 } catch (RemoteException ex) {
4705 }
4706 }
4707 String msg = "Permission Denial: getTasks() from pid="
4708 + Binder.getCallingPid()
4709 + ", uid=" + Binder.getCallingUid()
4710 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004711 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 throw new SecurityException(msg);
4713 }
4714
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004715 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004716 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004717 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004718 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719 CharSequence topDescription = null;
4720 TaskRecord curTask = null;
4721 int numActivities = 0;
4722 int numRunning = 0;
4723 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004724 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004726 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727
4728 // Initialize state for next task if needed.
4729 if (top == null ||
4730 (top.state == ActivityState.INITIALIZING
4731 && top.task == r.task)) {
4732 top = r;
4733 topDescription = r.description;
4734 curTask = r.task;
4735 numActivities = numRunning = 0;
4736 }
4737
4738 // Add 'r' into the current task.
4739 numActivities++;
4740 if (r.app != null && r.app.thread != null) {
4741 numRunning++;
4742 }
4743 if (topDescription == null) {
4744 topDescription = r.description;
4745 }
4746
Joe Onorato8a9b2202010-02-26 18:56:32 -08004747 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004748 TAG, r.intent.getComponent().flattenToShortString()
4749 + ": task=" + r.task);
4750
4751 // If the next one is a different task, generate a new
4752 // TaskInfo entry for what we have.
4753 if (next == null || next.task != curTask) {
4754 ActivityManager.RunningTaskInfo ci
4755 = new ActivityManager.RunningTaskInfo();
4756 ci.id = curTask.taskId;
4757 ci.baseActivity = r.intent.getComponent();
4758 ci.topActivity = top.intent.getComponent();
4759 ci.thumbnail = top.thumbnail;
4760 ci.description = topDescription;
4761 ci.numActivities = numActivities;
4762 ci.numRunning = numRunning;
4763 //System.out.println(
4764 // "#" + maxNum + ": " + " descr=" + ci.description);
4765 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004766 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 TAG, "State=" + top.state + "Idle=" + top.idle
4768 + " app=" + top.app
4769 + " thr=" + (top.app != null ? top.app.thread : null));
4770 if (top.state == ActivityState.RESUMED
4771 || top.state == ActivityState.PAUSING) {
4772 if (top.idle && top.app != null
4773 && top.app.thread != null) {
4774 topRecord = top;
4775 topThumbnail = top.app.thread;
4776 } else {
4777 top.thumbnailNeeded = true;
4778 }
4779 }
4780 if (pending == null) {
4781 pending = new PendingThumbnailsRecord(receiver);
4782 }
4783 pending.pendingRecords.add(top);
4784 }
4785 list.add(ci);
4786 maxNum--;
4787 top = null;
4788 }
4789 }
4790
4791 if (pending != null) {
4792 mPendingThumbnails.add(pending);
4793 }
4794 }
4795
Joe Onorato8a9b2202010-02-26 18:56:32 -08004796 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797
4798 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004799 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004800 try {
4801 topThumbnail.requestThumbnail(topRecord);
4802 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004803 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004804 sendPendingThumbnail(null, topRecord, null, null, true);
4805 }
4806 }
4807
4808 if (pending == null && receiver != null) {
4809 // In this case all thumbnails were available and the client
4810 // is being asked to be told when the remaining ones come in...
4811 // which is unusually, since the top-most currently running
4812 // activity should never have a canned thumbnail! Oh well.
4813 try {
4814 receiver.finished();
4815 } catch (RemoteException ex) {
4816 }
4817 }
4818
4819 return list;
4820 }
4821
4822 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4823 int flags) {
4824 synchronized (this) {
4825 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4826 "getRecentTasks()");
4827
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004828 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 final int N = mRecentTasks.size();
4831 ArrayList<ActivityManager.RecentTaskInfo> res
4832 = new ArrayList<ActivityManager.RecentTaskInfo>(
4833 maxNum < N ? maxNum : N);
4834 for (int i=0; i<N && maxNum > 0; i++) {
4835 TaskRecord tr = mRecentTasks.get(i);
4836 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4837 || (tr.intent == null)
4838 || ((tr.intent.getFlags()
4839 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4840 ActivityManager.RecentTaskInfo rti
4841 = new ActivityManager.RecentTaskInfo();
4842 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4843 rti.baseIntent = new Intent(
4844 tr.intent != null ? tr.intent : tr.affinityIntent);
4845 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004846
4847 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4848 // Check whether this activity is currently available.
4849 try {
4850 if (rti.origActivity != null) {
4851 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4852 continue;
4853 }
4854 } else if (rti.baseIntent != null) {
4855 if (pm.queryIntentActivities(rti.baseIntent,
4856 null, 0) == null) {
4857 continue;
4858 }
4859 }
4860 } catch (RemoteException e) {
4861 // Will never happen.
4862 }
4863 }
4864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 res.add(rti);
4866 maxNum--;
4867 }
4868 }
4869 return res;
4870 }
4871 }
4872
4873 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4874 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004875 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 TaskRecord jt = startTask;
4877
4878 // First look backwards
4879 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004880 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 if (r.task != jt) {
4882 jt = r.task;
4883 if (affinity.equals(jt.affinity)) {
4884 return j;
4885 }
4886 }
4887 }
4888
4889 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004890 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 jt = startTask;
4892 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004893 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004894 if (r.task != jt) {
4895 if (affinity.equals(jt.affinity)) {
4896 return j;
4897 }
4898 jt = r.task;
4899 }
4900 }
4901
4902 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004903 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 return N-1;
4905 }
4906
4907 return -1;
4908 }
4909
4910 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004911 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 */
4913 public void moveTaskToFront(int task) {
4914 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4915 "moveTaskToFront()");
4916
4917 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004918 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4919 Binder.getCallingUid(), "Task to front")) {
4920 return;
4921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 final long origId = Binder.clearCallingIdentity();
4923 try {
4924 int N = mRecentTasks.size();
4925 for (int i=0; i<N; i++) {
4926 TaskRecord tr = mRecentTasks.get(i);
4927 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004928 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 return;
4930 }
4931 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004932 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4933 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004934 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004935 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 return;
4937 }
4938 }
4939 } finally {
4940 Binder.restoreCallingIdentity(origId);
4941 }
4942 }
4943 }
4944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 public void moveTaskToBack(int task) {
4946 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4947 "moveTaskToBack()");
4948
4949 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004950 if (mMainStack.mResumedActivity != null
4951 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004952 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4953 Binder.getCallingUid(), "Task to back")) {
4954 return;
4955 }
4956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004958 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 Binder.restoreCallingIdentity(origId);
4960 }
4961 }
4962
4963 /**
4964 * Moves an activity, and all of the other activities within the same task, to the bottom
4965 * of the history stack. The activity's order within the task is unchanged.
4966 *
4967 * @param token A reference to the activity we wish to move
4968 * @param nonRoot If false then this only works if the activity is the root
4969 * of a task; if true it will work for any activity in a task.
4970 * @return Returns true if the move completed, false if not.
4971 */
4972 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4973 synchronized(this) {
4974 final long origId = Binder.clearCallingIdentity();
4975 int taskId = getTaskForActivityLocked(token, !nonRoot);
4976 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004977 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978 }
4979 Binder.restoreCallingIdentity(origId);
4980 }
4981 return false;
4982 }
4983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 public void moveTaskBackwards(int task) {
4985 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4986 "moveTaskBackwards()");
4987
4988 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004989 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4990 Binder.getCallingUid(), "Task backwards")) {
4991 return;
4992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 final long origId = Binder.clearCallingIdentity();
4994 moveTaskBackwardsLocked(task);
4995 Binder.restoreCallingIdentity(origId);
4996 }
4997 }
4998
4999 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005000 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 }
5002
5003 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5004 synchronized(this) {
5005 return getTaskForActivityLocked(token, onlyRoot);
5006 }
5007 }
5008
5009 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005010 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005011 TaskRecord lastTask = null;
5012 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005013 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 if (r == token) {
5015 if (!onlyRoot || lastTask != r.task) {
5016 return r.task.taskId;
5017 }
5018 return -1;
5019 }
5020 lastTask = r.task;
5021 }
5022
5023 return -1;
5024 }
5025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 public void finishOtherInstances(IBinder token, ComponentName className) {
5027 synchronized(this) {
5028 final long origId = Binder.clearCallingIdentity();
5029
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005030 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005031 TaskRecord lastTask = null;
5032 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005033 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 if (r.realActivity.equals(className)
5035 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005036 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 null, "others")) {
5038 i--;
5039 N--;
5040 }
5041 }
5042 lastTask = r.task;
5043 }
5044
5045 Binder.restoreCallingIdentity(origId);
5046 }
5047 }
5048
5049 // =========================================================
5050 // THUMBNAILS
5051 // =========================================================
5052
5053 public void reportThumbnail(IBinder token,
5054 Bitmap thumbnail, CharSequence description) {
5055 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5056 final long origId = Binder.clearCallingIdentity();
5057 sendPendingThumbnail(null, token, thumbnail, description, true);
5058 Binder.restoreCallingIdentity(origId);
5059 }
5060
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005061 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 Bitmap thumbnail, CharSequence description, boolean always) {
5063 TaskRecord task = null;
5064 ArrayList receivers = null;
5065
5066 //System.out.println("Send pending thumbnail: " + r);
5067
5068 synchronized(this) {
5069 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005070 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 if (index < 0) {
5072 return;
5073 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005074 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005075 }
5076 if (thumbnail == null) {
5077 thumbnail = r.thumbnail;
5078 description = r.description;
5079 }
5080 if (thumbnail == null && !always) {
5081 // If there is no thumbnail, and this entry is not actually
5082 // going away, then abort for now and pick up the next
5083 // thumbnail we get.
5084 return;
5085 }
5086 task = r.task;
5087
5088 int N = mPendingThumbnails.size();
5089 int i=0;
5090 while (i<N) {
5091 PendingThumbnailsRecord pr =
5092 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5093 //System.out.println("Looking in " + pr.pendingRecords);
5094 if (pr.pendingRecords.remove(r)) {
5095 if (receivers == null) {
5096 receivers = new ArrayList();
5097 }
5098 receivers.add(pr);
5099 if (pr.pendingRecords.size() == 0) {
5100 pr.finished = true;
5101 mPendingThumbnails.remove(i);
5102 N--;
5103 continue;
5104 }
5105 }
5106 i++;
5107 }
5108 }
5109
5110 if (receivers != null) {
5111 final int N = receivers.size();
5112 for (int i=0; i<N; i++) {
5113 try {
5114 PendingThumbnailsRecord pr =
5115 (PendingThumbnailsRecord)receivers.get(i);
5116 pr.receiver.newThumbnail(
5117 task != null ? task.taskId : -1, thumbnail, description);
5118 if (pr.finished) {
5119 pr.receiver.finished();
5120 }
5121 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005122 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005123 }
5124 }
5125 }
5126 }
5127
5128 // =========================================================
5129 // CONTENT PROVIDERS
5130 // =========================================================
5131
5132 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5133 List providers = null;
5134 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005135 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005136 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005137 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 } catch (RemoteException ex) {
5139 }
5140 if (providers != null) {
5141 final int N = providers.size();
5142 for (int i=0; i<N; i++) {
5143 ProviderInfo cpi =
5144 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005145 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 if (cpr == null) {
5147 cpr = new ContentProviderRecord(cpi, app.info);
5148 mProvidersByClass.put(cpi.name, cpr);
5149 }
5150 app.pubProviders.put(cpi.name, cpr);
5151 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005152 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 }
5154 }
5155 return providers;
5156 }
5157
5158 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005159 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5161 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5162 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5163 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005164 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 return null;
5166 }
5167 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5168 cpi.exported ? -1 : cpi.applicationInfo.uid)
5169 == PackageManager.PERMISSION_GRANTED) {
5170 return null;
5171 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005172
5173 PathPermission[] pps = cpi.pathPermissions;
5174 if (pps != null) {
5175 int i = pps.length;
5176 while (i > 0) {
5177 i--;
5178 PathPermission pp = pps[i];
5179 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5180 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005181 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005182 return null;
5183 }
5184 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5185 cpi.exported ? -1 : cpi.applicationInfo.uid)
5186 == PackageManager.PERMISSION_GRANTED) {
5187 return null;
5188 }
5189 }
5190 }
5191
Dianne Hackbornb424b632010-08-18 15:59:05 -07005192 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5193 if (perms != null) {
5194 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5195 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5196 return null;
5197 }
5198 }
5199 }
5200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 String msg = "Permission Denial: opening provider " + cpi.name
5202 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5203 + ", uid=" + callingUid + ") requires "
5204 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005205 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 return msg;
5207 }
5208
5209 private final ContentProviderHolder getContentProviderImpl(
5210 IApplicationThread caller, String name) {
5211 ContentProviderRecord cpr;
5212 ProviderInfo cpi = null;
5213
5214 synchronized(this) {
5215 ProcessRecord r = null;
5216 if (caller != null) {
5217 r = getRecordForAppLocked(caller);
5218 if (r == null) {
5219 throw new SecurityException(
5220 "Unable to find app for caller " + caller
5221 + " (pid=" + Binder.getCallingPid()
5222 + ") when getting content provider " + name);
5223 }
5224 }
5225
5226 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005227 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 if (cpr != null) {
5229 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005230 String msg;
5231 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5232 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 }
5234
5235 if (r != null && cpr.canRunHere(r)) {
5236 // This provider has been published or is in the process
5237 // of being published... but it is also allowed to run
5238 // in the caller's process, so don't make a connection
5239 // and just let the caller instantiate its own instance.
5240 if (cpr.provider != null) {
5241 // don't give caller the provider object, it needs
5242 // to make its own.
5243 cpr = new ContentProviderRecord(cpr);
5244 }
5245 return cpr;
5246 }
5247
5248 final long origId = Binder.clearCallingIdentity();
5249
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005250 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005251 // return it right away.
5252 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005253 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005254 "Adding provider requested by "
5255 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005256 + cpr.info.processName);
5257 Integer cnt = r.conProviders.get(cpr);
5258 if (cnt == null) {
5259 r.conProviders.put(cpr, new Integer(1));
5260 } else {
5261 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005264 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5265 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005266 // make sure to count it as being accessed and thus
5267 // back up on the LRU list. This is good because
5268 // content providers are often expensive to start.
5269 updateLruProcessLocked(cpr.app, false, true);
5270 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005271 } else {
5272 cpr.externals++;
5273 }
5274
5275 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 updateOomAdjLocked(cpr.app);
5277 }
5278
5279 Binder.restoreCallingIdentity(origId);
5280
5281 } else {
5282 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005283 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005284 resolveContentProvider(name,
5285 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 } catch (RemoteException ex) {
5287 }
5288 if (cpi == null) {
5289 return null;
5290 }
5291
Dianne Hackbornb424b632010-08-18 15:59:05 -07005292 String msg;
5293 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5294 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 }
5296
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005297 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005298 && !cpi.processName.equals("system")) {
5299 // If this content provider does not run in the system
5300 // process, and the system is not yet ready to run other
5301 // processes, then fail fast instead of hanging.
5302 throw new IllegalArgumentException(
5303 "Attempt to launch content provider before system ready");
5304 }
5305
Dianne Hackborn860755f2010-06-03 18:47:52 -07005306 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 final boolean firstClass = cpr == null;
5308 if (firstClass) {
5309 try {
5310 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005311 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 getApplicationInfo(
5313 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005314 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005315 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005316 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 + cpi.name);
5318 return null;
5319 }
5320 cpr = new ContentProviderRecord(cpi, ai);
5321 } catch (RemoteException ex) {
5322 // pm is in same process, this will never happen.
5323 }
5324 }
5325
5326 if (r != null && cpr.canRunHere(r)) {
5327 // If this is a multiprocess provider, then just return its
5328 // info and allow the caller to instantiate it. Only do
5329 // this if the provider is the same user as the caller's
5330 // process, or can run as root (so can be in any process).
5331 return cpr;
5332 }
5333
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005334 if (DEBUG_PROVIDER) {
5335 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005336 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005337 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 }
5339
5340 // This is single process, and our app is now connecting to it.
5341 // See if we are already in the process of launching this
5342 // provider.
5343 final int N = mLaunchingProviders.size();
5344 int i;
5345 for (i=0; i<N; i++) {
5346 if (mLaunchingProviders.get(i) == cpr) {
5347 break;
5348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 }
5350
5351 // If the provider is not already being launched, then get it
5352 // started.
5353 if (i >= N) {
5354 final long origId = Binder.clearCallingIdentity();
5355 ProcessRecord proc = startProcessLocked(cpi.processName,
5356 cpr.appInfo, false, 0, "content provider",
5357 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005358 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005359 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005360 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005361 + cpi.applicationInfo.packageName + "/"
5362 + cpi.applicationInfo.uid + " for provider "
5363 + name + ": process is bad");
5364 return null;
5365 }
5366 cpr.launchingApp = proc;
5367 mLaunchingProviders.add(cpr);
5368 Binder.restoreCallingIdentity(origId);
5369 }
5370
5371 // Make sure the provider is published (the same provider class
5372 // may be published under multiple names).
5373 if (firstClass) {
5374 mProvidersByClass.put(cpi.name, cpr);
5375 }
5376 mProvidersByName.put(name, cpr);
5377
5378 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005379 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005380 "Adding provider requested by "
5381 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005382 + cpr.info.processName);
5383 Integer cnt = r.conProviders.get(cpr);
5384 if (cnt == null) {
5385 r.conProviders.put(cpr, new Integer(1));
5386 } else {
5387 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005389 cpr.clients.add(r);
5390 } else {
5391 cpr.externals++;
5392 }
5393 }
5394 }
5395
5396 // Wait for the provider to be published...
5397 synchronized (cpr) {
5398 while (cpr.provider == null) {
5399 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005400 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 + cpi.applicationInfo.packageName + "/"
5402 + cpi.applicationInfo.uid + " for provider "
5403 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005404 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005405 cpi.applicationInfo.packageName,
5406 cpi.applicationInfo.uid, name);
5407 return null;
5408 }
5409 try {
5410 cpr.wait();
5411 } catch (InterruptedException ex) {
5412 }
5413 }
5414 }
5415 return cpr;
5416 }
5417
5418 public final ContentProviderHolder getContentProvider(
5419 IApplicationThread caller, String name) {
5420 if (caller == null) {
5421 String msg = "null IApplicationThread when getting content provider "
5422 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005423 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 throw new SecurityException(msg);
5425 }
5426
5427 return getContentProviderImpl(caller, name);
5428 }
5429
5430 private ContentProviderHolder getContentProviderExternal(String name) {
5431 return getContentProviderImpl(null, name);
5432 }
5433
5434 /**
5435 * Drop a content provider from a ProcessRecord's bookkeeping
5436 * @param cpr
5437 */
5438 public void removeContentProvider(IApplicationThread caller, String name) {
5439 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005440 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005441 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005442 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005443 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005444 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445 return;
5446 }
5447 final ProcessRecord r = getRecordForAppLocked(caller);
5448 if (r == null) {
5449 throw new SecurityException(
5450 "Unable to find app for caller " + caller +
5451 " when removing content provider " + name);
5452 }
5453 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005454 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005455 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005456 + r.info.processName + " from process "
5457 + localCpr.appInfo.processName);
5458 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005460 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005461 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 return;
5463 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005464 Integer cnt = r.conProviders.get(localCpr);
5465 if (cnt == null || cnt.intValue() <= 1) {
5466 localCpr.clients.remove(r);
5467 r.conProviders.remove(localCpr);
5468 } else {
5469 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005471 }
5472 updateOomAdjLocked();
5473 }
5474 }
5475
5476 private void removeContentProviderExternal(String name) {
5477 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005478 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 if(cpr == null) {
5480 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005481 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005482 return;
5483 }
5484
5485 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005486 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 localCpr.externals--;
5488 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005489 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 }
5491 updateOomAdjLocked();
5492 }
5493 }
5494
5495 public final void publishContentProviders(IApplicationThread caller,
5496 List<ContentProviderHolder> providers) {
5497 if (providers == null) {
5498 return;
5499 }
5500
5501 synchronized(this) {
5502 final ProcessRecord r = getRecordForAppLocked(caller);
5503 if (r == null) {
5504 throw new SecurityException(
5505 "Unable to find app for caller " + caller
5506 + " (pid=" + Binder.getCallingPid()
5507 + ") when publishing content providers");
5508 }
5509
5510 final long origId = Binder.clearCallingIdentity();
5511
5512 final int N = providers.size();
5513 for (int i=0; i<N; i++) {
5514 ContentProviderHolder src = providers.get(i);
5515 if (src == null || src.info == null || src.provider == null) {
5516 continue;
5517 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005518 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 if (dst != null) {
5520 mProvidersByClass.put(dst.info.name, dst);
5521 String names[] = dst.info.authority.split(";");
5522 for (int j = 0; j < names.length; j++) {
5523 mProvidersByName.put(names[j], dst);
5524 }
5525
5526 int NL = mLaunchingProviders.size();
5527 int j;
5528 for (j=0; j<NL; j++) {
5529 if (mLaunchingProviders.get(j) == dst) {
5530 mLaunchingProviders.remove(j);
5531 j--;
5532 NL--;
5533 }
5534 }
5535 synchronized (dst) {
5536 dst.provider = src.provider;
5537 dst.app = r;
5538 dst.notifyAll();
5539 }
5540 updateOomAdjLocked(r);
5541 }
5542 }
5543
5544 Binder.restoreCallingIdentity(origId);
5545 }
5546 }
5547
5548 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005549 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005550 synchronized (mSelf) {
5551 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5552 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005553 if (providers != null) {
5554 for (int i=providers.size()-1; i>=0; i--) {
5555 ProviderInfo pi = (ProviderInfo)providers.get(i);
5556 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5557 Slog.w(TAG, "Not installing system proc provider " + pi.name
5558 + ": not system .apk");
5559 providers.remove(i);
5560 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005561 }
5562 }
5563 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005564 if (providers != null) {
5565 mSystemThread.installSystemProviders(providers);
5566 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 }
5568
Dianne Hackborn8313fc72010-09-26 18:34:53 -07005569 /**
5570 * Allows app to retrieve the MIME type of a URI without having permission
5571 * to access its content provider.
5572 *
5573 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5574 *
5575 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5576 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5577 */
5578 public String getProviderMimeType(Uri uri) {
5579 final String name = uri.getAuthority();
5580 final long ident = Binder.clearCallingIdentity();
5581 ContentProviderHolder holder = null;
5582
5583 try {
5584 holder = getContentProviderExternal(name);
5585 if (holder != null) {
5586 return holder.provider.getType(uri);
5587 }
5588 } catch (RemoteException e) {
5589 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5590 return null;
5591 } finally {
5592 if (holder != null) {
5593 removeContentProviderExternal(name);
5594 }
5595 Binder.restoreCallingIdentity(ident);
5596 }
5597
5598 return null;
5599 }
5600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005601 // =========================================================
5602 // GLOBAL MANAGEMENT
5603 // =========================================================
5604
5605 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5606 ApplicationInfo info, String customProcess) {
5607 String proc = customProcess != null ? customProcess : info.processName;
5608 BatteryStatsImpl.Uid.Proc ps = null;
5609 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5610 synchronized (stats) {
5611 ps = stats.getProcessStatsLocked(info.uid, proc);
5612 }
5613 return new ProcessRecord(ps, thread, info, proc);
5614 }
5615
5616 final ProcessRecord addAppLocked(ApplicationInfo info) {
5617 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5618
5619 if (app == null) {
5620 app = newProcessRecordLocked(null, info, null);
5621 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005622 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 }
5624
5625 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5626 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5627 app.persistent = true;
5628 app.maxAdj = CORE_SERVER_ADJ;
5629 }
5630 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5631 mPersistentStartingProcesses.add(app);
5632 startProcessLocked(app, "added application", app.processName);
5633 }
5634
5635 return app;
5636 }
5637
5638 public void unhandledBack() {
5639 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5640 "unhandledBack()");
5641
5642 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005643 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005644 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 TAG, "Performing unhandledBack(): stack size = " + count);
5646 if (count > 1) {
5647 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005648 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005649 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5650 Binder.restoreCallingIdentity(origId);
5651 }
5652 }
5653 }
5654
5655 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5656 String name = uri.getAuthority();
5657 ContentProviderHolder cph = getContentProviderExternal(name);
5658 ParcelFileDescriptor pfd = null;
5659 if (cph != null) {
5660 // We record the binder invoker's uid in thread-local storage before
5661 // going to the content provider to open the file. Later, in the code
5662 // that handles all permissions checks, we look for this uid and use
5663 // that rather than the Activity Manager's own uid. The effect is that
5664 // we do the check against the caller's permissions even though it looks
5665 // to the content provider like the Activity Manager itself is making
5666 // the request.
5667 sCallerIdentity.set(new Identity(
5668 Binder.getCallingPid(), Binder.getCallingUid()));
5669 try {
5670 pfd = cph.provider.openFile(uri, "r");
5671 } catch (FileNotFoundException e) {
5672 // do nothing; pfd will be returned null
5673 } finally {
5674 // Ensure that whatever happens, we clean up the identity state
5675 sCallerIdentity.remove();
5676 }
5677
5678 // We've got the fd now, so we're done with the provider.
5679 removeContentProviderExternal(name);
5680 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005681 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005682 }
5683 return pfd;
5684 }
5685
5686 public void goingToSleep() {
5687 synchronized(this) {
5688 mSleeping = true;
5689 mWindowManager.setEventDispatching(false);
5690
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005691 if (mMainStack.mResumedActivity != null) {
5692 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005693 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005694 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005695 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005696
5697 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005698 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005699 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5700 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005701 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005702 }
5703 }
5704
Dianne Hackborn55280a92009-05-07 15:53:46 -07005705 public boolean shutdown(int timeout) {
5706 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5707 != PackageManager.PERMISSION_GRANTED) {
5708 throw new SecurityException("Requires permission "
5709 + android.Manifest.permission.SHUTDOWN);
5710 }
5711
5712 boolean timedout = false;
5713
5714 synchronized(this) {
5715 mShuttingDown = true;
5716 mWindowManager.setEventDispatching(false);
5717
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005718 if (mMainStack.mResumedActivity != null) {
5719 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005720 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005721 while (mMainStack.mResumedActivity != null
5722 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005723 long delay = endTime - System.currentTimeMillis();
5724 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005725 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005726 timedout = true;
5727 break;
5728 }
5729 try {
5730 this.wait();
5731 } catch (InterruptedException e) {
5732 }
5733 }
5734 }
5735 }
5736
5737 mUsageStatsService.shutdown();
5738 mBatteryStatsService.shutdown();
5739
5740 return timedout;
5741 }
5742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 public void wakingUp() {
5744 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005745 if (mMainStack.mGoingToSleep.isHeld()) {
5746 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005747 }
5748 mWindowManager.setEventDispatching(true);
5749 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005750 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005751 }
5752 }
5753
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005754 public void stopAppSwitches() {
5755 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5756 != PackageManager.PERMISSION_GRANTED) {
5757 throw new SecurityException("Requires permission "
5758 + android.Manifest.permission.STOP_APP_SWITCHES);
5759 }
5760
5761 synchronized(this) {
5762 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5763 + APP_SWITCH_DELAY_TIME;
5764 mDidAppSwitch = false;
5765 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5766 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5767 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5768 }
5769 }
5770
5771 public void resumeAppSwitches() {
5772 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5773 != PackageManager.PERMISSION_GRANTED) {
5774 throw new SecurityException("Requires permission "
5775 + android.Manifest.permission.STOP_APP_SWITCHES);
5776 }
5777
5778 synchronized(this) {
5779 // Note that we don't execute any pending app switches... we will
5780 // let those wait until either the timeout, or the next start
5781 // activity request.
5782 mAppSwitchesAllowedTime = 0;
5783 }
5784 }
5785
5786 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5787 String name) {
5788 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5789 return true;
5790 }
5791
5792 final int perm = checkComponentPermission(
5793 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5794 callingUid, -1);
5795 if (perm == PackageManager.PERMISSION_GRANTED) {
5796 return true;
5797 }
5798
Joe Onorato8a9b2202010-02-26 18:56:32 -08005799 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005800 return false;
5801 }
5802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005803 public void setDebugApp(String packageName, boolean waitForDebugger,
5804 boolean persistent) {
5805 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5806 "setDebugApp()");
5807
5808 // Note that this is not really thread safe if there are multiple
5809 // callers into it at the same time, but that's not a situation we
5810 // care about.
5811 if (persistent) {
5812 final ContentResolver resolver = mContext.getContentResolver();
5813 Settings.System.putString(
5814 resolver, Settings.System.DEBUG_APP,
5815 packageName);
5816 Settings.System.putInt(
5817 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5818 waitForDebugger ? 1 : 0);
5819 }
5820
5821 synchronized (this) {
5822 if (!persistent) {
5823 mOrigDebugApp = mDebugApp;
5824 mOrigWaitForDebugger = mWaitForDebugger;
5825 }
5826 mDebugApp = packageName;
5827 mWaitForDebugger = waitForDebugger;
5828 mDebugTransient = !persistent;
5829 if (packageName != null) {
5830 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005831 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 Binder.restoreCallingIdentity(origId);
5833 }
5834 }
5835 }
5836
5837 public void setAlwaysFinish(boolean enabled) {
5838 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5839 "setAlwaysFinish()");
5840
5841 Settings.System.putInt(
5842 mContext.getContentResolver(),
5843 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5844
5845 synchronized (this) {
5846 mAlwaysFinishActivities = enabled;
5847 }
5848 }
5849
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005850 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005852 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005854 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005855 }
5856 }
5857
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005858 public boolean isUserAMonkey() {
5859 // For now the fact that there is a controller implies
5860 // we have a monkey.
5861 synchronized (this) {
5862 return mController != null;
5863 }
5864 }
5865
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005866 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005867 synchronized (this) {
5868 mWatchers.register(watcher);
5869 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005870 }
5871
5872 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005873 synchronized (this) {
5874 mWatchers.unregister(watcher);
5875 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005876 }
5877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 public final void enterSafeMode() {
5879 synchronized(this) {
5880 // It only makes sense to do this before the system is ready
5881 // and started launching other packages.
5882 if (!mSystemReady) {
5883 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005884 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 } catch (RemoteException e) {
5886 }
5887
5888 View v = LayoutInflater.from(mContext).inflate(
5889 com.android.internal.R.layout.safe_mode, null);
5890 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5891 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5892 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5893 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5894 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5895 lp.format = v.getBackground().getOpacity();
5896 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5897 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5898 ((WindowManager)mContext.getSystemService(
5899 Context.WINDOW_SERVICE)).addView(v, lp);
5900 }
5901 }
5902 }
5903
5904 public void noteWakeupAlarm(IIntentSender sender) {
5905 if (!(sender instanceof PendingIntentRecord)) {
5906 return;
5907 }
5908 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5909 synchronized (stats) {
5910 if (mBatteryStatsService.isOnBattery()) {
5911 mBatteryStatsService.enforceCallingPermission();
5912 PendingIntentRecord rec = (PendingIntentRecord)sender;
5913 int MY_UID = Binder.getCallingUid();
5914 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5915 BatteryStatsImpl.Uid.Pkg pkg =
5916 stats.getPackageStatsLocked(uid, rec.key.packageName);
5917 pkg.incWakeupsLocked();
5918 }
5919 }
5920 }
5921
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005922 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005923 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005924 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005925 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005926 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005927 // XXX Note: don't acquire main activity lock here, because the window
5928 // manager calls in with its locks held.
5929
5930 boolean killed = false;
5931 synchronized (mPidsSelfLocked) {
5932 int[] types = new int[pids.length];
5933 int worstType = 0;
5934 for (int i=0; i<pids.length; i++) {
5935 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5936 if (proc != null) {
5937 int type = proc.setAdj;
5938 types[i] = type;
5939 if (type > worstType) {
5940 worstType = type;
5941 }
5942 }
5943 }
5944
5945 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5946 // then constrain it so we will kill all hidden procs.
5947 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5948 worstType = HIDDEN_APP_MIN_ADJ;
5949 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005950 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005951 for (int i=0; i<pids.length; i++) {
5952 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5953 if (proc == null) {
5954 continue;
5955 }
5956 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005957 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005958 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005959 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5960 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005961 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005962 proc.killedBackground = true;
5963 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 }
5965 }
5966 }
5967 return killed;
5968 }
5969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 public final void startRunning(String pkg, String cls, String action,
5971 String data) {
5972 synchronized(this) {
5973 if (mStartRunning) {
5974 return;
5975 }
5976 mStartRunning = true;
5977 mTopComponent = pkg != null && cls != null
5978 ? new ComponentName(pkg, cls) : null;
5979 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5980 mTopData = data;
5981 if (!mSystemReady) {
5982 return;
5983 }
5984 }
5985
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005986 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 }
5988
5989 private void retrieveSettings() {
5990 final ContentResolver resolver = mContext.getContentResolver();
5991 String debugApp = Settings.System.getString(
5992 resolver, Settings.System.DEBUG_APP);
5993 boolean waitForDebugger = Settings.System.getInt(
5994 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5995 boolean alwaysFinishActivities = Settings.System.getInt(
5996 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5997
5998 Configuration configuration = new Configuration();
5999 Settings.System.getConfiguration(resolver, configuration);
6000
6001 synchronized (this) {
6002 mDebugApp = mOrigDebugApp = debugApp;
6003 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6004 mAlwaysFinishActivities = alwaysFinishActivities;
6005 // This happens before any activities are started, so we can
6006 // change mConfiguration in-place.
6007 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006008 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006009 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006010 }
6011 }
6012
6013 public boolean testIsSystemReady() {
6014 // no need to synchronize(this) just to read & return the value
6015 return mSystemReady;
6016 }
6017
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006018 private static File getCalledPreBootReceiversFile() {
6019 File dataDir = Environment.getDataDirectory();
6020 File systemDir = new File(dataDir, "system");
6021 File fname = new File(systemDir, "called_pre_boots.dat");
6022 return fname;
6023 }
6024
6025 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6026 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6027 File file = getCalledPreBootReceiversFile();
6028 FileInputStream fis = null;
6029 try {
6030 fis = new FileInputStream(file);
6031 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6032 int vers = dis.readInt();
6033 String codename = dis.readUTF();
6034 if (vers == android.os.Build.VERSION.SDK_INT
6035 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6036 int num = dis.readInt();
6037 while (num > 0) {
6038 num--;
6039 String pkg = dis.readUTF();
6040 String cls = dis.readUTF();
6041 lastDoneReceivers.add(new ComponentName(pkg, cls));
6042 }
6043 }
6044 } catch (FileNotFoundException e) {
6045 } catch (IOException e) {
6046 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6047 } finally {
6048 if (fis != null) {
6049 try {
6050 fis.close();
6051 } catch (IOException e) {
6052 }
6053 }
6054 }
6055 return lastDoneReceivers;
6056 }
6057
6058 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6059 File file = getCalledPreBootReceiversFile();
6060 FileOutputStream fos = null;
6061 DataOutputStream dos = null;
6062 try {
6063 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6064 fos = new FileOutputStream(file);
6065 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6066 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6067 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6068 dos.writeInt(list.size());
6069 for (int i=0; i<list.size(); i++) {
6070 dos.writeUTF(list.get(i).getPackageName());
6071 dos.writeUTF(list.get(i).getClassName());
6072 }
6073 } catch (IOException e) {
6074 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6075 file.delete();
6076 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006077 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006078 if (dos != null) {
6079 try {
6080 dos.close();
6081 } catch (IOException e) {
6082 // TODO Auto-generated catch block
6083 e.printStackTrace();
6084 }
6085 }
6086 }
6087 }
6088
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006089 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 // In the simulator, startRunning will never have been called, which
6091 // normally sets a few crucial variables. Do it here instead.
6092 if (!Process.supportsProcesses()) {
6093 mStartRunning = true;
6094 mTopAction = Intent.ACTION_MAIN;
6095 }
6096
6097 synchronized(this) {
6098 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006099 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 return;
6101 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006102
6103 // Check to see if there are any update receivers to run.
6104 if (!mDidUpdate) {
6105 if (mWaitingUpdate) {
6106 return;
6107 }
6108 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6109 List<ResolveInfo> ris = null;
6110 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006111 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006112 intent, null, 0);
6113 } catch (RemoteException e) {
6114 }
6115 if (ris != null) {
6116 for (int i=ris.size()-1; i>=0; i--) {
6117 if ((ris.get(i).activityInfo.applicationInfo.flags
6118 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6119 ris.remove(i);
6120 }
6121 }
6122 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006123
6124 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6125
6126 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006127 for (int i=0; i<ris.size(); i++) {
6128 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006129 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6130 if (lastDoneReceivers.contains(comp)) {
6131 ris.remove(i);
6132 i--;
6133 }
6134 }
6135
6136 for (int i=0; i<ris.size(); i++) {
6137 ActivityInfo ai = ris.get(i).activityInfo;
6138 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6139 doneReceivers.add(comp);
6140 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006141 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006142 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006143 finisher = new IIntentReceiver.Stub() {
6144 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006145 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006146 boolean sticky) {
6147 // The raw IIntentReceiver interface is called
6148 // with the AM lock held, so redispatch to
6149 // execute our code without the lock.
6150 mHandler.post(new Runnable() {
6151 public void run() {
6152 synchronized (ActivityManagerService.this) {
6153 mDidUpdate = true;
6154 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006155 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006156 systemReady(goingCallback);
6157 }
6158 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006159 }
6160 };
6161 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006162 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006163 broadcastIntentLocked(null, null, intent, null, finisher,
6164 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006165 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006166 mWaitingUpdate = true;
6167 }
6168 }
6169 }
6170 if (mWaitingUpdate) {
6171 return;
6172 }
6173 mDidUpdate = true;
6174 }
6175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006176 mSystemReady = true;
6177 if (!mStartRunning) {
6178 return;
6179 }
6180 }
6181
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006182 ArrayList<ProcessRecord> procsToKill = null;
6183 synchronized(mPidsSelfLocked) {
6184 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6185 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6186 if (!isAllowedWhileBooting(proc.info)){
6187 if (procsToKill == null) {
6188 procsToKill = new ArrayList<ProcessRecord>();
6189 }
6190 procsToKill.add(proc);
6191 }
6192 }
6193 }
6194
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006195 synchronized(this) {
6196 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006197 for (int i=procsToKill.size()-1; i>=0; i--) {
6198 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006199 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006200 removeProcessLocked(proc, true);
6201 }
6202 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006203
6204 // Now that we have cleaned up any update processes, we
6205 // are ready to start launching real processes and know that
6206 // we won't trample on them any more.
6207 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006208 }
6209
Joe Onorato8a9b2202010-02-26 18:56:32 -08006210 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006211 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212 SystemClock.uptimeMillis());
6213
6214 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006215 // Make sure we have no pre-ready processes sitting around.
6216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006217 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6218 ResolveInfo ri = mContext.getPackageManager()
6219 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006220 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006221 CharSequence errorMsg = null;
6222 if (ri != null) {
6223 ActivityInfo ai = ri.activityInfo;
6224 ApplicationInfo app = ai.applicationInfo;
6225 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6226 mTopAction = Intent.ACTION_FACTORY_TEST;
6227 mTopData = null;
6228 mTopComponent = new ComponentName(app.packageName,
6229 ai.name);
6230 } else {
6231 errorMsg = mContext.getResources().getText(
6232 com.android.internal.R.string.factorytest_not_system);
6233 }
6234 } else {
6235 errorMsg = mContext.getResources().getText(
6236 com.android.internal.R.string.factorytest_no_action);
6237 }
6238 if (errorMsg != null) {
6239 mTopAction = null;
6240 mTopData = null;
6241 mTopComponent = null;
6242 Message msg = Message.obtain();
6243 msg.what = SHOW_FACTORY_ERROR_MSG;
6244 msg.getData().putCharSequence("msg", errorMsg);
6245 mHandler.sendMessage(msg);
6246 }
6247 }
6248 }
6249
6250 retrieveSettings();
6251
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006252 if (goingCallback != null) goingCallback.run();
6253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006254 synchronized (this) {
6255 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6256 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006257 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006258 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 if (apps != null) {
6260 int N = apps.size();
6261 int i;
6262 for (i=0; i<N; i++) {
6263 ApplicationInfo info
6264 = (ApplicationInfo)apps.get(i);
6265 if (info != null &&
6266 !info.packageName.equals("android")) {
6267 addAppLocked(info);
6268 }
6269 }
6270 }
6271 } catch (RemoteException ex) {
6272 // pm is in same process, this will never happen.
6273 }
6274 }
6275
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006276 // Start up initial activity.
6277 mBooting = true;
6278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006279 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006280 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006281 Message msg = Message.obtain();
6282 msg.what = SHOW_UID_ERROR_MSG;
6283 mHandler.sendMessage(msg);
6284 }
6285 } catch (RemoteException e) {
6286 }
6287
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006288 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 }
6290 }
6291
Dan Egnorb7f03672009-12-09 16:22:32 -08006292 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006293 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006294 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006295 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006296 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006297 startAppProblemLocked(app);
6298 app.stopFreezingAllLocked();
6299 return handleAppCrashLocked(app);
6300 }
6301
Dan Egnorb7f03672009-12-09 16:22:32 -08006302 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006303 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006305 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006306 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6307 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006308 startAppProblemLocked(app);
6309 app.stopFreezingAllLocked();
6310 }
6311
6312 /**
6313 * Generate a process error record, suitable for attachment to a ProcessRecord.
6314 *
6315 * @param app The ProcessRecord in which the error occurred.
6316 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6317 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006318 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006319 * @param shortMsg Short message describing the crash.
6320 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006321 * @param stackTrace Full crash stack trace, may be null.
6322 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006323 * @return Returns a fully-formed AppErrorStateInfo record.
6324 */
6325 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006326 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 report.condition = condition;
6330 report.processName = app.processName;
6331 report.pid = app.pid;
6332 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006333 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 report.shortMsg = shortMsg;
6335 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006336 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006337
6338 return report;
6339 }
6340
Dan Egnor42471dd2010-01-07 17:25:22 -08006341 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 synchronized (this) {
6343 app.crashing = false;
6344 app.crashingReport = null;
6345 app.notResponding = false;
6346 app.notRespondingReport = null;
6347 if (app.anrDialog == fromDialog) {
6348 app.anrDialog = null;
6349 }
6350 if (app.waitDialog == fromDialog) {
6351 app.waitDialog = null;
6352 }
6353 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006354 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006355 Slog.i(ActivityManagerService.TAG, "Killing "
6356 + app.processName + " (pid=" + app.pid + "): user's request");
6357 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6358 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359 Process.killProcess(app.pid);
6360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006361 }
6362 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006363
Dan Egnorb7f03672009-12-09 16:22:32 -08006364 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 long now = SystemClock.uptimeMillis();
6366
6367 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6368 app.info.uid);
6369 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6370 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006371 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006373 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 app.info.processName, app.info.uid);
6375 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006376 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6377 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006379 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006381 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382 }
6383 }
6384 if (!app.persistent) {
6385 // We don't want to start this process again until the user
6386 // explicitly does so... but for persistent process, we really
6387 // need to keep it running. If a persistent process is actually
6388 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006389 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006390 app.info.processName);
6391 mBadProcesses.put(app.info.processName, app.info.uid, now);
6392 app.bad = true;
6393 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6394 app.removed = true;
6395 removeProcessLocked(app, false);
6396 return false;
6397 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006398 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006399 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006400 if (r.app == app) {
6401 // If the top running activity is from this crashing
6402 // process, then terminate it to avoid getting in a loop.
6403 Slog.w(TAG, " Force finishing activity "
6404 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006405 int index = mMainStack.indexOfTokenLocked(r);
6406 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006407 Activity.RESULT_CANCELED, null, "crashed");
6408 // Also terminate an activities below it that aren't yet
6409 // stopped, to avoid a situation where one will get
6410 // re-start our crashing activity once it gets resumed again.
6411 index--;
6412 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006413 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006414 if (r.state == ActivityState.RESUMED
6415 || r.state == ActivityState.PAUSING
6416 || r.state == ActivityState.PAUSED) {
6417 if (!r.isHomeActivity) {
6418 Slog.w(TAG, " Force finishing activity "
6419 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006420 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006421 Activity.RESULT_CANCELED, null, "crashed");
6422 }
6423 }
6424 }
6425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006426 }
6427
6428 // Bump up the crash count of any services currently running in the proc.
6429 if (app.services.size() != 0) {
6430 // Any services running in the application need to be placed
6431 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006432 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006434 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006435 sr.crashCount++;
6436 }
6437 }
6438
6439 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6440 return true;
6441 }
6442
6443 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006444 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6445 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 skipCurrentReceiverLocked(app);
6447 }
6448
6449 void skipCurrentReceiverLocked(ProcessRecord app) {
6450 boolean reschedule = false;
6451 BroadcastRecord r = app.curReceiver;
6452 if (r != null) {
6453 // The current broadcast is waiting for this app's receiver
6454 // to be finished. Looks like that's not going to happen, so
6455 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006456 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006457 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6458 r.resultExtras, r.resultAbort, true);
6459 reschedule = true;
6460 }
6461 r = mPendingBroadcast;
6462 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006463 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006464 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006465 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6467 r.resultExtras, r.resultAbort, true);
6468 reschedule = true;
6469 }
6470 if (reschedule) {
6471 scheduleBroadcastsLocked();
6472 }
6473 }
6474
Dan Egnor60d87622009-12-16 16:32:58 -08006475 /**
6476 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6477 * The application process will exit immediately after this call returns.
6478 * @param app object of the crashing app, null for the system server
6479 * @param crashInfo describing the exception
6480 */
6481 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6482 ProcessRecord r = findAppProcess(app);
6483
6484 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6485 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006486 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006487 crashInfo.exceptionClassName,
6488 crashInfo.exceptionMessage,
6489 crashInfo.throwFileName,
6490 crashInfo.throwLineNumber);
6491
Dan Egnor42471dd2010-01-07 17:25:22 -08006492 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006493
6494 crashApplication(r, crashInfo);
6495 }
6496
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006497 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006498 IBinder app,
6499 int violationMask,
6500 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006501 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006502
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006503 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006504 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006505 boolean logIt = true;
6506 synchronized (mAlreadyLoggedViolatedStacks) {
6507 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6508 logIt = false;
6509 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006510 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006511 // the relative pain numbers, without logging all
6512 // the stack traces repeatedly. We'd want to do
6513 // likewise in the client code, which also does
6514 // dup suppression, before the Binder call.
6515 } else {
6516 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6517 mAlreadyLoggedViolatedStacks.clear();
6518 }
6519 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6520 }
6521 }
6522 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006523 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006524 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006525 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006526
6527 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6528 AppErrorResult result = new AppErrorResult();
6529 synchronized (this) {
6530 final long origId = Binder.clearCallingIdentity();
6531
6532 Message msg = Message.obtain();
6533 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6534 HashMap<String, Object> data = new HashMap<String, Object>();
6535 data.put("result", result);
6536 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006537 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006538 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006539 msg.obj = data;
6540 mHandler.sendMessage(msg);
6541
6542 Binder.restoreCallingIdentity(origId);
6543 }
6544 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006545 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006546 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006547 }
6548
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006549 // Depending on the policy in effect, there could be a bunch of
6550 // these in quick succession so we try to batch these together to
6551 // minimize disk writes, number of dropbox entries, and maximize
6552 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006553 private void logStrictModeViolationToDropBox(
6554 ProcessRecord process,
6555 StrictMode.ViolationInfo info) {
6556 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006557 return;
6558 }
6559 final boolean isSystemApp = process == null ||
6560 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6561 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6562 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6563 final DropBoxManager dbox = (DropBoxManager)
6564 mContext.getSystemService(Context.DROPBOX_SERVICE);
6565
6566 // Exit early if the dropbox isn't configured to accept this report type.
6567 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6568
6569 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006570 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006571 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6572 synchronized (sb) {
6573 bufferWasEmpty = sb.length() == 0;
6574 appendDropBoxProcessHeaders(process, sb);
6575 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6576 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006577 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6578 if (info.violationNumThisLoop != 0) {
6579 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6580 }
6581 if (info != null && info.durationMillis != -1) {
6582 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006583 }
6584 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006585 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6586 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006587 }
6588 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006589
6590 // Only buffer up to ~64k. Various logging bits truncate
6591 // things at 128k.
6592 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006593 }
6594
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006595 // Flush immediately if the buffer's grown too large, or this
6596 // is a non-system app. Non-system apps are isolated with a
6597 // different tag & policy and not batched.
6598 //
6599 // Batching is useful during internal testing with
6600 // StrictMode settings turned up high. Without batching,
6601 // thousands of separate files could be created on boot.
6602 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006603 new Thread("Error dump: " + dropboxTag) {
6604 @Override
6605 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006606 String report;
6607 synchronized (sb) {
6608 report = sb.toString();
6609 sb.delete(0, sb.length());
6610 sb.trimToSize();
6611 }
6612 if (report.length() != 0) {
6613 dbox.addText(dropboxTag, report);
6614 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006615 }
6616 }.start();
6617 return;
6618 }
6619
6620 // System app batching:
6621 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006622 // An existing dropbox-writing thread is outstanding, so
6623 // we don't need to start it up. The existing thread will
6624 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006625 return;
6626 }
6627
6628 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6629 // (After this point, we shouldn't access AMS internal data structures.)
6630 new Thread("Error dump: " + dropboxTag) {
6631 @Override
6632 public void run() {
6633 // 5 second sleep to let stacks arrive and be batched together
6634 try {
6635 Thread.sleep(5000); // 5 seconds
6636 } catch (InterruptedException e) {}
6637
6638 String errorReport;
6639 synchronized (mStrictModeBuffer) {
6640 errorReport = mStrictModeBuffer.toString();
6641 if (errorReport.length() == 0) {
6642 return;
6643 }
6644 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6645 mStrictModeBuffer.trimToSize();
6646 }
6647 dbox.addText(dropboxTag, errorReport);
6648 }
6649 }.start();
6650 }
6651
Dan Egnor60d87622009-12-16 16:32:58 -08006652 /**
6653 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6654 * @param app object of the crashing app, null for the system server
6655 * @param tag reported by the caller
6656 * @param crashInfo describing the context of the error
6657 * @return true if the process should exit immediately (WTF is fatal)
6658 */
6659 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006660 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006661 ProcessRecord r = findAppProcess(app);
6662
6663 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6664 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006665 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006666 tag, crashInfo.exceptionMessage);
6667
Dan Egnor42471dd2010-01-07 17:25:22 -08006668 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006669
Doug Zongker43866e02010-01-07 12:09:54 -08006670 if (Settings.Secure.getInt(mContext.getContentResolver(),
6671 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006672 crashApplication(r, crashInfo);
6673 return true;
6674 } else {
6675 return false;
6676 }
6677 }
6678
6679 /**
6680 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6681 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6682 */
6683 private ProcessRecord findAppProcess(IBinder app) {
6684 if (app == null) {
6685 return null;
6686 }
6687
6688 synchronized (this) {
6689 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6690 final int NA = apps.size();
6691 for (int ia=0; ia<NA; ia++) {
6692 ProcessRecord p = apps.valueAt(ia);
6693 if (p.thread != null && p.thread.asBinder() == app) {
6694 return p;
6695 }
6696 }
6697 }
6698
Joe Onorato8a9b2202010-02-26 18:56:32 -08006699 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006700 return null;
6701 }
6702 }
6703
6704 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006705 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6706 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006707 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006708 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6709 // Note: ProcessRecord 'process' is guarded by the service
6710 // instance. (notably process.pkgList, which could otherwise change
6711 // concurrently during execution of this method)
6712 synchronized (this) {
6713 if (process == null || process.pid == MY_PID) {
6714 sb.append("Process: system_server\n");
6715 } else {
6716 sb.append("Process: ").append(process.processName).append("\n");
6717 }
6718 if (process == null) {
6719 return;
6720 }
Dan Egnora455d192010-03-12 08:52:28 -08006721 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006722 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006723 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6724 for (String pkg : process.pkgList) {
6725 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006726 try {
Dan Egnora455d192010-03-12 08:52:28 -08006727 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6728 if (pi != null) {
6729 sb.append(" v").append(pi.versionCode);
6730 if (pi.versionName != null) {
6731 sb.append(" (").append(pi.versionName).append(")");
6732 }
6733 }
6734 } catch (RemoteException e) {
6735 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006736 }
Dan Egnora455d192010-03-12 08:52:28 -08006737 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006738 }
Dan Egnora455d192010-03-12 08:52:28 -08006739 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006740 }
6741
6742 private static String processClass(ProcessRecord process) {
6743 if (process == null || process.pid == MY_PID) {
6744 return "system_server";
6745 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6746 return "system_app";
6747 } else {
6748 return "data_app";
6749 }
6750 }
6751
6752 /**
6753 * Write a description of an error (crash, WTF, ANR) to the drop box.
6754 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6755 * @param process which caused the error, null means the system server
6756 * @param activity which triggered the error, null if unknown
6757 * @param parent activity related to the error, null if unknown
6758 * @param subject line related to the error, null if absent
6759 * @param report in long form describing the error, null if absent
6760 * @param logFile to include in the report, null if none
6761 * @param crashInfo giving an application stack trace, null if absent
6762 */
6763 public void addErrorToDropBox(String eventType,
6764 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6765 final String report, final File logFile,
6766 final ApplicationErrorReport.CrashInfo crashInfo) {
6767 // NOTE -- this must never acquire the ActivityManagerService lock,
6768 // otherwise the watchdog may be prevented from resetting the system.
6769
6770 final String dropboxTag = processClass(process) + "_" + eventType;
6771 final DropBoxManager dbox = (DropBoxManager)
6772 mContext.getSystemService(Context.DROPBOX_SERVICE);
6773
6774 // Exit early if the dropbox isn't configured to accept this report type.
6775 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6776
6777 final StringBuilder sb = new StringBuilder(1024);
6778 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006779 if (activity != null) {
6780 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6781 }
6782 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6783 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6784 }
6785 if (parent != null && parent != activity) {
6786 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6787 }
6788 if (subject != null) {
6789 sb.append("Subject: ").append(subject).append("\n");
6790 }
6791 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6792 sb.append("\n");
6793
6794 // Do the rest in a worker thread to avoid blocking the caller on I/O
6795 // (After this point, we shouldn't access AMS internal data structures.)
6796 Thread worker = new Thread("Error dump: " + dropboxTag) {
6797 @Override
6798 public void run() {
6799 if (report != null) {
6800 sb.append(report);
6801 }
6802 if (logFile != null) {
6803 try {
6804 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6805 } catch (IOException e) {
6806 Slog.e(TAG, "Error reading " + logFile, e);
6807 }
6808 }
6809 if (crashInfo != null && crashInfo.stackTrace != null) {
6810 sb.append(crashInfo.stackTrace);
6811 }
6812
6813 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6814 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6815 if (lines > 0) {
6816 sb.append("\n");
6817
6818 // Merge several logcat streams, and take the last N lines
6819 InputStreamReader input = null;
6820 try {
6821 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6822 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6823 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6824
6825 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6826 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6827 input = new InputStreamReader(logcat.getInputStream());
6828
6829 int num;
6830 char[] buf = new char[8192];
6831 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6832 } catch (IOException e) {
6833 Slog.e(TAG, "Error running logcat", e);
6834 } finally {
6835 if (input != null) try { input.close(); } catch (IOException e) {}
6836 }
6837 }
6838
6839 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006840 }
Dan Egnora455d192010-03-12 08:52:28 -08006841 };
6842
6843 if (process == null || process.pid == MY_PID) {
6844 worker.run(); // We may be about to die -- need to run this synchronously
6845 } else {
6846 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006847 }
6848 }
6849
6850 /**
6851 * Bring up the "unexpected error" dialog box for a crashing app.
6852 * Deal with edge cases (intercepts from instrumented applications,
6853 * ActivityController, error intent receivers, that sort of thing).
6854 * @param r the application crashing
6855 * @param crashInfo describing the failure
6856 */
6857 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006858 long timeMillis = System.currentTimeMillis();
6859 String shortMsg = crashInfo.exceptionClassName;
6860 String longMsg = crashInfo.exceptionMessage;
6861 String stackTrace = crashInfo.stackTrace;
6862 if (shortMsg != null && longMsg != null) {
6863 longMsg = shortMsg + ": " + longMsg;
6864 } else if (shortMsg != null) {
6865 longMsg = shortMsg;
6866 }
6867
Dan Egnor60d87622009-12-16 16:32:58 -08006868 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006869 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006870 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006871 try {
6872 String name = r != null ? r.processName : null;
6873 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006874 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006875 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006876 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006877 + " at watcher's request");
6878 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006879 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006880 }
6881 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006882 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006883 }
6884 }
6885
6886 final long origId = Binder.clearCallingIdentity();
6887
6888 // If this process is running instrumentation, finish it.
6889 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006890 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006892 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6893 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006894 Bundle info = new Bundle();
6895 info.putString("shortMsg", shortMsg);
6896 info.putString("longMsg", longMsg);
6897 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6898 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006899 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 }
6901
Dan Egnor60d87622009-12-16 16:32:58 -08006902 // If we can't identify the process or it's already exceeded its crash quota,
6903 // quit right away without showing a crash dialog.
6904 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006905 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006906 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907 }
6908
6909 Message msg = Message.obtain();
6910 msg.what = SHOW_ERROR_MSG;
6911 HashMap data = new HashMap();
6912 data.put("result", result);
6913 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914 msg.obj = data;
6915 mHandler.sendMessage(msg);
6916
6917 Binder.restoreCallingIdentity(origId);
6918 }
6919
6920 int res = result.get();
6921
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006922 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006923 synchronized (this) {
6924 if (r != null) {
6925 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6926 SystemClock.uptimeMillis());
6927 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006928 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006929 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006930 }
6931 }
6932
6933 if (appErrorIntent != null) {
6934 try {
6935 mContext.startActivity(appErrorIntent);
6936 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006937 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006940 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006941
6942 Intent createAppErrorIntentLocked(ProcessRecord r,
6943 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6944 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006945 if (report == null) {
6946 return null;
6947 }
6948 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6949 result.setComponent(r.errorReportReceiver);
6950 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6951 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6952 return result;
6953 }
6954
Dan Egnorb7f03672009-12-09 16:22:32 -08006955 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6956 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006957 if (r.errorReportReceiver == null) {
6958 return null;
6959 }
6960
6961 if (!r.crashing && !r.notResponding) {
6962 return null;
6963 }
6964
Dan Egnorb7f03672009-12-09 16:22:32 -08006965 ApplicationErrorReport report = new ApplicationErrorReport();
6966 report.packageName = r.info.packageName;
6967 report.installerPackageName = r.errorReportReceiver.getPackageName();
6968 report.processName = r.processName;
6969 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006970 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006971
Dan Egnorb7f03672009-12-09 16:22:32 -08006972 if (r.crashing) {
6973 report.type = ApplicationErrorReport.TYPE_CRASH;
6974 report.crashInfo = crashInfo;
6975 } else if (r.notResponding) {
6976 report.type = ApplicationErrorReport.TYPE_ANR;
6977 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006978
Dan Egnorb7f03672009-12-09 16:22:32 -08006979 report.anrInfo.activity = r.notRespondingReport.tag;
6980 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6981 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006982 }
6983
Dan Egnorb7f03672009-12-09 16:22:32 -08006984 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006985 }
6986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006987 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6988 // assume our apps are happy - lazy create the list
6989 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6990
6991 synchronized (this) {
6992
6993 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006994 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6995 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6997 // This one's in trouble, so we'll generate a report for it
6998 // crashes are higher priority (in case there's a crash *and* an anr)
6999 ActivityManager.ProcessErrorStateInfo report = null;
7000 if (app.crashing) {
7001 report = app.crashingReport;
7002 } else if (app.notResponding) {
7003 report = app.notRespondingReport;
7004 }
7005
7006 if (report != null) {
7007 if (errList == null) {
7008 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7009 }
7010 errList.add(report);
7011 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007012 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007013 " crashing = " + app.crashing +
7014 " notResponding = " + app.notResponding);
7015 }
7016 }
7017 }
7018 }
7019
7020 return errList;
7021 }
7022
7023 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7024 // Lazy instantiation of list
7025 List<ActivityManager.RunningAppProcessInfo> runList = null;
7026 synchronized (this) {
7027 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007028 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7029 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007030 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7031 // Generate process state info for running application
7032 ActivityManager.RunningAppProcessInfo currApp =
7033 new ActivityManager.RunningAppProcessInfo(app.processName,
7034 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007035 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007036 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007037 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007039 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007040 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007041 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7042 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7043 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007044 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7045 } else if (adj >= HOME_APP_ADJ) {
7046 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7047 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007048 } else if (adj >= SECONDARY_SERVER_ADJ) {
7049 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007050 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
7051 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
7052 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7053 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054 } else if (adj >= VISIBLE_APP_ADJ) {
7055 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7056 } else {
7057 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7058 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007059 currApp.importanceReasonCode = app.adjTypeCode;
7060 if (app.adjSource instanceof ProcessRecord) {
7061 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007062 } else if (app.adjSource instanceof ActivityRecord) {
7063 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007064 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7065 }
7066 if (app.adjTarget instanceof ComponentName) {
7067 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7068 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007069 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007070 // + " lru=" + currApp.lru);
7071 if (runList == null) {
7072 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7073 }
7074 runList.add(currApp);
7075 }
7076 }
7077 }
7078 return runList;
7079 }
7080
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007081 public List<ApplicationInfo> getRunningExternalApplications() {
7082 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7083 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7084 if (runningApps != null && runningApps.size() > 0) {
7085 Set<String> extList = new HashSet<String>();
7086 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7087 if (app.pkgList != null) {
7088 for (String pkg : app.pkgList) {
7089 extList.add(pkg);
7090 }
7091 }
7092 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007093 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007094 for (String pkg : extList) {
7095 try {
7096 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7097 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7098 retList.add(info);
7099 }
7100 } catch (RemoteException e) {
7101 }
7102 }
7103 }
7104 return retList;
7105 }
7106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007107 @Override
7108 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007109 if (checkCallingPermission(android.Manifest.permission.DUMP)
7110 != PackageManager.PERMISSION_GRANTED) {
7111 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7112 + Binder.getCallingPid()
7113 + ", uid=" + Binder.getCallingUid()
7114 + " without permission "
7115 + android.Manifest.permission.DUMP);
7116 return;
7117 }
7118
7119 boolean dumpAll = false;
7120
7121 int opti = 0;
7122 while (opti < args.length) {
7123 String opt = args[opti];
7124 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7125 break;
7126 }
7127 opti++;
7128 if ("-a".equals(opt)) {
7129 dumpAll = true;
7130 } else if ("-h".equals(opt)) {
7131 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007132 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007133 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007134 pw.println(" a[ctivities]: activity stack state");
7135 pw.println(" b[roadcasts]: broadcast state");
7136 pw.println(" i[ntents]: pending intent state");
7137 pw.println(" p[rocesses]: process state");
7138 pw.println(" o[om]: out of memory management");
7139 pw.println(" prov[iders]: content provider state");
7140 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007141 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007143 } else {
7144 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007145 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007146 }
7147
7148 // Is the caller requesting to dump a particular piece of data?
7149 if (opti < args.length) {
7150 String cmd = args[opti];
7151 opti++;
7152 if ("activities".equals(cmd) || "a".equals(cmd)) {
7153 synchronized (this) {
7154 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007155 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007156 return;
7157 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7158 synchronized (this) {
7159 dumpBroadcastsLocked(fd, pw, args, opti, true);
7160 }
7161 return;
7162 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7163 synchronized (this) {
7164 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7165 }
7166 return;
7167 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7168 synchronized (this) {
7169 dumpProcessesLocked(fd, pw, args, opti, true);
7170 }
7171 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007172 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7173 synchronized (this) {
7174 dumpOomLocked(fd, pw, args, opti, true);
7175 }
7176 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007177 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7178 synchronized (this) {
7179 dumpProvidersLocked(fd, pw, args, opti, true);
7180 }
7181 return;
7182 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007183 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007184 return;
7185 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7186 synchronized (this) {
7187 dumpServicesLocked(fd, pw, args, opti, true);
7188 }
7189 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007190 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007191 }
7192
7193 // No piece of data specified, dump everything.
7194 synchronized (this) {
7195 boolean needSep;
7196 if (dumpAll) {
7197 pw.println("Providers in Current Activity Manager State:");
7198 }
7199 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7200 if (needSep) {
7201 pw.println(" ");
7202 }
7203 if (dumpAll) {
7204 pw.println("-------------------------------------------------------------------------------");
7205 pw.println("Broadcasts in Current Activity Manager State:");
7206 }
7207 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7208 if (needSep) {
7209 pw.println(" ");
7210 }
7211 if (dumpAll) {
7212 pw.println("-------------------------------------------------------------------------------");
7213 pw.println("Services in Current Activity Manager State:");
7214 }
7215 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7216 if (needSep) {
7217 pw.println(" ");
7218 }
7219 if (dumpAll) {
7220 pw.println("-------------------------------------------------------------------------------");
7221 pw.println("PendingIntents in Current Activity Manager State:");
7222 }
7223 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7224 if (needSep) {
7225 pw.println(" ");
7226 }
7227 if (dumpAll) {
7228 pw.println("-------------------------------------------------------------------------------");
7229 pw.println("Activities in Current Activity Manager State:");
7230 }
7231 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7232 if (needSep) {
7233 pw.println(" ");
7234 }
7235 if (dumpAll) {
7236 pw.println("-------------------------------------------------------------------------------");
7237 pw.println("Processes in Current Activity Manager State:");
7238 }
7239 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7240 }
7241 }
7242
7243 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7244 int opti, boolean dumpAll, boolean needHeader) {
7245 if (needHeader) {
7246 pw.println(" Activity stack:");
7247 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007248 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007249 pw.println(" ");
7250 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007251 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7252 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007253 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007254 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007255 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007256 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007257 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007258 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007259 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007260 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007261 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007262 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007263 pw.println(" ");
7264 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007265 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007267
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007268 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007269 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7270 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007271 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007272 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007274 if (dumpAll && mRecentTasks.size() > 0) {
7275 pw.println(" ");
7276 pw.println("Recent tasks in Current Activity Manager State:");
7277
7278 final int N = mRecentTasks.size();
7279 for (int i=0; i<N; i++) {
7280 TaskRecord tr = mRecentTasks.get(i);
7281 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7282 pw.println(tr);
7283 mRecentTasks.get(i).dump(pw, " ");
7284 }
7285 }
7286
7287 pw.println(" ");
7288 pw.println(" mCurTask: " + mCurTask);
7289
7290 return true;
7291 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007292
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007293 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7294 int opti, boolean dumpAll) {
7295 boolean needSep = false;
7296 int numPers = 0;
7297
7298 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7300 final int NA = procs.size();
7301 for (int ia=0; ia<NA; ia++) {
7302 if (!needSep) {
7303 pw.println(" All known processes:");
7304 needSep = true;
7305 }
7306 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007307 pw.print(r.persistent ? " *PERS*" : " *APP*");
7308 pw.print(" UID "); pw.print(procs.keyAt(ia));
7309 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007310 r.dump(pw, " ");
7311 if (r.persistent) {
7312 numPers++;
7313 }
7314 }
7315 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007316 }
7317
7318 if (mLruProcesses.size() > 0) {
7319 if (needSep) pw.println(" ");
7320 needSep = true;
7321 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007322 dumpProcessOomList(pw, this, mLruProcesses, " ",
7323 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007324 needSep = true;
7325 }
7326
7327 synchronized (mPidsSelfLocked) {
7328 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 if (needSep) pw.println(" ");
7330 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007331 pw.println(" PID mappings:");
7332 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7333 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7334 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007335 }
7336 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007337 }
7338
7339 if (mForegroundProcesses.size() > 0) {
7340 if (needSep) pw.println(" ");
7341 needSep = true;
7342 pw.println(" Foreground Processes:");
7343 for (int i=0; i<mForegroundProcesses.size(); i++) {
7344 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7345 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007347 }
7348
7349 if (mPersistentStartingProcesses.size() > 0) {
7350 if (needSep) pw.println(" ");
7351 needSep = true;
7352 pw.println(" Persisent processes that are starting:");
7353 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007354 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007357 if (mStartingProcesses.size() > 0) {
7358 if (needSep) pw.println(" ");
7359 needSep = true;
7360 pw.println(" Processes that are starting:");
7361 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007362 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007364
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007365 if (mRemovedProcesses.size() > 0) {
7366 if (needSep) pw.println(" ");
7367 needSep = true;
7368 pw.println(" Processes that are being removed:");
7369 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007370 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007371 }
7372
7373 if (mProcessesOnHold.size() > 0) {
7374 if (needSep) pw.println(" ");
7375 needSep = true;
7376 pw.println(" Processes that are on old until the system is ready:");
7377 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007378 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007379 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380
Dianne Hackborn287952c2010-09-22 22:34:31 -07007381 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007382
7383 if (mProcessCrashTimes.getMap().size() > 0) {
7384 if (needSep) pw.println(" ");
7385 needSep = true;
7386 pw.println(" Time since processes crashed:");
7387 long now = SystemClock.uptimeMillis();
7388 for (Map.Entry<String, SparseArray<Long>> procs
7389 : mProcessCrashTimes.getMap().entrySet()) {
7390 SparseArray<Long> uids = procs.getValue();
7391 final int N = uids.size();
7392 for (int i=0; i<N; i++) {
7393 pw.print(" Process "); pw.print(procs.getKey());
7394 pw.print(" uid "); pw.print(uids.keyAt(i));
7395 pw.print(": last crashed ");
7396 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007397 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007398 }
7399 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007402 if (mBadProcesses.getMap().size() > 0) {
7403 if (needSep) pw.println(" ");
7404 needSep = true;
7405 pw.println(" Bad processes:");
7406 for (Map.Entry<String, SparseArray<Long>> procs
7407 : mBadProcesses.getMap().entrySet()) {
7408 SparseArray<Long> uids = procs.getValue();
7409 final int N = uids.size();
7410 for (int i=0; i<N; i++) {
7411 pw.print(" Bad process "); pw.print(procs.getKey());
7412 pw.print(" uid "); pw.print(uids.keyAt(i));
7413 pw.print(": crashed at time ");
7414 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007415 }
7416 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007418
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007419 pw.println(" ");
7420 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007421 if (mHeavyWeightProcess != null) {
7422 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7423 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007424 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007425 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007426 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7427 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7428 || mOrigWaitForDebugger) {
7429 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7430 + " mDebugTransient=" + mDebugTransient
7431 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7432 }
7433 if (mAlwaysFinishActivities || mController != null) {
7434 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7435 + " mController=" + mController);
7436 }
7437 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007439 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007440 + " mProcessesReady=" + mProcessesReady
7441 + " mSystemReady=" + mSystemReady);
7442 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007443 + " mBooted=" + mBooted
7444 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007445 pw.print(" mLastPowerCheckRealtime=");
7446 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7447 pw.println("");
7448 pw.print(" mLastPowerCheckUptime=");
7449 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7450 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007451 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7452 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007453 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007454 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007455
7456 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007457 }
7458
Dianne Hackborn287952c2010-09-22 22:34:31 -07007459 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7460 int opti, boolean needSep, boolean dumpAll) {
7461 if (mProcessesToGc.size() > 0) {
7462 if (needSep) pw.println(" ");
7463 needSep = true;
7464 pw.println(" Processes that are waiting to GC:");
7465 long now = SystemClock.uptimeMillis();
7466 for (int i=0; i<mProcessesToGc.size(); i++) {
7467 ProcessRecord proc = mProcessesToGc.get(i);
7468 pw.print(" Process "); pw.println(proc);
7469 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7470 pw.print(", last gced=");
7471 pw.print(now-proc.lastRequestedGc);
7472 pw.print(" ms ago, last lowMem=");
7473 pw.print(now-proc.lastLowMemory);
7474 pw.println(" ms ago");
7475
7476 }
7477 }
7478 return needSep;
7479 }
7480
7481 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7482 int opti, boolean dumpAll) {
7483 boolean needSep = false;
7484
7485 if (mLruProcesses.size() > 0) {
7486 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7487
7488 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7489 @Override
7490 public int compare(ProcessRecord object1, ProcessRecord object2) {
7491 if (object1.setAdj != object2.setAdj) {
7492 return object1.setAdj > object2.setAdj ? -1 : 1;
7493 }
7494 if (object1.setSchedGroup != object2.setSchedGroup) {
7495 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7496 }
7497 if (object1.keeping != object2.keeping) {
7498 return object1.keeping ? -1 : 1;
7499 }
7500 if (object1.pid != object2.pid) {
7501 return object1.pid > object2.pid ? -1 : 1;
7502 }
7503 return 0;
7504 }
7505 };
7506
7507 Collections.sort(procs, comparator);
7508
7509 if (needSep) pw.println(" ");
7510 needSep = true;
7511 pw.println(" Process OOM control:");
7512 dumpProcessOomList(pw, this, procs, " ",
7513 "Proc", "PERS", true);
7514 needSep = true;
7515 }
7516
7517 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7518
7519 pw.println(" ");
7520 pw.println(" mHomeProcess: " + mHomeProcess);
7521 if (mHeavyWeightProcess != null) {
7522 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7523 }
7524
7525 return true;
7526 }
7527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528 /**
7529 * There are three ways to call this:
7530 * - no service specified: dump all the services
7531 * - a flattened component name that matched an existing service was specified as the
7532 * first arg: dump that one service
7533 * - the first arg isn't the flattened component name of an existing service:
7534 * dump all services whose component contains the first arg as a substring
7535 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007536 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7537 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007538 String[] newArgs;
7539 String componentNameString;
7540 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007541 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542 componentNameString = null;
7543 newArgs = EMPTY_STRING_ARRAY;
7544 r = null;
7545 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007546 componentNameString = args[opti];
7547 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007549 synchronized (this) {
7550 r = componentName != null ? mServices.get(componentName) : null;
7551 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007552 newArgs = new String[args.length - opti];
7553 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554 }
7555
7556 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007557 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007559 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7560 synchronized (this) {
7561 for (ServiceRecord r1 : mServices.values()) {
7562 if (componentNameString == null
7563 || r1.name.flattenToString().contains(componentNameString)) {
7564 services.add(r1);
7565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007566 }
7567 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007568 for (int i=0; i<services.size(); i++) {
7569 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007571 }
7572 }
7573
7574 /**
7575 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7576 * there is a thread associated with the service.
7577 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007578 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7579 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007581 if (dumpAll) {
7582 synchronized (this) {
7583 pw.print(" * "); pw.println(r);
7584 r.dump(pw, " ");
7585 }
7586 pw.println("");
7587 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007588 if (r.app != null && r.app.thread != null) {
7589 try {
7590 // flush anything that is already in the PrintWriter since the thread is going
7591 // to write to the file descriptor directly
7592 pw.flush();
7593 r.app.thread.dumpService(fd, r, args);
7594 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007595 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007596 } catch (RemoteException e) {
7597 pw.println("got a RemoteException while dumping the service");
7598 }
7599 }
7600 }
7601
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007602 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7603 int opti, boolean dumpAll) {
7604 boolean needSep = false;
7605
7606 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007607 if (mRegisteredReceivers.size() > 0) {
7608 pw.println(" ");
7609 pw.println(" Registered Receivers:");
7610 Iterator it = mRegisteredReceivers.values().iterator();
7611 while (it.hasNext()) {
7612 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007613 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614 r.dump(pw, " ");
7615 }
7616 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 pw.println(" ");
7619 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007620 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007621 needSep = true;
7622 }
7623
7624 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7625 || mPendingBroadcast != null) {
7626 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007627 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007628 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007630 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7631 pw.println(" Broadcast #" + i + ":");
7632 mParallelBroadcasts.get(i).dump(pw, " ");
7633 }
7634 if (mOrderedBroadcasts.size() > 0) {
7635 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007636 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007637 }
7638 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7639 pw.println(" Serialized Broadcast #" + i + ":");
7640 mOrderedBroadcasts.get(i).dump(pw, " ");
7641 }
7642 pw.println(" ");
7643 pw.println(" Pending broadcast:");
7644 if (mPendingBroadcast != null) {
7645 mPendingBroadcast.dump(pw, " ");
7646 } else {
7647 pw.println(" (null)");
7648 }
7649 needSep = true;
7650 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007651
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007652 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007654 pw.println(" Historical broadcasts:");
7655 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7656 BroadcastRecord r = mBroadcastHistory[i];
7657 if (r == null) {
7658 break;
7659 }
7660 pw.println(" Historical Broadcast #" + i + ":");
7661 r.dump(pw, " ");
7662 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007663 needSep = true;
7664 }
7665
7666 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007667 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007668 pw.println(" Sticky broadcasts:");
7669 StringBuilder sb = new StringBuilder(128);
7670 for (Map.Entry<String, ArrayList<Intent>> ent
7671 : mStickyBroadcasts.entrySet()) {
7672 pw.print(" * Sticky action "); pw.print(ent.getKey());
7673 pw.println(":");
7674 ArrayList<Intent> intents = ent.getValue();
7675 final int N = intents.size();
7676 for (int i=0; i<N; i++) {
7677 sb.setLength(0);
7678 sb.append(" Intent: ");
7679 intents.get(i).toShortString(sb, true, false);
7680 pw.println(sb.toString());
7681 Bundle bundle = intents.get(i).getExtras();
7682 if (bundle != null) {
7683 pw.print(" ");
7684 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007685 }
7686 }
7687 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007688 needSep = true;
7689 }
7690
7691 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007693 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 pw.println(" mHandler:");
7695 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007696 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007698
7699 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007700 }
7701
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007702 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7703 int opti, boolean dumpAll) {
7704 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007705
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007706 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007707 if (mServices.size() > 0) {
7708 pw.println(" Active services:");
7709 Iterator<ServiceRecord> it = mServices.values().iterator();
7710 while (it.hasNext()) {
7711 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007712 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713 r.dump(pw, " ");
7714 }
7715 needSep = true;
7716 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007719 if (mPendingServices.size() > 0) {
7720 if (needSep) pw.println(" ");
7721 pw.println(" Pending services:");
7722 for (int i=0; i<mPendingServices.size(); i++) {
7723 ServiceRecord r = mPendingServices.get(i);
7724 pw.print(" * Pending "); pw.println(r);
7725 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007727 needSep = true;
7728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007730 if (mRestartingServices.size() > 0) {
7731 if (needSep) pw.println(" ");
7732 pw.println(" Restarting services:");
7733 for (int i=0; i<mRestartingServices.size(); i++) {
7734 ServiceRecord r = mRestartingServices.get(i);
7735 pw.print(" * Restarting "); pw.println(r);
7736 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007737 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007738 needSep = true;
7739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007740
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007741 if (mStoppingServices.size() > 0) {
7742 if (needSep) pw.println(" ");
7743 pw.println(" Stopping services:");
7744 for (int i=0; i<mStoppingServices.size(); i++) {
7745 ServiceRecord r = mStoppingServices.get(i);
7746 pw.print(" * Stopping "); pw.println(r);
7747 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007749 needSep = true;
7750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007752 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007753 if (mServiceConnections.size() > 0) {
7754 if (needSep) pw.println(" ");
7755 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007756 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007757 = mServiceConnections.values().iterator();
7758 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007759 ArrayList<ConnectionRecord> r = it.next();
7760 for (int i=0; i<r.size(); i++) {
7761 pw.print(" * "); pw.println(r.get(i));
7762 r.get(i).dump(pw, " ");
7763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007764 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007765 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007766 }
7767 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007768
7769 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007770 }
7771
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007772 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7773 int opti, boolean dumpAll) {
7774 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007775
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007776 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777 if (mProvidersByClass.size() > 0) {
7778 if (needSep) pw.println(" ");
7779 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007780 Iterator<Map.Entry<String, ContentProviderRecord>> it
7781 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007783 Map.Entry<String, ContentProviderRecord> e = it.next();
7784 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007785 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007786 r.dump(pw, " ");
7787 }
7788 needSep = true;
7789 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007790
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007791 if (mProvidersByName.size() > 0) {
7792 pw.println(" ");
7793 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007794 Iterator<Map.Entry<String, ContentProviderRecord>> it
7795 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007796 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007797 Map.Entry<String, ContentProviderRecord> e = it.next();
7798 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007799 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7800 pw.println(r);
7801 }
7802 needSep = true;
7803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007805
7806 if (mLaunchingProviders.size() > 0) {
7807 if (needSep) pw.println(" ");
7808 pw.println(" Launching content providers:");
7809 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7810 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7811 pw.println(mLaunchingProviders.get(i));
7812 }
7813 needSep = true;
7814 }
7815
7816 if (mGrantedUriPermissions.size() > 0) {
7817 pw.println();
7818 pw.println("Granted Uri Permissions:");
7819 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7820 int uid = mGrantedUriPermissions.keyAt(i);
7821 HashMap<Uri, UriPermission> perms
7822 = mGrantedUriPermissions.valueAt(i);
7823 pw.print(" * UID "); pw.print(uid);
7824 pw.println(" holds:");
7825 for (UriPermission perm : perms.values()) {
7826 pw.print(" "); pw.println(perm);
7827 perm.dump(pw, " ");
7828 }
7829 }
7830 needSep = true;
7831 }
7832
7833 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834 }
7835
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007836 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7837 int opti, boolean dumpAll) {
7838 boolean needSep = false;
7839
7840 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 if (this.mIntentSenderRecords.size() > 0) {
7842 Iterator<WeakReference<PendingIntentRecord>> it
7843 = mIntentSenderRecords.values().iterator();
7844 while (it.hasNext()) {
7845 WeakReference<PendingIntentRecord> ref = it.next();
7846 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007847 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007848 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007849 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007850 rec.dump(pw, " ");
7851 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007852 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 }
7854 }
7855 }
7856 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007857
7858 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007859 }
7860
7861 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007862 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 TaskRecord lastTask = null;
7864 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007865 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007866 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 if (lastTask != r.task) {
7868 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007869 pw.print(prefix);
7870 pw.print(full ? "* " : " ");
7871 pw.println(lastTask);
7872 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007873 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007874 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007875 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007876 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7877 pw.print(" #"); pw.print(i); pw.print(": ");
7878 pw.println(r);
7879 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007880 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 }
7883 }
7884
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007885 private static String buildOomTag(String prefix, String space, int val, int base) {
7886 if (val == base) {
7887 if (space == null) return prefix;
7888 return prefix + " ";
7889 }
7890 return prefix + "+" + Integer.toString(val-base);
7891 }
7892
7893 private static final int dumpProcessList(PrintWriter pw,
7894 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07007895 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007896 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007897 final int N = list.size()-1;
7898 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007899 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007900 pw.println(String.format("%s%s #%2d: %s",
7901 prefix, (r.persistent ? persistentLabel : normalLabel),
7902 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007903 if (r.persistent) {
7904 numPers++;
7905 }
7906 }
7907 return numPers;
7908 }
7909
Dianne Hackborn287952c2010-09-22 22:34:31 -07007910 private static final void dumpProcessOomList(PrintWriter pw,
7911 ActivityManagerService service, List<ProcessRecord> list,
7912 String prefix, String normalLabel, String persistentLabel,
7913 boolean inclDetails) {
7914
7915 final long curRealtime = SystemClock.elapsedRealtime();
7916 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
7917 final long curUptime = SystemClock.uptimeMillis();
7918 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
7919
7920 final int N = list.size()-1;
7921 for (int i=N; i>=0; i--) {
7922 ProcessRecord r = list.get(i);
7923 String oomAdj;
7924 if (r.setAdj >= EMPTY_APP_ADJ) {
7925 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
7926 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
7927 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7928 } else if (r.setAdj >= HOME_APP_ADJ) {
7929 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7930 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7931 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7932 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7933 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
7934 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7935 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7936 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7937 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
7938 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7939 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7940 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7941 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
7942 } else if (r.setAdj >= CORE_SERVER_ADJ) {
7943 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
7944 } else if (r.setAdj >= SYSTEM_ADJ) {
7945 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
7946 } else {
7947 oomAdj = Integer.toString(r.setAdj);
7948 }
7949 String schedGroup;
7950 switch (r.setSchedGroup) {
7951 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7952 schedGroup = "B";
7953 break;
7954 case Process.THREAD_GROUP_DEFAULT:
7955 schedGroup = "F";
7956 break;
7957 default:
7958 schedGroup = Integer.toString(r.setSchedGroup);
7959 break;
7960 }
7961 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
7962 prefix, (r.persistent ? persistentLabel : normalLabel),
7963 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
7964 if (r.adjSource != null || r.adjTarget != null) {
7965 pw.print(prefix);
7966 pw.print(" ");
7967 if (r.adjTarget instanceof ComponentName) {
7968 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7969 } else if (r.adjTarget != null) {
7970 pw.print(r.adjTarget.toString());
7971 } else {
7972 pw.print("{null}");
7973 }
7974 pw.print("<=");
7975 if (r.adjSource instanceof ProcessRecord) {
7976 pw.print("Proc{");
7977 pw.print(((ProcessRecord)r.adjSource).toShortString());
7978 pw.println("}");
7979 } else if (r.adjSource != null) {
7980 pw.println(r.adjSource.toString());
7981 } else {
7982 pw.println("{null}");
7983 }
7984 }
7985 if (inclDetails) {
7986 pw.print(prefix);
7987 pw.print(" ");
7988 pw.print("oom: max="); pw.print(r.maxAdj);
7989 pw.print(" hidden="); pw.print(r.hiddenAdj);
7990 pw.print(" curRaw="); pw.print(r.curRawAdj);
7991 pw.print(" setRaw="); pw.print(r.setRawAdj);
7992 pw.print(" cur="); pw.print(r.curAdj);
7993 pw.print(" set="); pw.println(r.setAdj);
7994 pw.print(prefix);
7995 pw.print(" ");
7996 pw.print("keeping="); pw.print(r.keeping);
7997 pw.print(" hidden="); pw.print(r.hidden);
7998 pw.print(" empty="); pw.println(r.empty);
7999
8000 if (!r.keeping) {
8001 if (r.lastWakeTime != 0) {
8002 long wtime;
8003 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8004 synchronized (stats) {
8005 wtime = stats.getProcessWakeTime(r.info.uid,
8006 r.pid, curRealtime);
8007 }
8008 long timeUsed = wtime - r.lastWakeTime;
8009 pw.print(prefix);
8010 pw.print(" ");
8011 pw.print("keep awake over ");
8012 TimeUtils.formatDuration(realtimeSince, pw);
8013 pw.print(" used ");
8014 TimeUtils.formatDuration(timeUsed, pw);
8015 pw.print(" (");
8016 pw.print((timeUsed*100)/realtimeSince);
8017 pw.println("%)");
8018 }
8019 if (r.lastCpuTime != 0) {
8020 long timeUsed = r.curCpuTime - r.lastCpuTime;
8021 pw.print(prefix);
8022 pw.print(" ");
8023 pw.print("run cpu over ");
8024 TimeUtils.formatDuration(uptimeSince, pw);
8025 pw.print(" used ");
8026 TimeUtils.formatDuration(timeUsed, pw);
8027 pw.print(" (");
8028 pw.print((timeUsed*100)/uptimeSince);
8029 pw.println("%)");
8030 }
8031 }
8032 }
8033 }
8034 }
8035
Dianne Hackborn472ad872010-04-07 17:31:48 -07008036 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008038 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008039 long uptime = SystemClock.uptimeMillis();
8040 long realtime = SystemClock.elapsedRealtime();
8041
8042 if (isCheckinRequest) {
8043 // short checkin version
8044 pw.println(uptime + "," + realtime);
8045 pw.flush();
8046 } else {
8047 pw.println("Applications Memory Usage (kB):");
8048 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8049 }
8050 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8051 ProcessRecord r = (ProcessRecord)list.get(i);
8052 if (r.thread != null) {
8053 if (!isCheckinRequest) {
8054 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8055 pw.flush();
8056 }
8057 try {
8058 r.thread.asBinder().dump(fd, args);
8059 } catch (RemoteException e) {
8060 if (!isCheckinRequest) {
8061 pw.println("Got RemoteException!");
8062 pw.flush();
8063 }
8064 }
8065 }
8066 }
8067 }
8068
8069 /**
8070 * Searches array of arguments for the specified string
8071 * @param args array of argument strings
8072 * @param value value to search for
8073 * @return true if the value is contained in the array
8074 */
8075 private static boolean scanArgs(String[] args, String value) {
8076 if (args != null) {
8077 for (String arg : args) {
8078 if (value.equals(arg)) {
8079 return true;
8080 }
8081 }
8082 }
8083 return false;
8084 }
8085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086 private final void killServicesLocked(ProcessRecord app,
8087 boolean allowRestart) {
8088 // Report disconnected services.
8089 if (false) {
8090 // XXX we are letting the client link to the service for
8091 // death notifications.
8092 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008093 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008094 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008095 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008096 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008097 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098 = r.connections.values().iterator();
8099 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008100 ArrayList<ConnectionRecord> cl = jt.next();
8101 for (int i=0; i<cl.size(); i++) {
8102 ConnectionRecord c = cl.get(i);
8103 if (c.binding.client != app) {
8104 try {
8105 //c.conn.connected(r.className, null);
8106 } catch (Exception e) {
8107 // todo: this should be asynchronous!
8108 Slog.w(TAG, "Exception thrown disconnected servce "
8109 + r.shortName
8110 + " from app " + app.processName, e);
8111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008112 }
8113 }
8114 }
8115 }
8116 }
8117 }
8118 }
8119
8120 // Clean up any connections this application has to other services.
8121 if (app.connections.size() > 0) {
8122 Iterator<ConnectionRecord> it = app.connections.iterator();
8123 while (it.hasNext()) {
8124 ConnectionRecord r = it.next();
8125 removeConnectionLocked(r, app, null);
8126 }
8127 }
8128 app.connections.clear();
8129
8130 if (app.services.size() != 0) {
8131 // Any services running in the application need to be placed
8132 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008133 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008135 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008136 synchronized (sr.stats.getBatteryStats()) {
8137 sr.stats.stopLaunchedLocked();
8138 }
8139 sr.app = null;
8140 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008141 if (mStoppingServices.remove(sr)) {
8142 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8143 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008144
8145 boolean hasClients = sr.bindings.size() > 0;
8146 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008147 Iterator<IntentBindRecord> bindings
8148 = sr.bindings.values().iterator();
8149 while (bindings.hasNext()) {
8150 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008151 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008152 + ": shouldUnbind=" + b.hasBound);
8153 b.binder = null;
8154 b.requested = b.received = b.hasBound = false;
8155 }
8156 }
8157
8158 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008159 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008160 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008161 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 sr.crashCount, sr.shortName, app.pid);
8163 bringDownServiceLocked(sr, true);
8164 } else if (!allowRestart) {
8165 bringDownServiceLocked(sr, true);
8166 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008167 boolean canceled = scheduleServiceRestartLocked(sr, true);
8168
8169 // Should the service remain running? Note that in the
8170 // extreme case of so many attempts to deliver a command
8171 // that it failed, that we also will stop it here.
8172 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8173 if (sr.pendingStarts.size() == 0) {
8174 sr.startRequested = false;
8175 if (!hasClients) {
8176 // Whoops, no reason to restart!
8177 bringDownServiceLocked(sr, true);
8178 }
8179 }
8180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008181 }
8182 }
8183
8184 if (!allowRestart) {
8185 app.services.clear();
8186 }
8187 }
8188
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008189 // Make sure we have no more records on the stopping list.
8190 int i = mStoppingServices.size();
8191 while (i > 0) {
8192 i--;
8193 ServiceRecord sr = mStoppingServices.get(i);
8194 if (sr.app == app) {
8195 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008196 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008197 }
8198 }
8199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008200 app.executingServices.clear();
8201 }
8202
8203 private final void removeDyingProviderLocked(ProcessRecord proc,
8204 ContentProviderRecord cpr) {
8205 synchronized (cpr) {
8206 cpr.launchingApp = null;
8207 cpr.notifyAll();
8208 }
8209
8210 mProvidersByClass.remove(cpr.info.name);
8211 String names[] = cpr.info.authority.split(";");
8212 for (int j = 0; j < names.length; j++) {
8213 mProvidersByName.remove(names[j]);
8214 }
8215
8216 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8217 while (cit.hasNext()) {
8218 ProcessRecord capp = cit.next();
8219 if (!capp.persistent && capp.thread != null
8220 && capp.pid != 0
8221 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008222 Slog.i(TAG, "Kill " + capp.processName
8223 + " (pid " + capp.pid + "): provider " + cpr.info.name
8224 + " in dying process " + proc.processName);
8225 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8226 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008227 Process.killProcess(capp.pid);
8228 }
8229 }
8230
8231 mLaunchingProviders.remove(cpr);
8232 }
8233
8234 /**
8235 * Main code for cleaning up a process when it has gone away. This is
8236 * called both as a result of the process dying, or directly when stopping
8237 * a process when running in single process mode.
8238 */
8239 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8240 boolean restarting, int index) {
8241 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008242 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008243 }
8244
Dianne Hackborn36124872009-10-08 16:22:03 -07008245 mProcessesToGc.remove(app);
8246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 // Dismiss any open dialogs.
8248 if (app.crashDialog != null) {
8249 app.crashDialog.dismiss();
8250 app.crashDialog = null;
8251 }
8252 if (app.anrDialog != null) {
8253 app.anrDialog.dismiss();
8254 app.anrDialog = null;
8255 }
8256 if (app.waitDialog != null) {
8257 app.waitDialog.dismiss();
8258 app.waitDialog = null;
8259 }
8260
8261 app.crashing = false;
8262 app.notResponding = false;
8263
8264 app.resetPackageList();
8265 app.thread = null;
8266 app.forcingToForeground = null;
8267 app.foregroundServices = false;
8268
8269 killServicesLocked(app, true);
8270
8271 boolean restart = false;
8272
8273 int NL = mLaunchingProviders.size();
8274
8275 // Remove published content providers.
8276 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008277 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008278 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008279 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 cpr.provider = null;
8281 cpr.app = null;
8282
8283 // See if someone is waiting for this provider... in which
8284 // case we don't remove it, but just let it restart.
8285 int i = 0;
8286 if (!app.bad) {
8287 for (; i<NL; i++) {
8288 if (mLaunchingProviders.get(i) == cpr) {
8289 restart = true;
8290 break;
8291 }
8292 }
8293 } else {
8294 i = NL;
8295 }
8296
8297 if (i >= NL) {
8298 removeDyingProviderLocked(app, cpr);
8299 NL = mLaunchingProviders.size();
8300 }
8301 }
8302 app.pubProviders.clear();
8303 }
8304
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008305 // Take care of any launching providers waiting for this process.
8306 if (checkAppInLaunchingProvidersLocked(app, false)) {
8307 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008308 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008310 // Unregister from connected content providers.
8311 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008312 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008313 while (it.hasNext()) {
8314 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8315 cpr.clients.remove(app);
8316 }
8317 app.conProviders.clear();
8318 }
8319
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008320 // At this point there may be remaining entries in mLaunchingProviders
8321 // where we were the only one waiting, so they are no longer of use.
8322 // Look for these and clean up if found.
8323 // XXX Commented out for now. Trying to figure out a way to reproduce
8324 // the actual situation to identify what is actually going on.
8325 if (false) {
8326 for (int i=0; i<NL; i++) {
8327 ContentProviderRecord cpr = (ContentProviderRecord)
8328 mLaunchingProviders.get(i);
8329 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8330 synchronized (cpr) {
8331 cpr.launchingApp = null;
8332 cpr.notifyAll();
8333 }
8334 }
8335 }
8336 }
8337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008338 skipCurrentReceiverLocked(app);
8339
8340 // Unregister any receivers.
8341 if (app.receivers.size() > 0) {
8342 Iterator<ReceiverList> it = app.receivers.iterator();
8343 while (it.hasNext()) {
8344 removeReceiverLocked(it.next());
8345 }
8346 app.receivers.clear();
8347 }
8348
Christopher Tate181fafa2009-05-14 11:12:14 -07008349 // If the app is undergoing backup, tell the backup manager about it
8350 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008351 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008352 try {
8353 IBackupManager bm = IBackupManager.Stub.asInterface(
8354 ServiceManager.getService(Context.BACKUP_SERVICE));
8355 bm.agentDisconnected(app.info.packageName);
8356 } catch (RemoteException e) {
8357 // can't happen; backup manager is local
8358 }
8359 }
8360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008361 // If the caller is restarting this app, then leave it in its
8362 // current lists and let the caller take care of it.
8363 if (restarting) {
8364 return;
8365 }
8366
8367 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008368 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008369 "Removing non-persistent process during cleanup: " + app);
8370 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008371 if (mHeavyWeightProcess == app) {
8372 mHeavyWeightProcess = null;
8373 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008375 } else if (!app.removed) {
8376 // This app is persistent, so we need to keep its record around.
8377 // If it is not already on the pending app list, add it there
8378 // and start a new process for it.
8379 app.thread = null;
8380 app.forcingToForeground = null;
8381 app.foregroundServices = false;
8382 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8383 mPersistentStartingProcesses.add(app);
8384 restart = true;
8385 }
8386 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008387 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8388 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008389 mProcessesOnHold.remove(app);
8390
The Android Open Source Project4df24232009-03-05 14:34:35 -08008391 if (app == mHomeProcess) {
8392 mHomeProcess = null;
8393 }
8394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008395 if (restart) {
8396 // We have components that still need to be running in the
8397 // process, so re-launch it.
8398 mProcessNames.put(app.processName, app.info.uid, app);
8399 startProcessLocked(app, "restart", app.processName);
8400 } else if (app.pid > 0 && app.pid != MY_PID) {
8401 // Goodbye!
8402 synchronized (mPidsSelfLocked) {
8403 mPidsSelfLocked.remove(app.pid);
8404 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8405 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008406 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 }
8408 }
8409
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008410 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8411 // Look through the content providers we are waiting to have launched,
8412 // and if any run in this process then either schedule a restart of
8413 // the process or kill the client waiting for it if this process has
8414 // gone bad.
8415 int NL = mLaunchingProviders.size();
8416 boolean restart = false;
8417 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008418 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008419 if (cpr.launchingApp == app) {
8420 if (!alwaysBad && !app.bad) {
8421 restart = true;
8422 } else {
8423 removeDyingProviderLocked(app, cpr);
8424 NL = mLaunchingProviders.size();
8425 }
8426 }
8427 }
8428 return restart;
8429 }
8430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008431 // =========================================================
8432 // SERVICES
8433 // =========================================================
8434
8435 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8436 ActivityManager.RunningServiceInfo info =
8437 new ActivityManager.RunningServiceInfo();
8438 info.service = r.name;
8439 if (r.app != null) {
8440 info.pid = r.app.pid;
8441 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008442 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 info.process = r.processName;
8444 info.foreground = r.isForeground;
8445 info.activeSince = r.createTime;
8446 info.started = r.startRequested;
8447 info.clientCount = r.connections.size();
8448 info.crashCount = r.crashCount;
8449 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008450 if (r.isForeground) {
8451 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8452 }
8453 if (r.startRequested) {
8454 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8455 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008456 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008457 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8458 }
8459 if (r.app != null && r.app.persistent) {
8460 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8461 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008462
8463 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8464 for (int i=0; i<connl.size(); i++) {
8465 ConnectionRecord conn = connl.get(i);
8466 if (conn.clientLabel != 0) {
8467 info.clientPackage = conn.binding.client.info.packageName;
8468 info.clientLabel = conn.clientLabel;
8469 return info;
8470 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008471 }
8472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008473 return info;
8474 }
8475
8476 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8477 int flags) {
8478 synchronized (this) {
8479 ArrayList<ActivityManager.RunningServiceInfo> res
8480 = new ArrayList<ActivityManager.RunningServiceInfo>();
8481
8482 if (mServices.size() > 0) {
8483 Iterator<ServiceRecord> it = mServices.values().iterator();
8484 while (it.hasNext() && res.size() < maxNum) {
8485 res.add(makeRunningServiceInfoLocked(it.next()));
8486 }
8487 }
8488
8489 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8490 ServiceRecord r = mRestartingServices.get(i);
8491 ActivityManager.RunningServiceInfo info =
8492 makeRunningServiceInfoLocked(r);
8493 info.restarting = r.nextRestartTime;
8494 res.add(info);
8495 }
8496
8497 return res;
8498 }
8499 }
8500
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008501 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8502 synchronized (this) {
8503 ServiceRecord r = mServices.get(name);
8504 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008505 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8506 for (int i=0; i<conn.size(); i++) {
8507 if (conn.get(i).clientIntent != null) {
8508 return conn.get(i).clientIntent;
8509 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008510 }
8511 }
8512 }
8513 }
8514 return null;
8515 }
8516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 private final ServiceRecord findServiceLocked(ComponentName name,
8518 IBinder token) {
8519 ServiceRecord r = mServices.get(name);
8520 return r == token ? r : null;
8521 }
8522
8523 private final class ServiceLookupResult {
8524 final ServiceRecord record;
8525 final String permission;
8526
8527 ServiceLookupResult(ServiceRecord _record, String _permission) {
8528 record = _record;
8529 permission = _permission;
8530 }
8531 };
8532
8533 private ServiceLookupResult findServiceLocked(Intent service,
8534 String resolvedType) {
8535 ServiceRecord r = null;
8536 if (service.getComponent() != null) {
8537 r = mServices.get(service.getComponent());
8538 }
8539 if (r == null) {
8540 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8541 r = mServicesByIntent.get(filter);
8542 }
8543
8544 if (r == null) {
8545 try {
8546 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008547 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 service, resolvedType, 0);
8549 ServiceInfo sInfo =
8550 rInfo != null ? rInfo.serviceInfo : null;
8551 if (sInfo == null) {
8552 return null;
8553 }
8554
8555 ComponentName name = new ComponentName(
8556 sInfo.applicationInfo.packageName, sInfo.name);
8557 r = mServices.get(name);
8558 } catch (RemoteException ex) {
8559 // pm is in same process, this will never happen.
8560 }
8561 }
8562 if (r != null) {
8563 int callingPid = Binder.getCallingPid();
8564 int callingUid = Binder.getCallingUid();
8565 if (checkComponentPermission(r.permission,
8566 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8567 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008568 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008569 + " from pid=" + callingPid
8570 + ", uid=" + callingUid
8571 + " requires " + r.permission);
8572 return new ServiceLookupResult(null, r.permission);
8573 }
8574 return new ServiceLookupResult(r, null);
8575 }
8576 return null;
8577 }
8578
8579 private class ServiceRestarter implements Runnable {
8580 private ServiceRecord mService;
8581
8582 void setService(ServiceRecord service) {
8583 mService = service;
8584 }
8585
8586 public void run() {
8587 synchronized(ActivityManagerService.this) {
8588 performServiceRestartLocked(mService);
8589 }
8590 }
8591 }
8592
8593 private ServiceLookupResult retrieveServiceLocked(Intent service,
8594 String resolvedType, int callingPid, int callingUid) {
8595 ServiceRecord r = null;
8596 if (service.getComponent() != null) {
8597 r = mServices.get(service.getComponent());
8598 }
8599 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8600 r = mServicesByIntent.get(filter);
8601 if (r == null) {
8602 try {
8603 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008604 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008605 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008606 ServiceInfo sInfo =
8607 rInfo != null ? rInfo.serviceInfo : null;
8608 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008609 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008610 ": not found");
8611 return null;
8612 }
8613
8614 ComponentName name = new ComponentName(
8615 sInfo.applicationInfo.packageName, sInfo.name);
8616 r = mServices.get(name);
8617 if (r == null) {
8618 filter = new Intent.FilterComparison(service.cloneFilter());
8619 ServiceRestarter res = new ServiceRestarter();
8620 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8621 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8622 synchronized (stats) {
8623 ss = stats.getServiceStatsLocked(
8624 sInfo.applicationInfo.uid, sInfo.packageName,
8625 sInfo.name);
8626 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008627 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008628 res.setService(r);
8629 mServices.put(name, r);
8630 mServicesByIntent.put(filter, r);
8631
8632 // Make sure this component isn't in the pending list.
8633 int N = mPendingServices.size();
8634 for (int i=0; i<N; i++) {
8635 ServiceRecord pr = mPendingServices.get(i);
8636 if (pr.name.equals(name)) {
8637 mPendingServices.remove(i);
8638 i--;
8639 N--;
8640 }
8641 }
8642 }
8643 } catch (RemoteException ex) {
8644 // pm is in same process, this will never happen.
8645 }
8646 }
8647 if (r != null) {
8648 if (checkComponentPermission(r.permission,
8649 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8650 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008651 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 + " from pid=" + Binder.getCallingPid()
8653 + ", uid=" + Binder.getCallingUid()
8654 + " requires " + r.permission);
8655 return new ServiceLookupResult(null, r.permission);
8656 }
8657 return new ServiceLookupResult(r, null);
8658 }
8659 return null;
8660 }
8661
Dianne Hackborn287952c2010-09-22 22:34:31 -07008662 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8663 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8664 + why + " of " + r + " in app " + r.app);
8665 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8666 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008667 long now = SystemClock.uptimeMillis();
8668 if (r.executeNesting == 0 && r.app != null) {
8669 if (r.app.executingServices.size() == 0) {
8670 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8671 msg.obj = r.app;
8672 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8673 }
8674 r.app.executingServices.add(r);
8675 }
8676 r.executeNesting++;
8677 r.executingStart = now;
8678 }
8679
8680 private final void sendServiceArgsLocked(ServiceRecord r,
8681 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008682 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008683 if (N == 0) {
8684 return;
8685 }
8686
Dianne Hackborn39792d22010-08-19 18:01:52 -07008687 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008688 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008689 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008690 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8691 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008692 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008693 // If somehow we got a dummy start at the front, then
8694 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008695 continue;
8696 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008697 si.deliveredTime = SystemClock.uptimeMillis();
8698 r.deliveredStarts.add(si);
8699 si.deliveryCount++;
8700 if (si.targetPermissionUid >= 0) {
8701 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008702 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008703 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008704 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008705 if (!oomAdjusted) {
8706 oomAdjusted = true;
8707 updateOomAdjLocked(r.app);
8708 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008709 int flags = 0;
8710 if (si.deliveryCount > 0) {
8711 flags |= Service.START_FLAG_RETRY;
8712 }
8713 if (si.doneExecutingCount > 0) {
8714 flags |= Service.START_FLAG_REDELIVERY;
8715 }
8716 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008717 } catch (RemoteException e) {
8718 // Remote process gone... we'll let the normal cleanup take
8719 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008720 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008721 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008722 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008723 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008724 break;
8725 }
8726 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008727 }
8728
8729 private final boolean requestServiceBindingLocked(ServiceRecord r,
8730 IntentBindRecord i, boolean rebind) {
8731 if (r.app == null || r.app.thread == null) {
8732 // If service is not currently running, can't yet bind.
8733 return false;
8734 }
8735 if ((!i.requested || rebind) && i.apps.size() > 0) {
8736 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008737 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8739 if (!rebind) {
8740 i.requested = true;
8741 }
8742 i.hasBound = true;
8743 i.doRebind = false;
8744 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008745 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008746 return false;
8747 }
8748 }
8749 return true;
8750 }
8751
8752 private final void requestServiceBindingsLocked(ServiceRecord r) {
8753 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8754 while (bindings.hasNext()) {
8755 IntentBindRecord i = bindings.next();
8756 if (!requestServiceBindingLocked(r, i, false)) {
8757 break;
8758 }
8759 }
8760 }
8761
8762 private final void realStartServiceLocked(ServiceRecord r,
8763 ProcessRecord app) throws RemoteException {
8764 if (app.thread == null) {
8765 throw new RemoteException();
8766 }
8767
8768 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008769 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008770
8771 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008772 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008773 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008774
8775 boolean created = false;
8776 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008777 mStringBuilder.setLength(0);
8778 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008779 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008780 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008781 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 synchronized (r.stats.getBatteryStats()) {
8783 r.stats.startLaunchedLocked();
8784 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008785 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008787 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 created = true;
8789 } finally {
8790 if (!created) {
8791 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008792 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008793 }
8794 }
8795
8796 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008797
8798 // If the service is in the started state, and there are no
8799 // pending arguments, then fake up one so its onStartCommand() will
8800 // be called.
8801 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8802 r.lastStartId++;
8803 if (r.lastStartId < 1) {
8804 r.lastStartId = 1;
8805 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008806 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008807 }
8808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008809 sendServiceArgsLocked(r, true);
8810 }
8811
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008812 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8813 boolean allowCancel) {
8814 boolean canceled = false;
8815
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008816 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008817 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008818 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008819
8820 // Any delivered but not yet finished starts should be put back
8821 // on the pending list.
8822 final int N = r.deliveredStarts.size();
8823 if (N > 0) {
8824 for (int i=N-1; i>=0; i--) {
8825 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008826 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008827 if (si.intent == null) {
8828 // We'll generate this again if needed.
8829 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8830 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8831 r.pendingStarts.add(0, si);
8832 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8833 dur *= 2;
8834 if (minDuration < dur) minDuration = dur;
8835 if (resetTime < dur) resetTime = dur;
8836 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008837 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008838 + r.name);
8839 canceled = true;
8840 }
8841 }
8842 r.deliveredStarts.clear();
8843 }
8844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008845 r.totalRestartCount++;
8846 if (r.restartDelay == 0) {
8847 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008848 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 } else {
8850 // If it has been a "reasonably long time" since the service
8851 // was started, then reset our restart duration back to
8852 // the beginning, so we don't infinitely increase the duration
8853 // on a service that just occasionally gets killed (which is
8854 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008855 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008856 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008857 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008858 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008859 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008860 if (r.restartDelay < minDuration) {
8861 r.restartDelay = minDuration;
8862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008863 }
8864 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008865
8866 r.nextRestartTime = now + r.restartDelay;
8867
8868 // Make sure that we don't end up restarting a bunch of services
8869 // all at the same time.
8870 boolean repeat;
8871 do {
8872 repeat = false;
8873 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8874 ServiceRecord r2 = mRestartingServices.get(i);
8875 if (r2 != r && r.nextRestartTime
8876 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8877 && r.nextRestartTime
8878 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8879 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8880 r.restartDelay = r.nextRestartTime - now;
8881 repeat = true;
8882 break;
8883 }
8884 }
8885 } while (repeat);
8886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 if (!mRestartingServices.contains(r)) {
8888 mRestartingServices.add(r);
8889 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008890
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008891 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008894 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008895 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008896 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008897 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008898 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008899 r.shortName, r.restartDelay);
8900
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008901 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008902 }
8903
8904 final void performServiceRestartLocked(ServiceRecord r) {
8905 if (!mRestartingServices.contains(r)) {
8906 return;
8907 }
8908 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8909 }
8910
8911 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8912 if (r.restartDelay == 0) {
8913 return false;
8914 }
8915 r.resetRestartCounter();
8916 mRestartingServices.remove(r);
8917 mHandler.removeCallbacks(r.restarter);
8918 return true;
8919 }
8920
8921 private final boolean bringUpServiceLocked(ServiceRecord r,
8922 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008923 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008924 //r.dump(" ");
8925
Dianne Hackborn36124872009-10-08 16:22:03 -07008926 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008927 sendServiceArgsLocked(r, false);
8928 return true;
8929 }
8930
8931 if (!whileRestarting && r.restartDelay > 0) {
8932 // If waiting for a restart, then do nothing.
8933 return true;
8934 }
8935
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008936 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008937
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008938 // We are now bringing the service up, so no longer in the
8939 // restarting state.
8940 mRestartingServices.remove(r);
8941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008942 final String appName = r.processName;
8943 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8944 if (app != null && app.thread != null) {
8945 try {
8946 realStartServiceLocked(r, app);
8947 return true;
8948 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008949 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 }
8951
8952 // If a dead object exception was thrown -- fall through to
8953 // restart the application.
8954 }
8955
Dianne Hackborn36124872009-10-08 16:22:03 -07008956 // Not running -- get it started, and enqueue this service record
8957 // to be executed when the app comes up.
8958 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8959 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008960 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008961 + r.appInfo.packageName + "/"
8962 + r.appInfo.uid + " for service "
8963 + r.intent.getIntent() + ": process is bad");
8964 bringDownServiceLocked(r, true);
8965 return false;
8966 }
8967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008968 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008969 mPendingServices.add(r);
8970 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008972 return true;
8973 }
8974
8975 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008976 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008977 //r.dump(" ");
8978
8979 // Does it still need to run?
8980 if (!force && r.startRequested) {
8981 return;
8982 }
8983 if (r.connections.size() > 0) {
8984 if (!force) {
8985 // XXX should probably keep a count of the number of auto-create
8986 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008987 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008988 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008989 ArrayList<ConnectionRecord> cr = it.next();
8990 for (int i=0; i<cr.size(); i++) {
8991 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8992 return;
8993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008994 }
8995 }
8996 }
8997
8998 // Report to all of the connections that the service is no longer
8999 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009000 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009001 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009002 ArrayList<ConnectionRecord> c = it.next();
9003 for (int i=0; i<c.size(); i++) {
9004 try {
9005 c.get(i).conn.connected(r.name, null);
9006 } catch (Exception e) {
9007 Slog.w(TAG, "Failure disconnecting service " + r.name +
9008 " to connection " + c.get(i).conn.asBinder() +
9009 " (in " + c.get(i).binding.client.processName + ")", e);
9010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009011 }
9012 }
9013 }
9014
9015 // Tell the service that it has been unbound.
9016 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9017 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9018 while (it.hasNext()) {
9019 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009020 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009021 + ": hasBound=" + ibr.hasBound);
9022 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9023 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009024 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009025 updateOomAdjLocked(r.app);
9026 ibr.hasBound = false;
9027 r.app.thread.scheduleUnbindService(r,
9028 ibr.intent.getIntent());
9029 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009030 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009031 + r.shortName, e);
9032 serviceDoneExecutingLocked(r, true);
9033 }
9034 }
9035 }
9036 }
9037
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009038 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009039 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009040 System.identityHashCode(r), r.shortName,
9041 (r.app != null) ? r.app.pid : -1);
9042
9043 mServices.remove(r.name);
9044 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 r.totalRestartCount = 0;
9046 unscheduleServiceRestartLocked(r);
9047
9048 // Also make sure it is not on the pending list.
9049 int N = mPendingServices.size();
9050 for (int i=0; i<N; i++) {
9051 if (mPendingServices.get(i) == r) {
9052 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009053 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009054 i--;
9055 N--;
9056 }
9057 }
9058
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009059 r.cancelNotification();
9060 r.isForeground = false;
9061 r.foregroundId = 0;
9062 r.foregroundNoti = null;
9063
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009064 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009065 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009066 r.pendingStarts.clear();
9067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 if (r.app != null) {
9069 synchronized (r.stats.getBatteryStats()) {
9070 r.stats.stopLaunchedLocked();
9071 }
9072 r.app.services.remove(r);
9073 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009075 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009076 mStoppingServices.add(r);
9077 updateOomAdjLocked(r.app);
9078 r.app.thread.scheduleStopService(r);
9079 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009080 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 + r.shortName, e);
9082 serviceDoneExecutingLocked(r, true);
9083 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009084 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009086 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009087 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 }
9089 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009090 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009091 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009092 }
9093 }
9094
9095 ComponentName startServiceLocked(IApplicationThread caller,
9096 Intent service, String resolvedType,
9097 int callingPid, int callingUid) {
9098 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009099 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009100 + " type=" + resolvedType + " args=" + service.getExtras());
9101
9102 if (caller != null) {
9103 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9104 if (callerApp == null) {
9105 throw new SecurityException(
9106 "Unable to find app for caller " + caller
9107 + " (pid=" + Binder.getCallingPid()
9108 + ") when starting service " + service);
9109 }
9110 }
9111
9112 ServiceLookupResult res =
9113 retrieveServiceLocked(service, resolvedType,
9114 callingPid, callingUid);
9115 if (res == null) {
9116 return null;
9117 }
9118 if (res.record == null) {
9119 return new ComponentName("!", res.permission != null
9120 ? res.permission : "private to package");
9121 }
9122 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009123 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9124 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009126 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009127 }
9128 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009129 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130 r.lastStartId++;
9131 if (r.lastStartId < 1) {
9132 r.lastStartId = 1;
9133 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009134 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9135 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009136 r.lastActivity = SystemClock.uptimeMillis();
9137 synchronized (r.stats.getBatteryStats()) {
9138 r.stats.startRunningLocked();
9139 }
9140 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9141 return new ComponentName("!", "Service process is bad");
9142 }
9143 return r.name;
9144 }
9145 }
9146
9147 public ComponentName startService(IApplicationThread caller, Intent service,
9148 String resolvedType) {
9149 // Refuse possible leaked file descriptors
9150 if (service != null && service.hasFileDescriptors() == true) {
9151 throw new IllegalArgumentException("File descriptors passed in Intent");
9152 }
9153
9154 synchronized(this) {
9155 final int callingPid = Binder.getCallingPid();
9156 final int callingUid = Binder.getCallingUid();
9157 final long origId = Binder.clearCallingIdentity();
9158 ComponentName res = startServiceLocked(caller, service,
9159 resolvedType, callingPid, callingUid);
9160 Binder.restoreCallingIdentity(origId);
9161 return res;
9162 }
9163 }
9164
9165 ComponentName startServiceInPackage(int uid,
9166 Intent service, String resolvedType) {
9167 synchronized(this) {
9168 final long origId = Binder.clearCallingIdentity();
9169 ComponentName res = startServiceLocked(null, service,
9170 resolvedType, -1, uid);
9171 Binder.restoreCallingIdentity(origId);
9172 return res;
9173 }
9174 }
9175
9176 public int stopService(IApplicationThread caller, Intent service,
9177 String resolvedType) {
9178 // Refuse possible leaked file descriptors
9179 if (service != null && service.hasFileDescriptors() == true) {
9180 throw new IllegalArgumentException("File descriptors passed in Intent");
9181 }
9182
9183 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009184 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009185 + " type=" + resolvedType);
9186
9187 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9188 if (caller != null && callerApp == null) {
9189 throw new SecurityException(
9190 "Unable to find app for caller " + caller
9191 + " (pid=" + Binder.getCallingPid()
9192 + ") when stopping service " + service);
9193 }
9194
9195 // If this service is active, make sure it is stopped.
9196 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9197 if (r != null) {
9198 if (r.record != null) {
9199 synchronized (r.record.stats.getBatteryStats()) {
9200 r.record.stats.stopRunningLocked();
9201 }
9202 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009203 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009204 final long origId = Binder.clearCallingIdentity();
9205 bringDownServiceLocked(r.record, false);
9206 Binder.restoreCallingIdentity(origId);
9207 return 1;
9208 }
9209 return -1;
9210 }
9211 }
9212
9213 return 0;
9214 }
9215
9216 public IBinder peekService(Intent service, String resolvedType) {
9217 // Refuse possible leaked file descriptors
9218 if (service != null && service.hasFileDescriptors() == true) {
9219 throw new IllegalArgumentException("File descriptors passed in Intent");
9220 }
9221
9222 IBinder ret = null;
9223
9224 synchronized(this) {
9225 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9226
9227 if (r != null) {
9228 // r.record is null if findServiceLocked() failed the caller permission check
9229 if (r.record == null) {
9230 throw new SecurityException(
9231 "Permission Denial: Accessing service " + r.record.name
9232 + " from pid=" + Binder.getCallingPid()
9233 + ", uid=" + Binder.getCallingUid()
9234 + " requires " + r.permission);
9235 }
9236 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9237 if (ib != null) {
9238 ret = ib.binder;
9239 }
9240 }
9241 }
9242
9243 return ret;
9244 }
9245
9246 public boolean stopServiceToken(ComponentName className, IBinder token,
9247 int startId) {
9248 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009249 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009250 + " " + token + " startId=" + startId);
9251 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009252 if (r != null) {
9253 if (startId >= 0) {
9254 // Asked to only stop if done with all work. Note that
9255 // to avoid leaks, we will take this as dropping all
9256 // start items up to and including this one.
9257 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9258 if (si != null) {
9259 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009260 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9261 cur.removeUriPermissionsLocked();
9262 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009263 break;
9264 }
9265 }
9266 }
9267
9268 if (r.lastStartId != startId) {
9269 return false;
9270 }
9271
9272 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009273 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009274 + " is last, but have " + r.deliveredStarts.size()
9275 + " remaining args");
9276 }
9277 }
9278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 synchronized (r.stats.getBatteryStats()) {
9280 r.stats.stopRunningLocked();
9281 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009282 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009283 }
9284 final long origId = Binder.clearCallingIdentity();
9285 bringDownServiceLocked(r, false);
9286 Binder.restoreCallingIdentity(origId);
9287 return true;
9288 }
9289 }
9290 return false;
9291 }
9292
9293 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009294 int id, Notification notification, boolean removeNotification) {
9295 final long origId = Binder.clearCallingIdentity();
9296 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009297 synchronized(this) {
9298 ServiceRecord r = findServiceLocked(className, token);
9299 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009300 if (id != 0) {
9301 if (notification == null) {
9302 throw new IllegalArgumentException("null notification");
9303 }
9304 if (r.foregroundId != id) {
9305 r.cancelNotification();
9306 r.foregroundId = id;
9307 }
9308 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9309 r.foregroundNoti = notification;
9310 r.isForeground = true;
9311 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 if (r.app != null) {
9313 updateServiceForegroundLocked(r.app, true);
9314 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009315 } else {
9316 if (r.isForeground) {
9317 r.isForeground = false;
9318 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009319 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009320 updateServiceForegroundLocked(r.app, true);
9321 }
9322 }
9323 if (removeNotification) {
9324 r.cancelNotification();
9325 r.foregroundId = 0;
9326 r.foregroundNoti = null;
9327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009328 }
9329 }
9330 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009331 } finally {
9332 Binder.restoreCallingIdentity(origId);
9333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 }
9335
9336 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9337 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009338 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009339 if (sr.isForeground) {
9340 anyForeground = true;
9341 break;
9342 }
9343 }
9344 if (anyForeground != proc.foregroundServices) {
9345 proc.foregroundServices = anyForeground;
9346 if (oomAdj) {
9347 updateOomAdjLocked();
9348 }
9349 }
9350 }
9351
9352 public int bindService(IApplicationThread caller, IBinder token,
9353 Intent service, String resolvedType,
9354 IServiceConnection connection, int flags) {
9355 // Refuse possible leaked file descriptors
9356 if (service != null && service.hasFileDescriptors() == true) {
9357 throw new IllegalArgumentException("File descriptors passed in Intent");
9358 }
9359
9360 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009361 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009362 + " type=" + resolvedType + " conn=" + connection.asBinder()
9363 + " flags=0x" + Integer.toHexString(flags));
9364 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9365 if (callerApp == null) {
9366 throw new SecurityException(
9367 "Unable to find app for caller " + caller
9368 + " (pid=" + Binder.getCallingPid()
9369 + ") when binding service " + service);
9370 }
9371
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009372 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009373 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009374 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009375 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009376 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009377 return 0;
9378 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009379 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009380 }
9381
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009382 int clientLabel = 0;
9383 PendingIntent clientIntent = null;
9384
9385 if (callerApp.info.uid == Process.SYSTEM_UID) {
9386 // Hacky kind of thing -- allow system stuff to tell us
9387 // what they are, so we can report this elsewhere for
9388 // others to know why certain services are running.
9389 try {
9390 clientIntent = (PendingIntent)service.getParcelableExtra(
9391 Intent.EXTRA_CLIENT_INTENT);
9392 } catch (RuntimeException e) {
9393 }
9394 if (clientIntent != null) {
9395 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9396 if (clientLabel != 0) {
9397 // There are no useful extras in the intent, trash them.
9398 // System code calling with this stuff just needs to know
9399 // this will happen.
9400 service = service.cloneFilter();
9401 }
9402 }
9403 }
9404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009405 ServiceLookupResult res =
9406 retrieveServiceLocked(service, resolvedType,
9407 Binder.getCallingPid(), Binder.getCallingUid());
9408 if (res == null) {
9409 return 0;
9410 }
9411 if (res.record == null) {
9412 return -1;
9413 }
9414 ServiceRecord s = res.record;
9415
9416 final long origId = Binder.clearCallingIdentity();
9417
9418 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009419 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009420 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009421 }
9422
9423 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9424 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009425 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009426
9427 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009428 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9429 if (clist == null) {
9430 clist = new ArrayList<ConnectionRecord>();
9431 s.connections.put(binder, clist);
9432 }
9433 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009434 b.connections.add(c);
9435 if (activity != null) {
9436 if (activity.connections == null) {
9437 activity.connections = new HashSet<ConnectionRecord>();
9438 }
9439 activity.connections.add(c);
9440 }
9441 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009442 clist = mServiceConnections.get(binder);
9443 if (clist == null) {
9444 clist = new ArrayList<ConnectionRecord>();
9445 mServiceConnections.put(binder, clist);
9446 }
9447 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009448
9449 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9450 s.lastActivity = SystemClock.uptimeMillis();
9451 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9452 return 0;
9453 }
9454 }
9455
9456 if (s.app != null) {
9457 // This could have made the service more important.
9458 updateOomAdjLocked(s.app);
9459 }
9460
Joe Onorato8a9b2202010-02-26 18:56:32 -08009461 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009462 + ": received=" + b.intent.received
9463 + " apps=" + b.intent.apps.size()
9464 + " doRebind=" + b.intent.doRebind);
9465
9466 if (s.app != null && b.intent.received) {
9467 // Service is already running, so we can immediately
9468 // publish the connection.
9469 try {
9470 c.conn.connected(s.name, b.intent.binder);
9471 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009472 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009473 + " to connection " + c.conn.asBinder()
9474 + " (in " + c.binding.client.processName + ")", e);
9475 }
9476
9477 // If this is the first app connected back to this binding,
9478 // and the service had previously asked to be told when
9479 // rebound, then do so.
9480 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9481 requestServiceBindingLocked(s, b.intent, true);
9482 }
9483 } else if (!b.intent.requested) {
9484 requestServiceBindingLocked(s, b.intent, false);
9485 }
9486
9487 Binder.restoreCallingIdentity(origId);
9488 }
9489
9490 return 1;
9491 }
9492
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009493 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009494 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009495 IBinder binder = c.conn.asBinder();
9496 AppBindRecord b = c.binding;
9497 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009498 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9499 if (clist != null) {
9500 clist.remove(c);
9501 if (clist.size() == 0) {
9502 s.connections.remove(binder);
9503 }
9504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009505 b.connections.remove(c);
9506 if (c.activity != null && c.activity != skipAct) {
9507 if (c.activity.connections != null) {
9508 c.activity.connections.remove(c);
9509 }
9510 }
9511 if (b.client != skipApp) {
9512 b.client.connections.remove(c);
9513 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009514 clist = mServiceConnections.get(binder);
9515 if (clist != null) {
9516 clist.remove(c);
9517 if (clist.size() == 0) {
9518 mServiceConnections.remove(binder);
9519 }
9520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521
9522 if (b.connections.size() == 0) {
9523 b.intent.apps.remove(b.client);
9524 }
9525
Joe Onorato8a9b2202010-02-26 18:56:32 -08009526 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009527 + ": shouldUnbind=" + b.intent.hasBound);
9528 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9529 && b.intent.hasBound) {
9530 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009531 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009532 updateOomAdjLocked(s.app);
9533 b.intent.hasBound = false;
9534 // Assume the client doesn't want to know about a rebind;
9535 // we will deal with that later if it asks for one.
9536 b.intent.doRebind = false;
9537 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9538 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009539 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009540 serviceDoneExecutingLocked(s, true);
9541 }
9542 }
9543
9544 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9545 bringDownServiceLocked(s, false);
9546 }
9547 }
9548
9549 public boolean unbindService(IServiceConnection connection) {
9550 synchronized (this) {
9551 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009552 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009553 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9554 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009555 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009556 + connection.asBinder());
9557 return false;
9558 }
9559
9560 final long origId = Binder.clearCallingIdentity();
9561
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009562 while (clist.size() > 0) {
9563 ConnectionRecord r = clist.get(0);
9564 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009565
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009566 if (r.binding.service.app != null) {
9567 // This could have made the service less important.
9568 updateOomAdjLocked(r.binding.service.app);
9569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009570 }
9571
9572 Binder.restoreCallingIdentity(origId);
9573 }
9574
9575 return true;
9576 }
9577
9578 public void publishService(IBinder token, Intent intent, IBinder service) {
9579 // Refuse possible leaked file descriptors
9580 if (intent != null && intent.hasFileDescriptors() == true) {
9581 throw new IllegalArgumentException("File descriptors passed in Intent");
9582 }
9583
9584 synchronized(this) {
9585 if (!(token instanceof ServiceRecord)) {
9586 throw new IllegalArgumentException("Invalid service token");
9587 }
9588 ServiceRecord r = (ServiceRecord)token;
9589
9590 final long origId = Binder.clearCallingIdentity();
9591
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009592 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009593 + " " + intent + ": " + service);
9594 if (r != null) {
9595 Intent.FilterComparison filter
9596 = new Intent.FilterComparison(intent);
9597 IntentBindRecord b = r.bindings.get(filter);
9598 if (b != null && !b.received) {
9599 b.binder = service;
9600 b.requested = true;
9601 b.received = true;
9602 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009603 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009604 = r.connections.values().iterator();
9605 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009606 ArrayList<ConnectionRecord> clist = it.next();
9607 for (int i=0; i<clist.size(); i++) {
9608 ConnectionRecord c = clist.get(i);
9609 if (!filter.equals(c.binding.intent.intent)) {
9610 if (DEBUG_SERVICE) Slog.v(
9611 TAG, "Not publishing to: " + c);
9612 if (DEBUG_SERVICE) Slog.v(
9613 TAG, "Bound intent: " + c.binding.intent.intent);
9614 if (DEBUG_SERVICE) Slog.v(
9615 TAG, "Published intent: " + intent);
9616 continue;
9617 }
9618 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9619 try {
9620 c.conn.connected(r.name, service);
9621 } catch (Exception e) {
9622 Slog.w(TAG, "Failure sending service " + r.name +
9623 " to connection " + c.conn.asBinder() +
9624 " (in " + c.binding.client.processName + ")", e);
9625 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626 }
9627 }
9628 }
9629 }
9630
9631 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9632
9633 Binder.restoreCallingIdentity(origId);
9634 }
9635 }
9636 }
9637
9638 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9639 // Refuse possible leaked file descriptors
9640 if (intent != null && intent.hasFileDescriptors() == true) {
9641 throw new IllegalArgumentException("File descriptors passed in Intent");
9642 }
9643
9644 synchronized(this) {
9645 if (!(token instanceof ServiceRecord)) {
9646 throw new IllegalArgumentException("Invalid service token");
9647 }
9648 ServiceRecord r = (ServiceRecord)token;
9649
9650 final long origId = Binder.clearCallingIdentity();
9651
9652 if (r != null) {
9653 Intent.FilterComparison filter
9654 = new Intent.FilterComparison(intent);
9655 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009656 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009657 + " at " + b + ": apps="
9658 + (b != null ? b.apps.size() : 0));
9659 if (b != null) {
9660 if (b.apps.size() > 0) {
9661 // Applications have already bound since the last
9662 // unbind, so just rebind right here.
9663 requestServiceBindingLocked(r, b, true);
9664 } else {
9665 // Note to tell the service the next time there is
9666 // a new client.
9667 b.doRebind = true;
9668 }
9669 }
9670
9671 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9672
9673 Binder.restoreCallingIdentity(origId);
9674 }
9675 }
9676 }
9677
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009678 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679 synchronized(this) {
9680 if (!(token instanceof ServiceRecord)) {
9681 throw new IllegalArgumentException("Invalid service token");
9682 }
9683 ServiceRecord r = (ServiceRecord)token;
9684 boolean inStopping = mStoppingServices.contains(token);
9685 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009686 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009687 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009688 + " with incorrect token: given " + token
9689 + ", expected " + r);
9690 return;
9691 }
9692
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009693 if (type == 1) {
9694 // This is a call from a service start... take care of
9695 // book-keeping.
9696 r.callStart = true;
9697 switch (res) {
9698 case Service.START_STICKY_COMPATIBILITY:
9699 case Service.START_STICKY: {
9700 // We are done with the associated start arguments.
9701 r.findDeliveredStart(startId, true);
9702 // Don't stop if killed.
9703 r.stopIfKilled = false;
9704 break;
9705 }
9706 case Service.START_NOT_STICKY: {
9707 // We are done with the associated start arguments.
9708 r.findDeliveredStart(startId, true);
9709 if (r.lastStartId == startId) {
9710 // There is no more work, and this service
9711 // doesn't want to hang around if killed.
9712 r.stopIfKilled = true;
9713 }
9714 break;
9715 }
9716 case Service.START_REDELIVER_INTENT: {
9717 // We'll keep this item until they explicitly
9718 // call stop for it, but keep track of the fact
9719 // that it was delivered.
9720 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9721 if (si != null) {
9722 si.deliveryCount = 0;
9723 si.doneExecutingCount++;
9724 // Don't stop if killed.
9725 r.stopIfKilled = true;
9726 }
9727 break;
9728 }
9729 default:
9730 throw new IllegalArgumentException(
9731 "Unknown service start result: " + res);
9732 }
9733 if (res == Service.START_STICKY_COMPATIBILITY) {
9734 r.callStart = false;
9735 }
9736 }
9737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009738 final long origId = Binder.clearCallingIdentity();
9739 serviceDoneExecutingLocked(r, inStopping);
9740 Binder.restoreCallingIdentity(origId);
9741 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009742 Slog.w(TAG, "Done executing unknown service from pid "
9743 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009744 }
9745 }
9746 }
9747
9748 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009749 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9750 + ": nesting=" + r.executeNesting
9751 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009752 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753 r.executeNesting--;
9754 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009755 if (DEBUG_SERVICE) Slog.v(TAG,
9756 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 r.app.executingServices.remove(r);
9758 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009759 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9760 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009761 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9762 }
9763 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009764 if (DEBUG_SERVICE) Slog.v(TAG,
9765 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766 mStoppingServices.remove(r);
9767 }
9768 updateOomAdjLocked(r.app);
9769 }
9770 }
9771
9772 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009773 String anrMessage = null;
9774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 synchronized(this) {
9776 if (proc.executingServices.size() == 0 || proc.thread == null) {
9777 return;
9778 }
9779 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9780 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9781 ServiceRecord timeout = null;
9782 long nextTime = 0;
9783 while (it.hasNext()) {
9784 ServiceRecord sr = it.next();
9785 if (sr.executingStart < maxTime) {
9786 timeout = sr;
9787 break;
9788 }
9789 if (sr.executingStart > nextTime) {
9790 nextTime = sr.executingStart;
9791 }
9792 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009793 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009794 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009795 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796 } else {
9797 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9798 msg.obj = proc;
9799 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9800 }
9801 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009802
9803 if (anrMessage != null) {
9804 appNotResponding(proc, null, null, anrMessage);
9805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009806 }
9807
9808 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009809 // BACKUP AND RESTORE
9810 // =========================================================
9811
9812 // Cause the target app to be launched if necessary and its backup agent
9813 // instantiated. The backup agent will invoke backupAgentCreated() on the
9814 // activity manager to announce its creation.
9815 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009816 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009817 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9818
9819 synchronized(this) {
9820 // !!! TODO: currently no check here that we're already bound
9821 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9822 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9823 synchronized (stats) {
9824 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9825 }
9826
9827 BackupRecord r = new BackupRecord(ss, app, backupMode);
9828 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9829 // startProcessLocked() returns existing proc's record if it's already running
9830 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009831 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009832 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009833 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009834 return false;
9835 }
9836
9837 r.app = proc;
9838 mBackupTarget = r;
9839 mBackupAppName = app.packageName;
9840
Christopher Tate6fa95972009-06-05 18:43:55 -07009841 // Try not to kill the process during backup
9842 updateOomAdjLocked(proc);
9843
Christopher Tate181fafa2009-05-14 11:12:14 -07009844 // If the process is already attached, schedule the creation of the backup agent now.
9845 // If it is not yet live, this will be done when it attaches to the framework.
9846 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009847 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009848 try {
9849 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9850 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009851 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009852 }
9853 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009854 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009855 }
9856 // Invariants: at this point, the target app process exists and the application
9857 // is either already running or in the process of coming up. mBackupTarget and
9858 // mBackupAppName describe the app, so that when it binds back to the AM we
9859 // know that it's scheduled for a backup-agent operation.
9860 }
9861
9862 return true;
9863 }
9864
9865 // A backup agent has just come up
9866 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009867 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009868 + " = " + agent);
9869
9870 synchronized(this) {
9871 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009872 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009873 return;
9874 }
Dianne Hackborn06740692010-09-22 22:46:21 -07009875 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009876
Dianne Hackborn06740692010-09-22 22:46:21 -07009877 long oldIdent = Binder.clearCallingIdentity();
9878 try {
9879 IBackupManager bm = IBackupManager.Stub.asInterface(
9880 ServiceManager.getService(Context.BACKUP_SERVICE));
9881 bm.agentConnected(agentPackageName, agent);
9882 } catch (RemoteException e) {
9883 // can't happen; the backup manager service is local
9884 } catch (Exception e) {
9885 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
9886 e.printStackTrace();
9887 } finally {
9888 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009889 }
9890 }
9891
9892 // done with this agent
9893 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009894 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009895 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009896 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009897 return;
9898 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009899
9900 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009901 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009902 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009903 return;
9904 }
9905
Christopher Tate181fafa2009-05-14 11:12:14 -07009906 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009907 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009908 return;
9909 }
9910
Christopher Tate6fa95972009-06-05 18:43:55 -07009911 ProcessRecord proc = mBackupTarget.app;
9912 mBackupTarget = null;
9913 mBackupAppName = null;
9914
9915 // Not backing this app up any more; reset its OOM adjustment
9916 updateOomAdjLocked(proc);
9917
Christopher Tatec7b31e32009-06-10 15:49:30 -07009918 // If the app crashed during backup, 'thread' will be null here
9919 if (proc.thread != null) {
9920 try {
9921 proc.thread.scheduleDestroyBackupAgent(appInfo);
9922 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009923 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009924 e.printStackTrace();
9925 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009926 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009927 }
9928 }
9929 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009930 // BROADCASTS
9931 // =========================================================
9932
Josh Bartel7f208742010-02-25 11:01:44 -06009933 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009934 List cur) {
9935 final ContentResolver resolver = mContext.getContentResolver();
9936 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9937 if (list == null) {
9938 return cur;
9939 }
9940 int N = list.size();
9941 for (int i=0; i<N; i++) {
9942 Intent intent = list.get(i);
9943 if (filter.match(resolver, intent, true, TAG) >= 0) {
9944 if (cur == null) {
9945 cur = new ArrayList<Intent>();
9946 }
9947 cur.add(intent);
9948 }
9949 }
9950 return cur;
9951 }
9952
9953 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009954 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009955 + mBroadcastsScheduled);
9956
9957 if (mBroadcastsScheduled) {
9958 return;
9959 }
9960 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9961 mBroadcastsScheduled = true;
9962 }
9963
9964 public Intent registerReceiver(IApplicationThread caller,
9965 IIntentReceiver receiver, IntentFilter filter, String permission) {
9966 synchronized(this) {
9967 ProcessRecord callerApp = null;
9968 if (caller != null) {
9969 callerApp = getRecordForAppLocked(caller);
9970 if (callerApp == null) {
9971 throw new SecurityException(
9972 "Unable to find app for caller " + caller
9973 + " (pid=" + Binder.getCallingPid()
9974 + ") when registering receiver " + receiver);
9975 }
9976 }
9977
9978 List allSticky = null;
9979
9980 // Look for any matching sticky broadcasts...
9981 Iterator actions = filter.actionsIterator();
9982 if (actions != null) {
9983 while (actions.hasNext()) {
9984 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009985 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009986 }
9987 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009988 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009989 }
9990
9991 // The first sticky in the list is returned directly back to
9992 // the client.
9993 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9994
Joe Onorato8a9b2202010-02-26 18:56:32 -08009995 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009996 + ": " + sticky);
9997
9998 if (receiver == null) {
9999 return sticky;
10000 }
10001
10002 ReceiverList rl
10003 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10004 if (rl == null) {
10005 rl = new ReceiverList(this, callerApp,
10006 Binder.getCallingPid(),
10007 Binder.getCallingUid(), receiver);
10008 if (rl.app != null) {
10009 rl.app.receivers.add(rl);
10010 } else {
10011 try {
10012 receiver.asBinder().linkToDeath(rl, 0);
10013 } catch (RemoteException e) {
10014 return sticky;
10015 }
10016 rl.linkedToDeath = true;
10017 }
10018 mRegisteredReceivers.put(receiver.asBinder(), rl);
10019 }
10020 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10021 rl.add(bf);
10022 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010023 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010024 }
10025 mReceiverResolver.addFilter(bf);
10026
10027 // Enqueue broadcasts for all existing stickies that match
10028 // this filter.
10029 if (allSticky != null) {
10030 ArrayList receivers = new ArrayList();
10031 receivers.add(bf);
10032
10033 int N = allSticky.size();
10034 for (int i=0; i<N; i++) {
10035 Intent intent = (Intent)allSticky.get(i);
10036 BroadcastRecord r = new BroadcastRecord(intent, null,
10037 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010038 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010039 if (mParallelBroadcasts.size() == 0) {
10040 scheduleBroadcastsLocked();
10041 }
10042 mParallelBroadcasts.add(r);
10043 }
10044 }
10045
10046 return sticky;
10047 }
10048 }
10049
10050 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010051 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010052
10053 boolean doNext = false;
10054
10055 synchronized(this) {
10056 ReceiverList rl
10057 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10058 if (rl != null) {
10059 if (rl.curBroadcast != null) {
10060 BroadcastRecord r = rl.curBroadcast;
10061 doNext = finishReceiverLocked(
10062 receiver.asBinder(), r.resultCode, r.resultData,
10063 r.resultExtras, r.resultAbort, true);
10064 }
10065
10066 if (rl.app != null) {
10067 rl.app.receivers.remove(rl);
10068 }
10069 removeReceiverLocked(rl);
10070 if (rl.linkedToDeath) {
10071 rl.linkedToDeath = false;
10072 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10073 }
10074 }
10075 }
10076
10077 if (!doNext) {
10078 return;
10079 }
10080
10081 final long origId = Binder.clearCallingIdentity();
10082 processNextBroadcast(false);
10083 trimApplications();
10084 Binder.restoreCallingIdentity(origId);
10085 }
10086
10087 void removeReceiverLocked(ReceiverList rl) {
10088 mRegisteredReceivers.remove(rl.receiver.asBinder());
10089 int N = rl.size();
10090 for (int i=0; i<N; i++) {
10091 mReceiverResolver.removeFilter(rl.get(i));
10092 }
10093 }
10094
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010095 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10096 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10097 ProcessRecord r = mLruProcesses.get(i);
10098 if (r.thread != null) {
10099 try {
10100 r.thread.dispatchPackageBroadcast(cmd, packages);
10101 } catch (RemoteException ex) {
10102 }
10103 }
10104 }
10105 }
10106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010107 private final int broadcastIntentLocked(ProcessRecord callerApp,
10108 String callerPackage, Intent intent, String resolvedType,
10109 IIntentReceiver resultTo, int resultCode, String resultData,
10110 Bundle map, String requiredPermission,
10111 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10112 intent = new Intent(intent);
10113
Joe Onorato8a9b2202010-02-26 18:56:32 -080010114 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010115 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10116 + " ordered=" + ordered);
10117 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010118 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010119 }
10120
10121 // Handle special intents: if this broadcast is from the package
10122 // manager about a package being removed, we need to remove all of
10123 // its activities from the history stack.
10124 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10125 intent.getAction());
10126 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10127 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010128 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010129 || uidRemoved) {
10130 if (checkComponentPermission(
10131 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10132 callingPid, callingUid, -1)
10133 == PackageManager.PERMISSION_GRANTED) {
10134 if (uidRemoved) {
10135 final Bundle intentExtras = intent.getExtras();
10136 final int uid = intentExtras != null
10137 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10138 if (uid >= 0) {
10139 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10140 synchronized (bs) {
10141 bs.removeUidStatsLocked(uid);
10142 }
10143 }
10144 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010145 // If resources are unvailble just force stop all
10146 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010147 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010148 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10149 if (list != null && (list.length > 0)) {
10150 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010151 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010152 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010153 sendPackageBroadcastLocked(
10154 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010155 }
10156 } else {
10157 Uri data = intent.getData();
10158 String ssp;
10159 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10160 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10161 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010162 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010163 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010164 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10165 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10166 new String[] {ssp});
10167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010168 }
10169 }
10170 }
10171 } else {
10172 String msg = "Permission Denial: " + intent.getAction()
10173 + " broadcast from " + callerPackage + " (pid=" + callingPid
10174 + ", uid=" + callingUid + ")"
10175 + " requires "
10176 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010177 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010178 throw new SecurityException(msg);
10179 }
10180 }
10181
10182 /*
10183 * If this is the time zone changed action, queue up a message that will reset the timezone
10184 * of all currently running processes. This message will get queued up before the broadcast
10185 * happens.
10186 */
10187 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10188 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10189 }
10190
Dianne Hackborn854060af2009-07-09 18:14:31 -070010191 /*
10192 * Prevent non-system code (defined here to be non-persistent
10193 * processes) from sending protected broadcasts.
10194 */
10195 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10196 || callingUid == Process.SHELL_UID || callingUid == 0) {
10197 // Always okay.
10198 } else if (callerApp == null || !callerApp.persistent) {
10199 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010200 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010201 intent.getAction())) {
10202 String msg = "Permission Denial: not allowed to send broadcast "
10203 + intent.getAction() + " from pid="
10204 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010205 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010206 throw new SecurityException(msg);
10207 }
10208 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010209 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010210 return BROADCAST_SUCCESS;
10211 }
10212 }
10213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010214 // Add to the sticky list if requested.
10215 if (sticky) {
10216 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10217 callingPid, callingUid)
10218 != PackageManager.PERMISSION_GRANTED) {
10219 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10220 + callingPid + ", uid=" + callingUid
10221 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010222 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010223 throw new SecurityException(msg);
10224 }
10225 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010226 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010227 + " and enforce permission " + requiredPermission);
10228 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10229 }
10230 if (intent.getComponent() != null) {
10231 throw new SecurityException(
10232 "Sticky broadcasts can't target a specific component");
10233 }
10234 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10235 if (list == null) {
10236 list = new ArrayList<Intent>();
10237 mStickyBroadcasts.put(intent.getAction(), list);
10238 }
10239 int N = list.size();
10240 int i;
10241 for (i=0; i<N; i++) {
10242 if (intent.filterEquals(list.get(i))) {
10243 // This sticky already exists, replace it.
10244 list.set(i, new Intent(intent));
10245 break;
10246 }
10247 }
10248 if (i >= N) {
10249 list.add(new Intent(intent));
10250 }
10251 }
10252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010253 // Figure out who all will receive this broadcast.
10254 List receivers = null;
10255 List<BroadcastFilter> registeredReceivers = null;
10256 try {
10257 if (intent.getComponent() != null) {
10258 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010259 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010260 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010261 if (ai != null) {
10262 receivers = new ArrayList();
10263 ResolveInfo ri = new ResolveInfo();
10264 ri.activityInfo = ai;
10265 receivers.add(ri);
10266 }
10267 } else {
10268 // Need to resolve the intent to interested receivers...
10269 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10270 == 0) {
10271 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010272 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010273 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 }
Mihai Preda074edef2009-05-18 17:13:31 +020010275 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010276 }
10277 } catch (RemoteException ex) {
10278 // pm is in same process, this will never happen.
10279 }
10280
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010281 final boolean replacePending =
10282 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10283
Joe Onorato8a9b2202010-02-26 18:56:32 -080010284 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010285 + " replacePending=" + replacePending);
10286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010287 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10288 if (!ordered && NR > 0) {
10289 // If we are not serializing this broadcast, then send the
10290 // registered receivers separately so they don't wait for the
10291 // components to be launched.
10292 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10293 callerPackage, callingPid, callingUid, requiredPermission,
10294 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010295 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010296 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010297 TAG, "Enqueueing parallel broadcast " + r
10298 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010299 boolean replaced = false;
10300 if (replacePending) {
10301 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10302 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010303 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010304 "***** DROPPING PARALLEL: " + intent);
10305 mParallelBroadcasts.set(i, r);
10306 replaced = true;
10307 break;
10308 }
10309 }
10310 }
10311 if (!replaced) {
10312 mParallelBroadcasts.add(r);
10313 scheduleBroadcastsLocked();
10314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 registeredReceivers = null;
10316 NR = 0;
10317 }
10318
10319 // Merge into one list.
10320 int ir = 0;
10321 if (receivers != null) {
10322 // A special case for PACKAGE_ADDED: do not allow the package
10323 // being added to see this broadcast. This prevents them from
10324 // using this as a back door to get run as soon as they are
10325 // installed. Maybe in the future we want to have a special install
10326 // broadcast or such for apps, but we'd like to deliberately make
10327 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010328 String skipPackages[] = null;
10329 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10330 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10331 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10332 Uri data = intent.getData();
10333 if (data != null) {
10334 String pkgName = data.getSchemeSpecificPart();
10335 if (pkgName != null) {
10336 skipPackages = new String[] { pkgName };
10337 }
10338 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010339 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010340 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010341 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010342 if (skipPackages != null && (skipPackages.length > 0)) {
10343 for (String skipPackage : skipPackages) {
10344 if (skipPackage != null) {
10345 int NT = receivers.size();
10346 for (int it=0; it<NT; it++) {
10347 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10348 if (curt.activityInfo.packageName.equals(skipPackage)) {
10349 receivers.remove(it);
10350 it--;
10351 NT--;
10352 }
10353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 }
10355 }
10356 }
10357
10358 int NT = receivers != null ? receivers.size() : 0;
10359 int it = 0;
10360 ResolveInfo curt = null;
10361 BroadcastFilter curr = null;
10362 while (it < NT && ir < NR) {
10363 if (curt == null) {
10364 curt = (ResolveInfo)receivers.get(it);
10365 }
10366 if (curr == null) {
10367 curr = registeredReceivers.get(ir);
10368 }
10369 if (curr.getPriority() >= curt.priority) {
10370 // Insert this broadcast record into the final list.
10371 receivers.add(it, curr);
10372 ir++;
10373 curr = null;
10374 it++;
10375 NT++;
10376 } else {
10377 // Skip to the next ResolveInfo in the final list.
10378 it++;
10379 curt = null;
10380 }
10381 }
10382 }
10383 while (ir < NR) {
10384 if (receivers == null) {
10385 receivers = new ArrayList();
10386 }
10387 receivers.add(registeredReceivers.get(ir));
10388 ir++;
10389 }
10390
10391 if ((receivers != null && receivers.size() > 0)
10392 || resultTo != null) {
10393 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10394 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010395 receivers, resultTo, resultCode, resultData, map, ordered,
10396 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010397 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010398 TAG, "Enqueueing ordered broadcast " + r
10399 + ": prev had " + mOrderedBroadcasts.size());
10400 if (DEBUG_BROADCAST) {
10401 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010402 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010404 boolean replaced = false;
10405 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010406 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010407 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010408 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010409 "***** DROPPING ORDERED: " + intent);
10410 mOrderedBroadcasts.set(i, r);
10411 replaced = true;
10412 break;
10413 }
10414 }
10415 }
10416 if (!replaced) {
10417 mOrderedBroadcasts.add(r);
10418 scheduleBroadcastsLocked();
10419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010420 }
10421
10422 return BROADCAST_SUCCESS;
10423 }
10424
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010425 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426 // Refuse possible leaked file descriptors
10427 if (intent != null && intent.hasFileDescriptors() == true) {
10428 throw new IllegalArgumentException("File descriptors passed in Intent");
10429 }
10430
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010431 int flags = intent.getFlags();
10432
10433 if (!mProcessesReady) {
10434 // if the caller really truly claims to know what they're doing, go
10435 // ahead and allow the broadcast without launching any receivers
10436 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10437 intent = new Intent(intent);
10438 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10439 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10440 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10441 + " before boot completion");
10442 throw new IllegalStateException("Cannot broadcast before boot completed");
10443 }
10444 }
10445
10446 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10447 throw new IllegalArgumentException(
10448 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10449 }
10450
10451 return intent;
10452 }
10453
10454 public final int broadcastIntent(IApplicationThread caller,
10455 Intent intent, String resolvedType, IIntentReceiver resultTo,
10456 int resultCode, String resultData, Bundle map,
10457 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010459 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010461 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10462 final int callingPid = Binder.getCallingPid();
10463 final int callingUid = Binder.getCallingUid();
10464 final long origId = Binder.clearCallingIdentity();
10465 int res = broadcastIntentLocked(callerApp,
10466 callerApp != null ? callerApp.info.packageName : null,
10467 intent, resolvedType, resultTo,
10468 resultCode, resultData, map, requiredPermission, serialized,
10469 sticky, callingPid, callingUid);
10470 Binder.restoreCallingIdentity(origId);
10471 return res;
10472 }
10473 }
10474
10475 int broadcastIntentInPackage(String packageName, int uid,
10476 Intent intent, String resolvedType, IIntentReceiver resultTo,
10477 int resultCode, String resultData, Bundle map,
10478 String requiredPermission, boolean serialized, boolean sticky) {
10479 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010480 intent = verifyBroadcastLocked(intent);
10481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010482 final long origId = Binder.clearCallingIdentity();
10483 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10484 resultTo, resultCode, resultData, map, requiredPermission,
10485 serialized, sticky, -1, uid);
10486 Binder.restoreCallingIdentity(origId);
10487 return res;
10488 }
10489 }
10490
10491 public final void unbroadcastIntent(IApplicationThread caller,
10492 Intent intent) {
10493 // Refuse possible leaked file descriptors
10494 if (intent != null && intent.hasFileDescriptors() == true) {
10495 throw new IllegalArgumentException("File descriptors passed in Intent");
10496 }
10497
10498 synchronized(this) {
10499 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10500 != PackageManager.PERMISSION_GRANTED) {
10501 String msg = "Permission Denial: unbroadcastIntent() from pid="
10502 + Binder.getCallingPid()
10503 + ", uid=" + Binder.getCallingUid()
10504 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010505 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010506 throw new SecurityException(msg);
10507 }
10508 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10509 if (list != null) {
10510 int N = list.size();
10511 int i;
10512 for (i=0; i<N; i++) {
10513 if (intent.filterEquals(list.get(i))) {
10514 list.remove(i);
10515 break;
10516 }
10517 }
10518 }
10519 }
10520 }
10521
10522 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10523 String resultData, Bundle resultExtras, boolean resultAbort,
10524 boolean explicit) {
10525 if (mOrderedBroadcasts.size() == 0) {
10526 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010527 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 }
10529 return false;
10530 }
10531 BroadcastRecord r = mOrderedBroadcasts.get(0);
10532 if (r.receiver == null) {
10533 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010534 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010535 }
10536 return false;
10537 }
10538 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010539 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010540 return false;
10541 }
10542 int state = r.state;
10543 r.state = r.IDLE;
10544 if (state == r.IDLE) {
10545 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010546 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010547 }
10548 }
10549 r.receiver = null;
10550 r.intent.setComponent(null);
10551 if (r.curApp != null) {
10552 r.curApp.curReceiver = null;
10553 }
10554 if (r.curFilter != null) {
10555 r.curFilter.receiverList.curBroadcast = null;
10556 }
10557 r.curFilter = null;
10558 r.curApp = null;
10559 r.curComponent = null;
10560 r.curReceiver = null;
10561 mPendingBroadcast = null;
10562
10563 r.resultCode = resultCode;
10564 r.resultData = resultData;
10565 r.resultExtras = resultExtras;
10566 r.resultAbort = resultAbort;
10567
10568 // We will process the next receiver right now if this is finishing
10569 // an app receiver (which is always asynchronous) or after we have
10570 // come back from calling a receiver.
10571 return state == BroadcastRecord.APP_RECEIVE
10572 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10573 }
10574
10575 public void finishReceiver(IBinder who, int resultCode, String resultData,
10576 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010577 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010578
10579 // Refuse possible leaked file descriptors
10580 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10581 throw new IllegalArgumentException("File descriptors passed in Bundle");
10582 }
10583
10584 boolean doNext;
10585
10586 final long origId = Binder.clearCallingIdentity();
10587
10588 synchronized(this) {
10589 doNext = finishReceiverLocked(
10590 who, resultCode, resultData, resultExtras, resultAbort, true);
10591 }
10592
10593 if (doNext) {
10594 processNextBroadcast(false);
10595 }
10596 trimApplications();
10597
10598 Binder.restoreCallingIdentity(origId);
10599 }
10600
Jeff Brown4d94a762010-09-23 11:33:28 -070010601 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010602 if (r.nextReceiver > 0) {
10603 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10604 if (curReceiver instanceof BroadcastFilter) {
10605 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010606 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010607 System.identityHashCode(r),
10608 r.intent.getAction(),
10609 r.nextReceiver - 1,
10610 System.identityHashCode(bf));
10611 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010612 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010613 System.identityHashCode(r),
10614 r.intent.getAction(),
10615 r.nextReceiver - 1,
10616 ((ResolveInfo)curReceiver).toString());
10617 }
10618 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010619 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010621 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010622 System.identityHashCode(r),
10623 r.intent.getAction(),
10624 r.nextReceiver,
10625 "NONE");
10626 }
10627 }
10628
Jeff Brown4d94a762010-09-23 11:33:28 -070010629 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10630 if (! mPendingBroadcastTimeoutMessage) {
10631 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10632 mHandler.sendMessageAtTime(msg, timeoutTime);
10633 mPendingBroadcastTimeoutMessage = true;
10634 }
10635 }
10636
10637 private final void cancelBroadcastTimeoutLocked() {
10638 if (mPendingBroadcastTimeoutMessage) {
10639 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10640 mPendingBroadcastTimeoutMessage = false;
10641 }
10642 }
10643
10644 private final void broadcastTimeoutLocked(boolean fromMsg) {
10645 if (fromMsg) {
10646 mPendingBroadcastTimeoutMessage = false;
10647 }
10648
10649 if (mOrderedBroadcasts.size() == 0) {
10650 return;
10651 }
10652
10653 long now = SystemClock.uptimeMillis();
10654 BroadcastRecord r = mOrderedBroadcasts.get(0);
10655 if (fromMsg) {
10656 if (mDidDexOpt) {
10657 // Delay timeouts until dexopt finishes.
10658 mDidDexOpt = false;
10659 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10660 setBroadcastTimeoutLocked(timeoutTime);
10661 return;
10662 }
10663 if (! mProcessesReady) {
10664 // Only process broadcast timeouts if the system is ready. That way
10665 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10666 // to do heavy lifting for system up.
10667 return;
10668 }
10669
10670 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10671 if (timeoutTime > now) {
10672 // We can observe premature timeouts because we do not cancel and reset the
10673 // broadcast timeout message after each receiver finishes. Instead, we set up
10674 // an initial timeout then kick it down the road a little further as needed
10675 // when it expires.
10676 if (DEBUG_BROADCAST) Slog.v(TAG,
10677 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10678 + timeoutTime);
10679 setBroadcastTimeoutLocked(timeoutTime);
10680 return;
10681 }
10682 }
10683
10684 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10685 + ", started " + (now - r.receiverTime) + "ms ago");
10686 r.receiverTime = now;
10687 r.anrCount++;
10688
10689 // Current receiver has passed its expiration date.
10690 if (r.nextReceiver <= 0) {
10691 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10692 return;
10693 }
10694
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010695 ProcessRecord app = null;
10696 String anrMessage = null;
10697
Jeff Brown4d94a762010-09-23 11:33:28 -070010698 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10699 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10700 logBroadcastReceiverDiscardLocked(r);
10701 if (curReceiver instanceof BroadcastFilter) {
10702 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10703 if (bf.receiverList.pid != 0
10704 && bf.receiverList.pid != MY_PID) {
10705 synchronized (this.mPidsSelfLocked) {
10706 app = this.mPidsSelfLocked.get(
10707 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010709 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010710 } else {
10711 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010712 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010713
Jeff Brown4d94a762010-09-23 11:33:28 -070010714 if (app != null) {
10715 anrMessage = "Broadcast of " + r.intent.toString();
10716 }
10717
10718 if (mPendingBroadcast == r) {
10719 mPendingBroadcast = null;
10720 }
10721
10722 // Move on to the next receiver.
10723 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10724 r.resultExtras, r.resultAbort, true);
10725 scheduleBroadcastsLocked();
10726
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010727 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010728 // Post the ANR to the handler since we do not want to process ANRs while
10729 // potentially holding our lock.
10730 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010732 }
10733
10734 private final void processCurBroadcastLocked(BroadcastRecord r,
10735 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010736 if (DEBUG_BROADCAST) Slog.v(TAG,
10737 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010738 if (app.thread == null) {
10739 throw new RemoteException();
10740 }
10741 r.receiver = app.thread.asBinder();
10742 r.curApp = app;
10743 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010744 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010745
10746 // Tell the application to launch this receiver.
10747 r.intent.setComponent(r.curComponent);
10748
10749 boolean started = false;
10750 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010751 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010752 "Delivering to component " + r.curComponent
10753 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010754 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10756 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010757 if (DEBUG_BROADCAST) Slog.v(TAG,
10758 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010759 started = true;
10760 } finally {
10761 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010762 if (DEBUG_BROADCAST) Slog.v(TAG,
10763 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 r.receiver = null;
10765 r.curApp = null;
10766 app.curReceiver = null;
10767 }
10768 }
10769
10770 }
10771
Jeff Brown4d94a762010-09-23 11:33:28 -070010772 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010773 Intent intent, int resultCode, String data, Bundle extras,
10774 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010775 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010776 if (app != null && app.thread != null) {
10777 // If we have an app thread, do the call through that so it is
10778 // correctly ordered with other one-way calls.
10779 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010780 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010781 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010782 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010783 }
10784 }
10785
Jeff Brown4d94a762010-09-23 11:33:28 -070010786 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010787 BroadcastFilter filter, boolean ordered) {
10788 boolean skip = false;
10789 if (filter.requiredPermission != null) {
10790 int perm = checkComponentPermission(filter.requiredPermission,
10791 r.callingPid, r.callingUid, -1);
10792 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010793 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 + r.intent.toString()
10795 + " from " + r.callerPackage + " (pid="
10796 + r.callingPid + ", uid=" + r.callingUid + ")"
10797 + " requires " + filter.requiredPermission
10798 + " due to registered receiver " + filter);
10799 skip = true;
10800 }
10801 }
10802 if (r.requiredPermission != null) {
10803 int perm = checkComponentPermission(r.requiredPermission,
10804 filter.receiverList.pid, filter.receiverList.uid, -1);
10805 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010806 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010807 + r.intent.toString()
10808 + " to " + filter.receiverList.app
10809 + " (pid=" + filter.receiverList.pid
10810 + ", uid=" + filter.receiverList.uid + ")"
10811 + " requires " + r.requiredPermission
10812 + " due to sender " + r.callerPackage
10813 + " (uid " + r.callingUid + ")");
10814 skip = true;
10815 }
10816 }
10817
10818 if (!skip) {
10819 // If this is not being sent as an ordered broadcast, then we
10820 // don't want to touch the fields that keep track of the current
10821 // state of ordered broadcasts.
10822 if (ordered) {
10823 r.receiver = filter.receiverList.receiver.asBinder();
10824 r.curFilter = filter;
10825 filter.receiverList.curBroadcast = r;
10826 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010827 if (filter.receiverList.app != null) {
10828 // Bump hosting application to no longer be in background
10829 // scheduling class. Note that we can't do that if there
10830 // isn't an app... but we can only be in that case for
10831 // things that directly call the IActivityManager API, which
10832 // are already core system stuff so don't matter for this.
10833 r.curApp = filter.receiverList.app;
10834 filter.receiverList.app.curReceiver = r;
10835 updateOomAdjLocked();
10836 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010837 }
10838 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010839 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010840 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010841 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010842 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010843 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010844 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010845 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010846 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010847 if (ordered) {
10848 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10849 }
10850 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010851 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010852 if (ordered) {
10853 r.receiver = null;
10854 r.curFilter = null;
10855 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010856 if (filter.receiverList.app != null) {
10857 filter.receiverList.app.curReceiver = null;
10858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 }
10860 }
10861 }
10862 }
10863
Dianne Hackborn12527f92009-11-11 17:39:50 -080010864 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10865 if (r.callingUid < 0) {
10866 // This was from a registerReceiver() call; ignore it.
10867 return;
10868 }
10869 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10870 MAX_BROADCAST_HISTORY-1);
10871 r.finishTime = SystemClock.uptimeMillis();
10872 mBroadcastHistory[0] = r;
10873 }
10874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010875 private final void processNextBroadcast(boolean fromMsg) {
10876 synchronized(this) {
10877 BroadcastRecord r;
10878
Joe Onorato8a9b2202010-02-26 18:56:32 -080010879 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010880 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010881 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882
10883 updateCpuStats();
10884
10885 if (fromMsg) {
10886 mBroadcastsScheduled = false;
10887 }
10888
10889 // First, deliver any non-serialized broadcasts right away.
10890 while (mParallelBroadcasts.size() > 0) {
10891 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010892 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010894 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010895 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010896 for (int i=0; i<N; i++) {
10897 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010898 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010899 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010900 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070010901 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010902 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010903 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010904 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010905 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 }
10907
10908 // Now take care of the next serialized one...
10909
10910 // If we are waiting for a process to come up to handle the next
10911 // broadcast, then do nothing at this point. Just in case, we
10912 // check that the process we're waiting for still exists.
10913 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010914 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010915 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010916 + mPendingBroadcast.curApp);
10917 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010918
10919 boolean isDead;
10920 synchronized (mPidsSelfLocked) {
10921 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10922 }
10923 if (!isDead) {
10924 // It's still alive, so keep waiting
10925 return;
10926 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010927 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010929 mPendingBroadcast.state = BroadcastRecord.IDLE;
10930 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010931 mPendingBroadcast = null;
10932 }
10933 }
10934
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010935 boolean looped = false;
10936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010937 do {
10938 if (mOrderedBroadcasts.size() == 0) {
10939 // No more broadcasts pending, so all done!
10940 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010941 if (looped) {
10942 // If we had finished the last ordered broadcast, then
10943 // make sure all processes have correct oom and sched
10944 // adjustments.
10945 updateOomAdjLocked();
10946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010947 return;
10948 }
10949 r = mOrderedBroadcasts.get(0);
10950 boolean forceReceive = false;
10951
10952 // Ensure that even if something goes awry with the timeout
10953 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010954 // and continue to make progress.
10955 //
10956 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070010957 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010958 // one time heavy lifting after system upgrades and can take
10959 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010961 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010962 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 if ((numReceivers > 0) &&
10964 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010965 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 + " now=" + now
10967 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010968 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 + " intent=" + r.intent
10970 + " numReceivers=" + numReceivers
10971 + " nextReceiver=" + r.nextReceiver
10972 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070010973 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010974 forceReceive = true;
10975 r.state = BroadcastRecord.IDLE;
10976 }
10977 }
10978
10979 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010980 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010981 "processNextBroadcast() called when not idle (state="
10982 + r.state + ")");
10983 return;
10984 }
10985
10986 if (r.receivers == null || r.nextReceiver >= numReceivers
10987 || r.resultAbort || forceReceive) {
10988 // No more receivers for this broadcast! Send the final
10989 // result if requested...
10990 if (r.resultTo != null) {
10991 try {
10992 if (DEBUG_BROADCAST) {
10993 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010994 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010995 + " seq=" + seq + " app=" + r.callerApp);
10996 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010997 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010999 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011000 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011001 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011002 }
11003 }
11004
Joe Onorato8a9b2202010-02-26 18:56:32 -080011005 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011006 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007
Joe Onorato8a9b2202010-02-26 18:56:32 -080011008 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011009 + r);
11010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011012 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013 mOrderedBroadcasts.remove(0);
11014 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011015 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 continue;
11017 }
11018 } while (r == null);
11019
11020 // Get the next receiver...
11021 int recIdx = r.nextReceiver++;
11022
11023 // Keep track of when this receiver started, and make sure there
11024 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011025 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011027 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011028
Joe Onorato8a9b2202010-02-26 18:56:32 -080011029 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011030 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011031 }
11032 if (! mPendingBroadcastTimeoutMessage) {
11033 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011034 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011035 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11036 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011037 }
11038
11039 Object nextReceiver = r.receivers.get(recIdx);
11040 if (nextReceiver instanceof BroadcastFilter) {
11041 // Simple case: this is a registered receiver who gets
11042 // a direct call.
11043 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011044 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011045 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011047 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011048 if (r.receiver == null || !r.ordered) {
11049 // The receiver has already finished, so schedule to
11050 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011051 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11052 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 r.state = BroadcastRecord.IDLE;
11054 scheduleBroadcastsLocked();
11055 }
11056 return;
11057 }
11058
11059 // Hard case: need to instantiate the receiver, possibly
11060 // starting its application process to host it.
11061
11062 ResolveInfo info =
11063 (ResolveInfo)nextReceiver;
11064
11065 boolean skip = false;
11066 int perm = checkComponentPermission(info.activityInfo.permission,
11067 r.callingPid, r.callingUid,
11068 info.activityInfo.exported
11069 ? -1 : info.activityInfo.applicationInfo.uid);
11070 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011071 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011072 + r.intent.toString()
11073 + " from " + r.callerPackage + " (pid=" + r.callingPid
11074 + ", uid=" + r.callingUid + ")"
11075 + " requires " + info.activityInfo.permission
11076 + " due to receiver " + info.activityInfo.packageName
11077 + "/" + info.activityInfo.name);
11078 skip = true;
11079 }
11080 if (r.callingUid != Process.SYSTEM_UID &&
11081 r.requiredPermission != null) {
11082 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011083 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 checkPermission(r.requiredPermission,
11085 info.activityInfo.applicationInfo.packageName);
11086 } catch (RemoteException e) {
11087 perm = PackageManager.PERMISSION_DENIED;
11088 }
11089 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011090 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 + r.intent + " to "
11092 + info.activityInfo.applicationInfo.packageName
11093 + " requires " + r.requiredPermission
11094 + " due to sender " + r.callerPackage
11095 + " (uid " + r.callingUid + ")");
11096 skip = true;
11097 }
11098 }
11099 if (r.curApp != null && r.curApp.crashing) {
11100 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011101 if (DEBUG_BROADCAST) Slog.v(TAG,
11102 "Skipping deliver ordered " + r + " to " + r.curApp
11103 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 skip = true;
11105 }
11106
11107 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011108 if (DEBUG_BROADCAST) Slog.v(TAG,
11109 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 r.receiver = null;
11111 r.curFilter = null;
11112 r.state = BroadcastRecord.IDLE;
11113 scheduleBroadcastsLocked();
11114 return;
11115 }
11116
11117 r.state = BroadcastRecord.APP_RECEIVE;
11118 String targetProcess = info.activityInfo.processName;
11119 r.curComponent = new ComponentName(
11120 info.activityInfo.applicationInfo.packageName,
11121 info.activityInfo.name);
11122 r.curReceiver = info.activityInfo;
11123
11124 // Is this receiver's application already running?
11125 ProcessRecord app = getProcessRecordLocked(targetProcess,
11126 info.activityInfo.applicationInfo.uid);
11127 if (app != null && app.thread != null) {
11128 try {
11129 processCurBroadcastLocked(r, app);
11130 return;
11131 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011132 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011133 + r.curComponent, e);
11134 }
11135
11136 // If a dead object exception was thrown -- fall through to
11137 // restart the application.
11138 }
11139
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011140 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011141 if (DEBUG_BROADCAST) Slog.v(TAG,
11142 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011143 if ((r.curApp=startProcessLocked(targetProcess,
11144 info.activityInfo.applicationInfo, true,
11145 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011146 "broadcast", r.curComponent,
11147 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11148 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 // Ah, this recipient is unavailable. Finish it if necessary,
11150 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011151 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 + info.activityInfo.applicationInfo.packageName + "/"
11153 + info.activityInfo.applicationInfo.uid + " for broadcast "
11154 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011155 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11157 r.resultExtras, r.resultAbort, true);
11158 scheduleBroadcastsLocked();
11159 r.state = BroadcastRecord.IDLE;
11160 return;
11161 }
11162
11163 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011164 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 }
11166 }
11167
11168 // =========================================================
11169 // INSTRUMENTATION
11170 // =========================================================
11171
11172 public boolean startInstrumentation(ComponentName className,
11173 String profileFile, int flags, Bundle arguments,
11174 IInstrumentationWatcher watcher) {
11175 // Refuse possible leaked file descriptors
11176 if (arguments != null && arguments.hasFileDescriptors()) {
11177 throw new IllegalArgumentException("File descriptors passed in Bundle");
11178 }
11179
11180 synchronized(this) {
11181 InstrumentationInfo ii = null;
11182 ApplicationInfo ai = null;
11183 try {
11184 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011185 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011187 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 } catch (PackageManager.NameNotFoundException e) {
11189 }
11190 if (ii == null) {
11191 reportStartInstrumentationFailure(watcher, className,
11192 "Unable to find instrumentation info for: " + className);
11193 return false;
11194 }
11195 if (ai == null) {
11196 reportStartInstrumentationFailure(watcher, className,
11197 "Unable to find instrumentation target package: " + ii.targetPackage);
11198 return false;
11199 }
11200
11201 int match = mContext.getPackageManager().checkSignatures(
11202 ii.targetPackage, ii.packageName);
11203 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11204 String msg = "Permission Denial: starting instrumentation "
11205 + className + " from pid="
11206 + Binder.getCallingPid()
11207 + ", uid=" + Binder.getCallingPid()
11208 + " not allowed because package " + ii.packageName
11209 + " does not have a signature matching the target "
11210 + ii.targetPackage;
11211 reportStartInstrumentationFailure(watcher, className, msg);
11212 throw new SecurityException(msg);
11213 }
11214
11215 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011216 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011217 ProcessRecord app = addAppLocked(ai);
11218 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011219 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 app.instrumentationProfileFile = profileFile;
11221 app.instrumentationArguments = arguments;
11222 app.instrumentationWatcher = watcher;
11223 app.instrumentationResultClass = className;
11224 Binder.restoreCallingIdentity(origId);
11225 }
11226
11227 return true;
11228 }
11229
11230 /**
11231 * Report errors that occur while attempting to start Instrumentation. Always writes the
11232 * error to the logs, but if somebody is watching, send the report there too. This enables
11233 * the "am" command to report errors with more information.
11234 *
11235 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11236 * @param cn The component name of the instrumentation.
11237 * @param report The error report.
11238 */
11239 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11240 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011241 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242 try {
11243 if (watcher != null) {
11244 Bundle results = new Bundle();
11245 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11246 results.putString("Error", report);
11247 watcher.instrumentationStatus(cn, -1, results);
11248 }
11249 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011250 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011251 }
11252 }
11253
11254 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11255 if (app.instrumentationWatcher != null) {
11256 try {
11257 // NOTE: IInstrumentationWatcher *must* be oneway here
11258 app.instrumentationWatcher.instrumentationFinished(
11259 app.instrumentationClass,
11260 resultCode,
11261 results);
11262 } catch (RemoteException e) {
11263 }
11264 }
11265 app.instrumentationWatcher = null;
11266 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011267 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011268 app.instrumentationProfileFile = null;
11269 app.instrumentationArguments = null;
11270
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011271 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 }
11273
11274 public void finishInstrumentation(IApplicationThread target,
11275 int resultCode, Bundle results) {
11276 // Refuse possible leaked file descriptors
11277 if (results != null && results.hasFileDescriptors()) {
11278 throw new IllegalArgumentException("File descriptors passed in Intent");
11279 }
11280
11281 synchronized(this) {
11282 ProcessRecord app = getRecordForAppLocked(target);
11283 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011284 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 return;
11286 }
11287 final long origId = Binder.clearCallingIdentity();
11288 finishInstrumentationLocked(app, resultCode, results);
11289 Binder.restoreCallingIdentity(origId);
11290 }
11291 }
11292
11293 // =========================================================
11294 // CONFIGURATION
11295 // =========================================================
11296
11297 public ConfigurationInfo getDeviceConfigurationInfo() {
11298 ConfigurationInfo config = new ConfigurationInfo();
11299 synchronized (this) {
11300 config.reqTouchScreen = mConfiguration.touchscreen;
11301 config.reqKeyboardType = mConfiguration.keyboard;
11302 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011303 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11304 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011305 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11306 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011307 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11308 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011309 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11310 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011311 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 }
11313 return config;
11314 }
11315
11316 public Configuration getConfiguration() {
11317 Configuration ci;
11318 synchronized(this) {
11319 ci = new Configuration(mConfiguration);
11320 }
11321 return ci;
11322 }
11323
11324 public void updateConfiguration(Configuration values) {
11325 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11326 "updateConfiguration()");
11327
11328 synchronized(this) {
11329 if (values == null && mWindowManager != null) {
11330 // sentinel: fetch the current configuration from the window manager
11331 values = mWindowManager.computeNewConfiguration();
11332 }
11333
11334 final long origId = Binder.clearCallingIdentity();
11335 updateConfigurationLocked(values, null);
11336 Binder.restoreCallingIdentity(origId);
11337 }
11338 }
11339
11340 /**
11341 * Do either or both things: (1) change the current configuration, and (2)
11342 * make sure the given activity is running with the (now) current
11343 * configuration. Returns true if the activity has been left running, or
11344 * false if <var>starting</var> is being destroyed to match the new
11345 * configuration.
11346 */
11347 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011348 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011349 int changes = 0;
11350
11351 boolean kept = true;
11352
11353 if (values != null) {
11354 Configuration newConfig = new Configuration(mConfiguration);
11355 changes = newConfig.updateFrom(values);
11356 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011357 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011358 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011359 }
11360
Doug Zongker2bec3d42009-12-04 12:52:44 -080011361 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362
11363 if (values.locale != null) {
11364 saveLocaleLocked(values.locale,
11365 !values.locale.equals(mConfiguration.locale),
11366 values.userSetLocale);
11367 }
11368
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011369 mConfigurationSeq++;
11370 if (mConfigurationSeq <= 0) {
11371 mConfigurationSeq = 1;
11372 }
11373 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011374 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011375 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011376
11377 AttributeCache ac = AttributeCache.instance();
11378 if (ac != null) {
11379 ac.updateConfiguration(mConfiguration);
11380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011381
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011382 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11383 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11384 msg.obj = new Configuration(mConfiguration);
11385 mHandler.sendMessage(msg);
11386 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011388 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11389 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390 try {
11391 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011392 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011393 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011394 app.thread.scheduleConfigurationChanged(mConfiguration);
11395 }
11396 } catch (Exception e) {
11397 }
11398 }
11399 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011400 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11401 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011402 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11403 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011404 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11405 broadcastIntentLocked(null, null,
11406 new Intent(Intent.ACTION_LOCALE_CHANGED),
11407 null, null, 0, null, null,
11408 null, false, false, MY_PID, Process.SYSTEM_UID);
11409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410 }
11411 }
11412
11413 if (changes != 0 && starting == null) {
11414 // If the configuration changed, and the caller is not already
11415 // in the process of starting an activity, then find the top
11416 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011417 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 }
11419
11420 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011421 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011422 if (kept) {
11423 // If this didn't result in the starting activity being
11424 // destroyed, then we need to make sure at this point that all
11425 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011426 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011427 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011428 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011429 }
11430 }
11431
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011432 if (values != null && mWindowManager != null) {
11433 mWindowManager.setNewConfiguration(mConfiguration);
11434 }
11435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 return kept;
11437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011438
11439 /**
11440 * Save the locale. You must be inside a synchronized (this) block.
11441 */
11442 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11443 if(isDiff) {
11444 SystemProperties.set("user.language", l.getLanguage());
11445 SystemProperties.set("user.region", l.getCountry());
11446 }
11447
11448 if(isPersist) {
11449 SystemProperties.set("persist.sys.language", l.getLanguage());
11450 SystemProperties.set("persist.sys.country", l.getCountry());
11451 SystemProperties.set("persist.sys.localevar", l.getVariant());
11452 }
11453 }
11454
11455 // =========================================================
11456 // LIFETIME MANAGEMENT
11457 // =========================================================
11458
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011459 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11460 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011461 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011462 // This adjustment has already been computed. If we are calling
11463 // from the top, we may have already computed our adjustment with
11464 // an earlier hidden adjustment that isn't really for us... if
11465 // so, use the new hidden adjustment.
11466 if (!recursed && app.hidden) {
11467 app.curAdj = hiddenAdj;
11468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011469 return app.curAdj;
11470 }
11471
11472 if (app.thread == null) {
11473 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011474 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011475 return (app.curAdj=EMPTY_APP_ADJ);
11476 }
11477
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011478 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11479 // The max adjustment doesn't allow this app to be anything
11480 // below foreground, so it is not worth doing work for it.
11481 app.adjType = "fixed";
11482 app.adjSeq = mAdjSeq;
11483 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011484 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011485 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11486 return (app.curAdj=app.maxAdj);
11487 }
11488
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011489 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011490 app.adjSource = null;
11491 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011492 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011493 app.empty = false;
11494 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011495
The Android Open Source Project4df24232009-03-05 14:34:35 -080011496 // Determine the importance of the process, starting with most
11497 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011498 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011499 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011501 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011502 // The last app on the list is the foreground app.
11503 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011504 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011505 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011506 } else if (app.instrumentationClass != null) {
11507 // Don't want to kill running instrumentation.
11508 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011509 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011510 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 } else if (app.curReceiver != null ||
11512 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11513 // An app that is currently receiving a broadcast also
11514 // counts as being in the foreground.
11515 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011516 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011517 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 } else if (app.executingServices.size() > 0) {
11519 // An app that is currently executing a service callback also
11520 // counts as being in the foreground.
11521 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011522 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011523 app.adjType = "exec-service";
11524 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011525 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011526 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011527 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011528 app.adjType = "foreground-service";
11529 } else if (app.forcingToForeground != null) {
11530 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011531 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011532 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011533 app.adjType = "force-foreground";
11534 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011535 } else if (app == mHeavyWeightProcess) {
11536 // We don't want to kill the current heavy-weight process.
11537 adj = HEAVY_WEIGHT_APP_ADJ;
11538 schedGroup = Process.THREAD_GROUP_DEFAULT;
11539 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011540 } else if (app == mHomeProcess) {
11541 // This process is hosting what we currently consider to be the
11542 // home app, so we don't want to let it go into the background.
11543 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011544 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011545 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 } else if ((N=app.activities.size()) != 0) {
11547 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011548 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011550 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011551 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011552 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011554 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011555 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011556 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011557 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011558 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011559 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011560 break;
11561 }
11562 }
11563 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011564 // A very not-needed process. If this is lower in the lru list,
11565 // we will push it in to the empty bucket.
11566 app.hidden = true;
11567 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011568 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011569 adj = hiddenAdj;
11570 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571 }
11572
Joe Onorato8a9b2202010-02-26 18:56:32 -080011573 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011574
The Android Open Source Project4df24232009-03-05 14:34:35 -080011575 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 // there are applications dependent on our services or providers, but
11577 // this gives us a baseline and makes sure we don't get into an
11578 // infinite recursion.
11579 app.adjSeq = mAdjSeq;
11580 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011581
Christopher Tate6fa95972009-06-05 18:43:55 -070011582 if (mBackupTarget != null && app == mBackupTarget.app) {
11583 // If possible we want to avoid killing apps while they're being backed up
11584 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011585 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011586 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011587 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011588 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011589 }
11590 }
11591
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011592 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11593 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 final long now = SystemClock.uptimeMillis();
11595 // This process is more important if the top activity is
11596 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011597 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011599 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011600 if (s.startRequested) {
11601 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11602 // This service has seen some activity within
11603 // recent memory, so we will keep its process ahead
11604 // of the background processes.
11605 if (adj > SECONDARY_SERVER_ADJ) {
11606 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011607 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011608 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011609 }
11610 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011611 // If we have let the service slide into the background
11612 // state, still have some text describing what it is doing
11613 // even though the service no longer has an impact.
11614 if (adj > SECONDARY_SERVER_ADJ) {
11615 app.adjType = "started-bg-services";
11616 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011617 // Don't kill this process because it is doing work; it
11618 // has said it is doing work.
11619 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011620 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011621 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11622 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011623 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011624 = s.connections.values().iterator();
11625 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011626 ArrayList<ConnectionRecord> clist = kt.next();
11627 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11628 // XXX should compute this based on the max of
11629 // all connected clients.
11630 ConnectionRecord cr = clist.get(i);
11631 if (cr.binding.client == app) {
11632 // Binding to ourself is not interesting.
11633 continue;
11634 }
11635 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11636 ProcessRecord client = cr.binding.client;
11637 int myHiddenAdj = hiddenAdj;
11638 if (myHiddenAdj > client.hiddenAdj) {
11639 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11640 myHiddenAdj = client.hiddenAdj;
11641 } else {
11642 myHiddenAdj = VISIBLE_APP_ADJ;
11643 }
11644 }
11645 int clientAdj = computeOomAdjLocked(
11646 client, myHiddenAdj, TOP_APP, true);
11647 if (adj > clientAdj) {
11648 adj = clientAdj >= VISIBLE_APP_ADJ
11649 ? clientAdj : VISIBLE_APP_ADJ;
11650 if (!client.hidden) {
11651 app.hidden = false;
11652 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011653 if (client.keeping) {
11654 app.keeping = true;
11655 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011656 app.adjType = "service";
11657 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11658 .REASON_SERVICE_IN_USE;
11659 app.adjSource = cr.binding.client;
11660 app.adjTarget = s.name;
11661 }
11662 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11663 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11664 schedGroup = Process.THREAD_GROUP_DEFAULT;
11665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 }
11667 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011668 ActivityRecord a = cr.activity;
11669 //if (a != null) {
11670 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11671 //}
11672 if (a != null && adj > FOREGROUND_APP_ADJ &&
11673 (a.state == ActivityState.RESUMED
11674 || a.state == ActivityState.PAUSING)) {
11675 adj = FOREGROUND_APP_ADJ;
11676 schedGroup = Process.THREAD_GROUP_DEFAULT;
11677 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011678 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011679 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11680 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011681 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011682 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011684 }
11685 }
11686 }
11687 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011688
Dianne Hackborn287952c2010-09-22 22:34:31 -070011689 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011690 // would like to avoid killing it unless it would prevent the current
11691 // application from running. By default we put the process in
11692 // with the rest of the background processes; as we scan through
11693 // its services we may bump it up from there.
11694 if (adj > hiddenAdj) {
11695 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011696 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011697 app.adjType = "bg-services";
11698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011699 }
11700
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011701 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11702 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011703 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011704 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11705 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011706 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 if (cpr.clients.size() != 0) {
11708 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11709 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11710 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011711 if (client == app) {
11712 // Being our own client is not interesting.
11713 continue;
11714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011715 int myHiddenAdj = hiddenAdj;
11716 if (myHiddenAdj > client.hiddenAdj) {
11717 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11718 myHiddenAdj = client.hiddenAdj;
11719 } else {
11720 myHiddenAdj = FOREGROUND_APP_ADJ;
11721 }
11722 }
11723 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011724 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011725 if (adj > clientAdj) {
11726 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011727 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011728 if (!client.hidden) {
11729 app.hidden = false;
11730 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011731 if (client.keeping) {
11732 app.keeping = true;
11733 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011734 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011735 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11736 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011737 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011738 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011739 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011740 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11741 schedGroup = Process.THREAD_GROUP_DEFAULT;
11742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011743 }
11744 }
11745 // If the provider has external (non-framework) process
11746 // dependencies, ensure that its adjustment is at least
11747 // FOREGROUND_APP_ADJ.
11748 if (cpr.externals != 0) {
11749 if (adj > FOREGROUND_APP_ADJ) {
11750 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011751 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011752 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011753 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011754 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011755 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011756 }
11757 }
11758 }
11759 }
11760
11761 app.curRawAdj = adj;
11762
Joe Onorato8a9b2202010-02-26 18:56:32 -080011763 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011764 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11765 if (adj > app.maxAdj) {
11766 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011767 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011768 schedGroup = Process.THREAD_GROUP_DEFAULT;
11769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011770 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011771 if (adj < HIDDEN_APP_MIN_ADJ) {
11772 app.keeping = true;
11773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011774
11775 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011776 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011778 return adj;
11779 }
11780
11781 /**
11782 * Ask a given process to GC right now.
11783 */
11784 final void performAppGcLocked(ProcessRecord app) {
11785 try {
11786 app.lastRequestedGc = SystemClock.uptimeMillis();
11787 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011788 if (app.reportLowMemory) {
11789 app.reportLowMemory = false;
11790 app.thread.scheduleLowMemory();
11791 } else {
11792 app.thread.processInBackground();
11793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794 }
11795 } catch (Exception e) {
11796 // whatever.
11797 }
11798 }
11799
11800 /**
11801 * Returns true if things are idle enough to perform GCs.
11802 */
Josh Bartel7f208742010-02-25 11:01:44 -060011803 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 return mParallelBroadcasts.size() == 0
11805 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011806 && (mSleeping || (mMainStack.mResumedActivity != null &&
11807 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 }
11809
11810 /**
11811 * Perform GCs on all processes that are waiting for it, but only
11812 * if things are idle.
11813 */
11814 final void performAppGcsLocked() {
11815 final int N = mProcessesToGc.size();
11816 if (N <= 0) {
11817 return;
11818 }
Josh Bartel7f208742010-02-25 11:01:44 -060011819 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011820 while (mProcessesToGc.size() > 0) {
11821 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011822 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011823 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11824 <= SystemClock.uptimeMillis()) {
11825 // To avoid spamming the system, we will GC processes one
11826 // at a time, waiting a few seconds between each.
11827 performAppGcLocked(proc);
11828 scheduleAppGcsLocked();
11829 return;
11830 } else {
11831 // It hasn't been long enough since we last GCed this
11832 // process... put it in the list to wait for its time.
11833 addProcessToGcListLocked(proc);
11834 break;
11835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011836 }
11837 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011838
11839 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011840 }
11841 }
11842
11843 /**
11844 * If all looks good, perform GCs on all processes waiting for them.
11845 */
11846 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011847 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011848 performAppGcsLocked();
11849 return;
11850 }
11851 // Still not idle, wait some more.
11852 scheduleAppGcsLocked();
11853 }
11854
11855 /**
11856 * Schedule the execution of all pending app GCs.
11857 */
11858 final void scheduleAppGcsLocked() {
11859 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011860
11861 if (mProcessesToGc.size() > 0) {
11862 // Schedule a GC for the time to the next process.
11863 ProcessRecord proc = mProcessesToGc.get(0);
11864 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11865
11866 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11867 long now = SystemClock.uptimeMillis();
11868 if (when < (now+GC_TIMEOUT)) {
11869 when = now + GC_TIMEOUT;
11870 }
11871 mHandler.sendMessageAtTime(msg, when);
11872 }
11873 }
11874
11875 /**
11876 * Add a process to the array of processes waiting to be GCed. Keeps the
11877 * list in sorted order by the last GC time. The process can't already be
11878 * on the list.
11879 */
11880 final void addProcessToGcListLocked(ProcessRecord proc) {
11881 boolean added = false;
11882 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11883 if (mProcessesToGc.get(i).lastRequestedGc <
11884 proc.lastRequestedGc) {
11885 added = true;
11886 mProcessesToGc.add(i+1, proc);
11887 break;
11888 }
11889 }
11890 if (!added) {
11891 mProcessesToGc.add(0, proc);
11892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011893 }
11894
11895 /**
11896 * Set up to ask a process to GC itself. This will either do it
11897 * immediately, or put it on the list of processes to gc the next
11898 * time things are idle.
11899 */
11900 final void scheduleAppGcLocked(ProcessRecord app) {
11901 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011902 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 return;
11904 }
11905 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011906 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011907 scheduleAppGcsLocked();
11908 }
11909 }
11910
Dianne Hackborn287952c2010-09-22 22:34:31 -070011911 final void checkExcessivePowerUsageLocked(boolean doKills) {
11912 updateCpuStatsNow();
11913
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011914 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011915 boolean doWakeKills = doKills;
11916 boolean doCpuKills = doKills;
11917 if (mLastPowerCheckRealtime == 0) {
11918 doWakeKills = false;
11919 }
11920 if (mLastPowerCheckUptime == 0) {
11921 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011922 }
11923 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011924 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011925 }
11926 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011927 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
11928 final long curUptime = SystemClock.uptimeMillis();
11929 final long uptimeSince = curUptime - mLastPowerCheckUptime;
11930 mLastPowerCheckRealtime = curRealtime;
11931 mLastPowerCheckUptime = curUptime;
11932 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
11933 doWakeKills = false;
11934 }
11935 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
11936 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011937 }
11938 int i = mLruProcesses.size();
11939 while (i > 0) {
11940 i--;
11941 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011942 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011943 long wtime;
11944 synchronized (stats) {
11945 wtime = stats.getProcessWakeTime(app.info.uid,
11946 app.pid, curRealtime);
11947 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011948 long wtimeUsed = wtime - app.lastWakeTime;
11949 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
11950 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011951 StringBuilder sb = new StringBuilder(128);
11952 sb.append("Wake for ");
11953 app.toShortString(sb);
11954 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011955 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011956 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011957 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011958 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011959 sb.append((wtimeUsed*100)/realtimeSince);
11960 sb.append("%)");
11961 Slog.i(TAG, sb.toString());
11962 sb.setLength(0);
11963 sb.append("CPU for ");
11964 app.toShortString(sb);
11965 sb.append(": over ");
11966 TimeUtils.formatDuration(uptimeSince, sb);
11967 sb.append(" used ");
11968 TimeUtils.formatDuration(cputimeUsed, sb);
11969 sb.append(" (");
11970 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011971 sb.append("%)");
11972 Slog.i(TAG, sb.toString());
11973 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011974 // If a process has held a wake lock for more
11975 // than 50% of the time during this period,
11976 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070011977 if (doWakeKills && realtimeSince > 0
11978 && ((wtimeUsed*100)/realtimeSince) >= 50) {
11979 synchronized (stats) {
11980 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
11981 realtimeSince, wtimeUsed);
11982 }
11983 Slog.w(TAG, "Excessive wake lock in " + app.processName
11984 + " (pid " + app.pid + "): held " + wtimeUsed
11985 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011986 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11987 app.processName, app.setAdj, "excessive wake lock");
11988 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011989 } else if (doCpuKills && uptimeSince > 0
11990 && ((cputimeUsed*100)/uptimeSince) >= 50) {
11991 synchronized (stats) {
11992 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
11993 uptimeSince, cputimeUsed);
11994 }
11995 Slog.w(TAG, "Excessive CPU in " + app.processName
11996 + " (pid " + app.pid + "): used " + cputimeUsed
11997 + " during " + uptimeSince);
11998 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11999 app.processName, app.setAdj, "excessive cpu");
12000 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012001 } else {
12002 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012003 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012004 }
12005 }
12006 }
12007 }
12008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012009 private final boolean updateOomAdjLocked(
12010 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12011 app.hiddenAdj = hiddenAdj;
12012
12013 if (app.thread == null) {
12014 return true;
12015 }
12016
Dianne Hackborn287952c2010-09-22 22:34:31 -070012017 final boolean wasKeeping = app.keeping;
12018
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012019 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012021 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012022 if (app.curRawAdj != app.setRawAdj) {
12023 if (app.curRawAdj > FOREGROUND_APP_ADJ
12024 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12025 // If this app is transitioning from foreground to
12026 // non-foreground, have it do a gc.
12027 scheduleAppGcLocked(app);
12028 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12029 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12030 // Likewise do a gc when an app is moving in to the
12031 // background (such as a service stopping).
12032 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012033 }
12034
12035 if (wasKeeping && !app.keeping) {
12036 // This app is no longer something we want to keep. Note
12037 // its current wake lock time to later know to kill it if
12038 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012039 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12040 synchronized (stats) {
12041 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12042 app.pid, SystemClock.elapsedRealtime());
12043 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012044 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012045 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012047 app.setRawAdj = app.curRawAdj;
12048 }
12049 if (adj != app.setAdj) {
12050 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012051 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012052 TAG, "Set app " + app.processName +
12053 " oom adj to " + adj);
12054 app.setAdj = adj;
12055 } else {
12056 return false;
12057 }
12058 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012059 if (app.setSchedGroup != app.curSchedGroup) {
12060 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012061 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012062 "Setting process group of " + app.processName
12063 + " to " + app.curSchedGroup);
12064 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012065 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012066 try {
12067 Process.setProcessGroup(app.pid, app.curSchedGroup);
12068 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012069 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012070 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012071 e.printStackTrace();
12072 } finally {
12073 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012074 }
12075 }
12076 if (false) {
12077 if (app.thread != null) {
12078 try {
12079 app.thread.setSchedulingGroup(app.curSchedGroup);
12080 } catch (RemoteException e) {
12081 }
12082 }
12083 }
12084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012085 }
12086
12087 return true;
12088 }
12089
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012090 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012091 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012092 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012093 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012095 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012096 }
12097 }
12098 return resumedActivity;
12099 }
12100
12101 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012102 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012103 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12104 int curAdj = app.curAdj;
12105 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12106 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12107
12108 mAdjSeq++;
12109
12110 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12111 if (res) {
12112 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12113 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12114 if (nowHidden != wasHidden) {
12115 // Changed to/from hidden state, so apps after it in the LRU
12116 // list may also be changed.
12117 updateOomAdjLocked();
12118 }
12119 }
12120 return res;
12121 }
12122
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012123 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012124 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012125 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012126 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12127
12128 if (false) {
12129 RuntimeException e = new RuntimeException();
12130 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012131 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012132 }
12133
12134 mAdjSeq++;
12135
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012136 // Let's determine how many processes we have running vs.
12137 // how many slots we have for background processes; we may want
12138 // to put multiple processes in a slot of there are enough of
12139 // them.
12140 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12141 int factor = (mLruProcesses.size()-4)/numSlots;
12142 if (factor < 1) factor = 1;
12143 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012144 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012146 // First try updating the OOM adjustment for each of the
12147 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012148 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012149 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12150 while (i > 0) {
12151 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012152 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012153 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012154 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012155 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012156 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012157 step++;
12158 if (step >= factor) {
12159 step = 0;
12160 curHiddenAdj++;
12161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012162 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012163 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012164 if (!app.killedBackground) {
12165 numHidden++;
12166 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012167 Slog.i(TAG, "No longer want " + app.processName
12168 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012169 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12170 app.processName, app.setAdj, "too many background");
12171 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012172 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012173 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012174 }
12175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 } else {
12177 didOomAdj = false;
12178 }
12179 }
12180
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012181 // If we return false, we will fall back on killing processes to
12182 // have a fixed limit. Do this if a limit has been requested; else
12183 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012184 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12185 }
12186
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012187 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012188 synchronized (this) {
12189 int i;
12190
12191 // First remove any unused application processes whose package
12192 // has been removed.
12193 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12194 final ProcessRecord app = mRemovedProcesses.get(i);
12195 if (app.activities.size() == 0
12196 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012197 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012198 TAG, "Exiting empty application process "
12199 + app.processName + " ("
12200 + (app.thread != null ? app.thread.asBinder() : null)
12201 + ")\n");
12202 if (app.pid > 0 && app.pid != MY_PID) {
12203 Process.killProcess(app.pid);
12204 } else {
12205 try {
12206 app.thread.scheduleExit();
12207 } catch (Exception e) {
12208 // Ignore exceptions.
12209 }
12210 }
12211 cleanUpApplicationRecordLocked(app, false, -1);
12212 mRemovedProcesses.remove(i);
12213
12214 if (app.persistent) {
12215 if (app.persistent) {
12216 addAppLocked(app.info);
12217 }
12218 }
12219 }
12220 }
12221
12222 // Now try updating the OOM adjustment for each of the
12223 // application processes based on their current state.
12224 // If the setOomAdj() API is not supported, then go with our
12225 // back-up plan...
12226 if (!updateOomAdjLocked()) {
12227
12228 // Count how many processes are running services.
12229 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012230 for (i=mLruProcesses.size()-1; i>=0; i--) {
12231 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012232
12233 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012234 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012235 // Don't count processes holding services against our
12236 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012237 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012238 TAG, "Not trimming app " + app + " with services: "
12239 + app.services);
12240 numServiceProcs++;
12241 }
12242 }
12243
12244 int curMaxProcs = mProcessLimit;
12245 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12246 if (mAlwaysFinishActivities) {
12247 curMaxProcs = 1;
12248 }
12249 curMaxProcs += numServiceProcs;
12250
12251 // Quit as many processes as we can to get down to the desired
12252 // process count. First remove any processes that no longer
12253 // have activites running in them.
12254 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012255 i<mLruProcesses.size()
12256 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012257 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012258 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012259 // Quit an application only if it is not currently
12260 // running any activities.
12261 if (!app.persistent && app.activities.size() == 0
12262 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012263 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012264 TAG, "Exiting empty application process "
12265 + app.processName + " ("
12266 + (app.thread != null ? app.thread.asBinder() : null)
12267 + ")\n");
12268 if (app.pid > 0 && app.pid != MY_PID) {
12269 Process.killProcess(app.pid);
12270 } else {
12271 try {
12272 app.thread.scheduleExit();
12273 } catch (Exception e) {
12274 // Ignore exceptions.
12275 }
12276 }
12277 // todo: For now we assume the application is not buggy
12278 // or evil, and will quit as a result of our request.
12279 // Eventually we need to drive this off of the death
12280 // notification, and kill the process if it takes too long.
12281 cleanUpApplicationRecordLocked(app, false, i);
12282 i--;
12283 }
12284 }
12285
12286 // If we still have too many processes, now from the least
12287 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012288 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012289 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012290 " of " + curMaxProcs + " processes");
12291 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012292 i<mLruProcesses.size()
12293 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012294 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012295 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012296 // Quit the application only if we have a state saved for
12297 // all of its activities.
12298 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012299 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012300 int NUMA = app.activities.size();
12301 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012302 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012303 TAG, "Looking to quit " + app.processName);
12304 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012305 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012306 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012307 TAG, " " + r.intent.getComponent().flattenToShortString()
12308 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12309 canQuit = (r.haveState || !r.stateNotNeeded)
12310 && !r.visible && r.stopped;
12311 }
12312 if (canQuit) {
12313 // Finish all of the activities, and then the app itself.
12314 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012315 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012316 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012317 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012318 }
12319 r.resultTo = null;
12320 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012321 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012322 + app.processName + " ("
12323 + (app.thread != null ? app.thread.asBinder() : null)
12324 + ")\n");
12325 if (app.pid > 0 && app.pid != MY_PID) {
12326 Process.killProcess(app.pid);
12327 } else {
12328 try {
12329 app.thread.scheduleExit();
12330 } catch (Exception e) {
12331 // Ignore exceptions.
12332 }
12333 }
12334 // todo: For now we assume the application is not buggy
12335 // or evil, and will quit as a result of our request.
12336 // Eventually we need to drive this off of the death
12337 // notification, and kill the process if it takes too long.
12338 cleanUpApplicationRecordLocked(app, false, i);
12339 i--;
12340 //dump();
12341 }
12342 }
12343
12344 }
12345
12346 int curMaxActivities = MAX_ACTIVITIES;
12347 if (mAlwaysFinishActivities) {
12348 curMaxActivities = 1;
12349 }
12350
12351 // Finally, if there are too many activities now running, try to
12352 // finish as many as we can to get back down to the limit.
12353 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012354 i<mMainStack.mLRUActivities.size()
12355 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012356 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012357 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012358 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012359
12360 // We can finish this one if we have its icicle saved and
12361 // it is not persistent.
12362 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012363 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012364 final int origSize = mMainStack.mLRUActivities.size();
12365 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012366
12367 // This will remove it from the LRU list, so keep
12368 // our index at the same value. Note that this check to
12369 // see if the size changes is just paranoia -- if
12370 // something unexpected happens, we don't want to end up
12371 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012372 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012373 i--;
12374 }
12375 }
12376 }
12377 }
12378 }
12379
12380 /** This method sends the specified signal to each of the persistent apps */
12381 public void signalPersistentProcesses(int sig) throws RemoteException {
12382 if (sig != Process.SIGNAL_USR1) {
12383 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12384 }
12385
12386 synchronized (this) {
12387 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12388 != PackageManager.PERMISSION_GRANTED) {
12389 throw new SecurityException("Requires permission "
12390 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12391 }
12392
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012393 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12394 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012395 if (r.thread != null && r.persistent) {
12396 Process.sendSignal(r.pid, sig);
12397 }
12398 }
12399 }
12400 }
12401
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012402 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012403 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012404
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012405 try {
12406 synchronized (this) {
12407 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12408 // its own permission.
12409 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12410 != PackageManager.PERMISSION_GRANTED) {
12411 throw new SecurityException("Requires permission "
12412 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012413 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012414
12415 if (start && fd == null) {
12416 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012417 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012418
12419 ProcessRecord proc = null;
12420 try {
12421 int pid = Integer.parseInt(process);
12422 synchronized (mPidsSelfLocked) {
12423 proc = mPidsSelfLocked.get(pid);
12424 }
12425 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012426 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012427
12428 if (proc == null) {
12429 HashMap<String, SparseArray<ProcessRecord>> all
12430 = mProcessNames.getMap();
12431 SparseArray<ProcessRecord> procs = all.get(process);
12432 if (procs != null && procs.size() > 0) {
12433 proc = procs.valueAt(0);
12434 }
12435 }
12436
12437 if (proc == null || proc.thread == null) {
12438 throw new IllegalArgumentException("Unknown process: " + process);
12439 }
12440
12441 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12442 if (isSecure) {
12443 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12444 throw new SecurityException("Process not debuggable: " + proc);
12445 }
12446 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012447
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012448 proc.thread.profilerControl(start, path, fd);
12449 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012450 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012451 }
12452 } catch (RemoteException e) {
12453 throw new IllegalStateException("Process disappeared");
12454 } finally {
12455 if (fd != null) {
12456 try {
12457 fd.close();
12458 } catch (IOException e) {
12459 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012460 }
12461 }
12462 }
12463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012464 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12465 public void monitor() {
12466 synchronized (this) { }
12467 }
12468}