blob: ff650eca36984bb455a1ce857d21845fb390c06b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070021import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import com.android.server.IntentResolver;
23import com.android.server.ProcessMap;
24import com.android.server.ProcessStats;
25import com.android.server.SystemServer;
26import com.android.server.Watchdog;
27import com.android.server.WindowManagerService;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070028import com.android.server.am.ActivityStack.ActivityState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.app.IServiceConnection;
46import android.app.IThumbnailReceiver;
47import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070048import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070049import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070051import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080052import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020053import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.ComponentName;
56import android.content.ContentResolver;
57import android.content.Context;
58import android.content.Intent;
59import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070060import android.content.IIntentReceiver;
61import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070062import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.content.pm.ActivityInfo;
64import android.content.pm.ApplicationInfo;
65import android.content.pm.ConfigurationInfo;
66import android.content.pm.IPackageDataObserver;
67import android.content.pm.IPackageManager;
68import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080069import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070071import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.ProviderInfo;
73import android.content.pm.ResolveInfo;
74import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070075import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.content.res.Configuration;
77import android.graphics.Bitmap;
78import android.net.Uri;
79import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080080import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080081import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070082import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080085import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.os.FileUtils;
87import android.os.Handler;
88import android.os.IBinder;
89import android.os.IPermissionController;
90import android.os.Looper;
91import android.os.Message;
92import android.os.Parcel;
93import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070095import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.RemoteException;
97import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -070098import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.SystemClock;
100import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.util.Config;
103import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800104import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800105import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.util.PrintWriterPrinter;
107import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700108import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.view.Gravity;
110import android.view.LayoutInflater;
111import android.view.View;
112import android.view.WindowManager;
113import android.view.WindowManagerPolicy;
114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import java.io.File;
116import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.io.FileNotFoundException;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200118import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800119import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import java.io.PrintWriter;
121import java.lang.IllegalStateException;
122import java.lang.ref.WeakReference;
123import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700124import java.util.Collections;
125import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126import java.util.HashMap;
127import java.util.HashSet;
128import java.util.Iterator;
129import java.util.List;
130import java.util.Locale;
131import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700132import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700133import java.util.concurrent.atomic.AtomicBoolean;
134import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700136public final class ActivityManagerService extends ActivityManagerNative
137 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 static final String TAG = "ActivityManager";
139 static final boolean DEBUG = false;
140 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
141 static final boolean DEBUG_SWITCH = localLOGV || false;
142 static final boolean DEBUG_TASKS = localLOGV || false;
143 static final boolean DEBUG_PAUSE = localLOGV || false;
144 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
145 static final boolean DEBUG_TRANSITION = localLOGV || false;
146 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700147 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700149 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final boolean DEBUG_VISBILITY = localLOGV || false;
151 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700152 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800153 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700155 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700156 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700157 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700158 static final boolean DEBUG_POWER = localLOGV || false;
159 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 static final boolean VALIDATE_TOKENS = false;
161 static final boolean SHOW_ACTIVITY_START_TIME = true;
162
163 // Control over CPU and battery monitoring.
164 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
165 static final boolean MONITOR_CPU_USAGE = true;
166 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
167 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
168 static final boolean MONITOR_THREAD_CPU_USAGE = false;
169
Dianne Hackborn1655be42009-05-08 14:29:01 -0700170 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700171 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 private static final String SYSTEM_SECURE = "ro.secure";
174
175 // This is the maximum number of application processes we would like
176 // to have running. Due to the asynchronous nature of things, we can
177 // temporarily go beyond this limit.
178 static final int MAX_PROCESSES = 2;
179
180 // Set to false to leave processes running indefinitely, relying on
181 // the kernel killing them as resources are required.
182 static final boolean ENFORCE_PROCESS_LIMIT = false;
183
184 // This is the maximum number of activities that we would like to have
185 // running at a given time.
186 static final int MAX_ACTIVITIES = 20;
187
188 // Maximum number of recent tasks that we can remember.
189 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700190
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700191 // Amount of time after a call to stopAppSwitches() during which we will
192 // prevent further untrusted switches from happening.
193 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194
195 // How long we wait for a launched process to attach to the activity manager
196 // before we decide it's never going to come up for real.
197 static final int PROC_START_TIMEOUT = 10*1000;
198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 // How long to wait after going idle before forcing apps to GC.
200 static final int GC_TIMEOUT = 5*1000;
201
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700202 // The minimum amount of time between successive GC requests for a process.
203 static final int GC_MIN_INTERVAL = 60*1000;
204
Dianne Hackborn287952c2010-09-22 22:34:31 -0700205 // The rate at which we check for apps using excessive power -- 15 mins.
206 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
207
208 // The minimum sample duration we will allow before deciding we have
209 // enough data on wake locks to start killing things.
210 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
211
212 // The minimum sample duration we will allow before deciding we have
213 // enough data on CPU usage to start killing things.
214 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 // How long we allow a receiver to run before giving up on it.
217 static final int BROADCAST_TIMEOUT = 10*1000;
218
219 // How long we wait for a service to finish executing.
220 static final int SERVICE_TIMEOUT = 20*1000;
221
222 // How long a service needs to be running until restarting its process
223 // is no longer considered to be a relaunch of the service.
224 static final int SERVICE_RESTART_DURATION = 5*1000;
225
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700226 // How long a service needs to be running until it will start back at
227 // SERVICE_RESTART_DURATION after being killed.
228 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
229
230 // Multiplying factor to increase restart duration time by, for each time
231 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
232 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
233
234 // The minimum amount of time between restarting services that we allow.
235 // That is, when multiple services are restarting, we won't allow each
236 // to restart less than this amount of time from the last one.
237 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 // Maximum amount of time for there to be no activity on a service before
240 // we consider it non-essential and allow its process to go on the
241 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700242 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243
244 // How long we wait until we timeout on key dispatching.
245 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
246
247 // The minimum time we allow between crashes, for us to consider this
248 // application to be bad and stop and its services and reject broadcasts.
249 static final int MIN_CRASH_INTERVAL = 60*1000;
250
251 // How long we wait until we timeout on key dispatching during instrumentation.
252 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
253
254 // OOM adjustments for processes in various states:
255
256 // This is a process without anything currently running in it. Definitely
257 // the first to go! Value set in system/rootdir/init.rc on startup.
258 // This value is initalized in the constructor, careful when refering to
259 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800260 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261
262 // This is a process only hosting activities that are not visible,
263 // so it can be killed without any disruption. Value set in
264 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800265 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 static int HIDDEN_APP_MIN_ADJ;
267
The Android Open Source Project4df24232009-03-05 14:34:35 -0800268 // This is a process holding the home application -- we want to try
269 // avoiding killing it, even if it would normally be in the background,
270 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800271 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800272
Christopher Tate6fa95972009-06-05 18:43:55 -0700273 // This is a process currently hosting a backup operation. Killing it
274 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 // This is a process holding a secondary server -- killing it will not
278 // have much of an impact as far as the user is concerned. Value set in
279 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800280 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700282 // This is a process with a heavy-weight application. It is in the
283 // background, but we want to try to avoid killing it. Value set in
284 // system/rootdir/init.rc on startup.
285 static final int HEAVY_WEIGHT_APP_ADJ;
286
287 // This is a process only hosting components that are perceptible to the
288 // user, and we really want to avoid killing them, but they are not
289 // immediately visible. An example is background music playback. Value set in
290 // system/rootdir/init.rc on startup.
291 static final int PERCEPTIBLE_APP_ADJ;
292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 // This is a process only hosting activities that are visible to the
294 // user, so we'd prefer they don't disappear. Value set in
295 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800296 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297
298 // This is the process running the current foreground app. We'd really
299 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800300 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301
302 // This is a process running a core server, such as telephony. Definitely
303 // don't want to kill it, but doing so is not completely fatal.
304 static final int CORE_SERVER_ADJ = -12;
305
306 // The system process runs at the default adjustment.
307 static final int SYSTEM_ADJ = -16;
308
309 // Memory pages are 4K.
310 static final int PAGE_SIZE = 4*1024;
311
312 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800313 static final int EMPTY_APP_MEM;
314 static final int HIDDEN_APP_MEM;
315 static final int HOME_APP_MEM;
316 static final int BACKUP_APP_MEM;
317 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700318 static final int HEAVY_WEIGHT_APP_MEM;
319 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800320 static final int VISIBLE_APP_MEM;
321 static final int FOREGROUND_APP_MEM;
322
323 // The minimum number of hidden apps we want to be able to keep around,
324 // without empty apps being able to push them out of memory.
325 static final int MIN_HIDDEN_APPS = 2;
326
Dianne Hackborn8633e682010-04-22 16:03:41 -0700327 // The maximum number of hidden processes we will keep around before
328 // killing them; this is just a control to not let us go too crazy with
329 // keeping around processes on devices with large amounts of RAM.
330 static final int MAX_HIDDEN_APPS = 15;
331
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800332 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700333 // been idle for less than 15 seconds.
334 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800335
336 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700337 // been idle for less than 120 seconds.
338 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700340 static int getIntProp(String name, boolean allowZero) {
341 String str = SystemProperties.get(name);
342 if (str == null) {
343 throw new IllegalArgumentException("Property not defined: " + name);
344 }
345 int val = Integer.valueOf(str);
346 if (val == 0 && !allowZero) {
347 throw new IllegalArgumentException("Property must not be zero: " + name);
348 }
349 return val;
350 }
351
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800352 static {
353 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700354 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
355 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
356 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
357 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
358 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
359 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
360 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
361 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
362 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
363 // These days we use the last empty slot for hidden apps as well.
364 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
365 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
366 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
367 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
368 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
369 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
370 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
371 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
372 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
373 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375
Dan Egnor42471dd2010-01-07 17:25:22 -0800376 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377
378 static final String[] EMPTY_STRING_ARRAY = new String[0];
379
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700380 public ActivityStack mMainStack;
381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700383 * Description of a request to start a new activity, which has been held
384 * due to app switches being disabled.
385 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700386 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700387 ActivityRecord r;
388 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700389 Uri[] grantedUriPermissions;
390 int grantedMode;
391 boolean onlyIfNeeded;
392 }
393
394 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
395 = new ArrayList<PendingActivityLaunch>();
396
397 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 * List of all active broadcasts that are to be executed immediately
399 * (without waiting for another broadcast to finish). Currently this only
400 * contains broadcasts to registered receivers, to avoid spinning up
401 * a bunch of processes to execute IntentReceiver components.
402 */
403 final ArrayList<BroadcastRecord> mParallelBroadcasts
404 = new ArrayList<BroadcastRecord>();
405
406 /**
407 * List of all active broadcasts that are to be executed one at a time.
408 * The object at the top of the list is the currently activity broadcasts;
409 * those after it are waiting for the top to finish..
410 */
411 final ArrayList<BroadcastRecord> mOrderedBroadcasts
412 = new ArrayList<BroadcastRecord>();
413
414 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800415 * Historical data of past broadcasts, for debugging.
416 */
417 static final int MAX_BROADCAST_HISTORY = 100;
418 final BroadcastRecord[] mBroadcastHistory
419 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
420
421 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 * Set when we current have a BROADCAST_INTENT_MSG in flight.
423 */
424 boolean mBroadcastsScheduled = false;
425
426 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 * Activity we have told the window manager to have key focus.
428 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700429 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700430 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 * List of intents that were used to start the most recent tasks.
432 */
433 final ArrayList<TaskRecord> mRecentTasks
434 = new ArrayList<TaskRecord>();
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * All of the applications we currently have running organized by name.
438 * The keys are strings of the application package name (as
439 * returned by the package manager), and the keys are ApplicationRecord
440 * objects.
441 */
442 final ProcessMap<ProcessRecord> mProcessNames
443 = new ProcessMap<ProcessRecord>();
444
445 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700446 * The currently running heavy-weight process, if any.
447 */
448 ProcessRecord mHeavyWeightProcess = null;
449
450 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 * The last time that various processes have crashed.
452 */
453 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
454
455 /**
456 * Set of applications that we consider to be bad, and will reject
457 * incoming broadcasts from (which the user has no control over).
458 * Processes are added to this set when they have crashed twice within
459 * a minimum amount of time; they are removed from it when they are
460 * later restarted (hopefully due to some user action). The value is the
461 * time it was added to the list.
462 */
463 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
464
465 /**
466 * All of the processes we currently have running organized by pid.
467 * The keys are the pid running the application.
468 *
469 * <p>NOTE: This object is protected by its own lock, NOT the global
470 * activity manager lock!
471 */
472 final SparseArray<ProcessRecord> mPidsSelfLocked
473 = new SparseArray<ProcessRecord>();
474
475 /**
476 * All of the processes that have been forced to be foreground. The key
477 * is the pid of the caller who requested it (we hold a death
478 * link on it).
479 */
480 abstract class ForegroundToken implements IBinder.DeathRecipient {
481 int pid;
482 IBinder token;
483 }
484 final SparseArray<ForegroundToken> mForegroundProcesses
485 = new SparseArray<ForegroundToken>();
486
487 /**
488 * List of records for processes that someone had tried to start before the
489 * system was ready. We don't start them at that point, but ensure they
490 * are started by the time booting is complete.
491 */
492 final ArrayList<ProcessRecord> mProcessesOnHold
493 = new ArrayList<ProcessRecord>();
494
495 /**
496 * List of records for processes that we have started and are waiting
497 * for them to call back. This is really only needed when running in
498 * single processes mode, in which case we do not have a unique pid for
499 * each process.
500 */
501 final ArrayList<ProcessRecord> mStartingProcesses
502 = new ArrayList<ProcessRecord>();
503
504 /**
505 * List of persistent applications that are in the process
506 * of being started.
507 */
508 final ArrayList<ProcessRecord> mPersistentStartingProcesses
509 = new ArrayList<ProcessRecord>();
510
511 /**
512 * Processes that are being forcibly torn down.
513 */
514 final ArrayList<ProcessRecord> mRemovedProcesses
515 = new ArrayList<ProcessRecord>();
516
517 /**
518 * List of running applications, sorted by recent usage.
519 * The first entry in the list is the least recently used.
520 * It contains ApplicationRecord objects. This list does NOT include
521 * any persistent application records (since we never want to exit them).
522 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800523 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 = new ArrayList<ProcessRecord>();
525
526 /**
527 * List of processes that should gc as soon as things are idle.
528 */
529 final ArrayList<ProcessRecord> mProcessesToGc
530 = new ArrayList<ProcessRecord>();
531
532 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800533 * This is the process holding what we currently consider to be
534 * the "home" activity.
535 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700536 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800537
538 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 * Set of PendingResultRecord objects that are currently active.
540 */
541 final HashSet mPendingResultRecords = new HashSet();
542
543 /**
544 * Set of IntentSenderRecord objects that are currently active.
545 */
546 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
547 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
548
549 /**
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700550 * Fingerprints (String.hashCode()) of stack traces that we've
551 * already logged DropBox entries for. Guarded by itself. If
552 * something (rogue user app) forces this over
553 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
554 */
555 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
556 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
557
558 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700559 * Strict Mode background batched logging state.
560 *
561 * The string buffer is guarded by itself, and its lock is also
562 * used to determine if another batched write is already
563 * in-flight.
564 */
565 private final StringBuilder mStrictModeBuffer = new StringBuilder();
566
567 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800568 * Intent broadcast that we have tried to start, but are
569 * waiting for its application's process to be created. We only
570 * need one (instead of a list) because we always process broadcasts
571 * one at a time, so no others can be started while waiting for this
572 * one.
573 */
574 BroadcastRecord mPendingBroadcast = null;
575
576 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700577 * The receiver index that is pending, to restart the broadcast if needed.
578 */
579 int mPendingBroadcastRecvIndex;
580
581 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 * Keeps track of all IIntentReceivers that have been registered for
583 * broadcasts. Hash keys are the receiver IBinder, hash value is
584 * a ReceiverList.
585 */
586 final HashMap mRegisteredReceivers = new HashMap();
587
588 /**
589 * Resolver for broadcast intents to registered receivers.
590 * Holds BroadcastFilter (subclass of IntentFilter).
591 */
592 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
593 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
594 @Override
595 protected boolean allowFilterResult(
596 BroadcastFilter filter, List<BroadcastFilter> dest) {
597 IBinder target = filter.receiverList.receiver.asBinder();
598 for (int i=dest.size()-1; i>=0; i--) {
599 if (dest.get(i).receiverList.receiver.asBinder() == target) {
600 return false;
601 }
602 }
603 return true;
604 }
605 };
606
607 /**
608 * State of all active sticky broadcasts. Keys are the action of the
609 * sticky Intent, values are an ArrayList of all broadcasted intents with
610 * that action (which should usually be one).
611 */
612 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
613 new HashMap<String, ArrayList<Intent>>();
614
615 /**
616 * All currently running services.
617 */
618 final HashMap<ComponentName, ServiceRecord> mServices =
619 new HashMap<ComponentName, ServiceRecord>();
620
621 /**
622 * All currently running services indexed by the Intent used to start them.
623 */
624 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
625 new HashMap<Intent.FilterComparison, ServiceRecord>();
626
627 /**
628 * All currently bound service connections. Keys are the IBinder of
629 * the client's IServiceConnection.
630 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700631 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
632 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633
634 /**
635 * List of services that we have been asked to start,
636 * but haven't yet been able to. It is used to hold start requests
637 * while waiting for their corresponding application thread to get
638 * going.
639 */
640 final ArrayList<ServiceRecord> mPendingServices
641 = new ArrayList<ServiceRecord>();
642
643 /**
644 * List of services that are scheduled to restart following a crash.
645 */
646 final ArrayList<ServiceRecord> mRestartingServices
647 = new ArrayList<ServiceRecord>();
648
649 /**
650 * List of services that are in the process of being stopped.
651 */
652 final ArrayList<ServiceRecord> mStoppingServices
653 = new ArrayList<ServiceRecord>();
654
655 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700656 * Backup/restore process management
657 */
658 String mBackupAppName = null;
659 BackupRecord mBackupTarget = null;
660
661 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 * List of PendingThumbnailsRecord objects of clients who are still
663 * waiting to receive all of the thumbnails for a task.
664 */
665 final ArrayList mPendingThumbnails = new ArrayList();
666
667 /**
668 * List of HistoryRecord objects that have been finished and must
669 * still report back to a pending thumbnail receiver.
670 */
671 final ArrayList mCancelledThumbnails = new ArrayList();
672
673 /**
674 * All of the currently running global content providers. Keys are a
675 * string containing the provider name and values are a
676 * ContentProviderRecord object containing the data about it. Note
677 * that a single provider may be published under multiple names, so
678 * there may be multiple entries here for a single one in mProvidersByClass.
679 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700680 final HashMap<String, ContentProviderRecord> mProvidersByName
681 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682
683 /**
684 * All of the currently running global content providers. Keys are a
685 * string containing the provider's implementation class and values are a
686 * ContentProviderRecord object containing the data about it.
687 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700688 final HashMap<String, ContentProviderRecord> mProvidersByClass
689 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690
691 /**
692 * List of content providers who have clients waiting for them. The
693 * application is currently being launched and the provider will be
694 * removed from this list once it is published.
695 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700696 final ArrayList<ContentProviderRecord> mLaunchingProviders
697 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698
699 /**
700 * Global set of specific Uri permissions that have been granted.
701 */
702 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
703 = new SparseArray<HashMap<Uri, UriPermission>>();
704
705 /**
706 * Thread-local storage used to carry caller permissions over through
707 * indirect content-provider access.
708 * @see #ActivityManagerService.openContentUri()
709 */
710 private class Identity {
711 public int pid;
712 public int uid;
713
714 Identity(int _pid, int _uid) {
715 pid = _pid;
716 uid = _uid;
717 }
718 }
719 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
720
721 /**
722 * All information we have collected about the runtime performance of
723 * any user id that can impact battery performance.
724 */
725 final BatteryStatsService mBatteryStatsService;
726
727 /**
728 * information about component usage
729 */
730 final UsageStatsService mUsageStatsService;
731
732 /**
733 * Current configuration information. HistoryRecord objects are given
734 * a reference to this object to indicate which configuration they are
735 * currently running in, so this object must be kept immutable.
736 */
737 Configuration mConfiguration = new Configuration();
738
739 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800740 * Current sequencing integer of the configuration, for skipping old
741 * configurations.
742 */
743 int mConfigurationSeq = 0;
744
745 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700746 * Hardware-reported OpenGLES version.
747 */
748 final int GL_ES_VERSION;
749
750 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751 * List of initialization arguments to pass to all processes when binding applications to them.
752 * For example, references to the commonly used services.
753 */
754 HashMap<String, IBinder> mAppBindArgs;
755
756 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700757 * Temporary to avoid allocations. Protected by main lock.
758 */
759 final StringBuilder mStringBuilder = new StringBuilder(256);
760
761 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 * Used to control how we initialize the service.
763 */
764 boolean mStartRunning = false;
765 ComponentName mTopComponent;
766 String mTopAction;
767 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700768 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 boolean mSystemReady = false;
770 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700771 boolean mWaitingUpdate = false;
772 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700773 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700774 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775
776 Context mContext;
777
778 int mFactoryTest;
779
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700780 boolean mCheckedForSetup;
781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700783 * The time at which we will allow normal application switches again,
784 * after a call to {@link #stopAppSwitches()}.
785 */
786 long mAppSwitchesAllowedTime;
787
788 /**
789 * This is set to true after the first switch after mAppSwitchesAllowedTime
790 * is set; any switches after that will clear the time.
791 */
792 boolean mDidAppSwitch;
793
794 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700795 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700796 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700797 long mLastPowerCheckRealtime;
798
799 /**
800 * Last time (in uptime) at which we checked for power usage.
801 */
802 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700803
804 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 * Set while we are wanting to sleep, to prevent any
806 * activities from being started/resumed.
807 */
808 boolean mSleeping = false;
809
810 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700811 * Set if we are shutting down the system, similar to sleeping.
812 */
813 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814
815 /**
816 * Task identifier that activities are currently being started
817 * in. Incremented each time a new task is created.
818 * todo: Replace this with a TokenSpace class that generates non-repeating
819 * integers that won't wrap.
820 */
821 int mCurTask = 1;
822
823 /**
824 * Current sequence id for oom_adj computation traversal.
825 */
826 int mAdjSeq = 0;
827
828 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700829 * Current sequence id for process LRU updating.
830 */
831 int mLruSeq = 0;
832
833 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
835 * is set, indicating the user wants processes started in such a way
836 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
837 * running in each process (thus no pre-initialized process, etc).
838 */
839 boolean mSimpleProcessManagement = false;
840
841 /**
842 * System monitoring: number of processes that died since the last
843 * N procs were started.
844 */
845 int[] mProcDeaths = new int[20];
846
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700847 /**
848 * This is set if we had to do a delayed dexopt of an app before launching
849 * it, to increasing the ANR timeouts in that case.
850 */
851 boolean mDidDexOpt;
852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 String mDebugApp = null;
854 boolean mWaitForDebugger = false;
855 boolean mDebugTransient = false;
856 String mOrigDebugApp = null;
857 boolean mOrigWaitForDebugger = false;
858 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700859 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700861 final RemoteCallbackList<IActivityWatcher> mWatchers
862 = new RemoteCallbackList<IActivityWatcher>();
863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 /**
865 * Callback of last caller to {@link #requestPss}.
866 */
867 Runnable mRequestPssCallback;
868
869 /**
870 * Remaining processes for which we are waiting results from the last
871 * call to {@link #requestPss}.
872 */
873 final ArrayList<ProcessRecord> mRequestPssList
874 = new ArrayList<ProcessRecord>();
875
876 /**
877 * Runtime statistics collection thread. This object's lock is used to
878 * protect all related state.
879 */
880 final Thread mProcessStatsThread;
881
882 /**
883 * Used to collect process stats when showing not responding dialog.
884 * Protected by mProcessStatsThread.
885 */
886 final ProcessStats mProcessStats = new ProcessStats(
887 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700888 final AtomicLong mLastCpuTime = new AtomicLong(0);
889 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 long mLastWriteTime = 0;
892
893 /**
894 * Set to true after the system has finished booting.
895 */
896 boolean mBooted = false;
897
898 int mProcessLimit = 0;
899
900 WindowManagerService mWindowManager;
901
902 static ActivityManagerService mSelf;
903 static ActivityThread mSystemThread;
904
905 private final class AppDeathRecipient implements IBinder.DeathRecipient {
906 final ProcessRecord mApp;
907 final int mPid;
908 final IApplicationThread mAppThread;
909
910 AppDeathRecipient(ProcessRecord app, int pid,
911 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800912 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 TAG, "New death recipient " + this
914 + " for thread " + thread.asBinder());
915 mApp = app;
916 mPid = pid;
917 mAppThread = thread;
918 }
919
920 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800921 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 TAG, "Death received in " + this
923 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 synchronized(ActivityManagerService.this) {
925 appDiedLocked(mApp, mPid, mAppThread);
926 }
927 }
928 }
929
930 static final int SHOW_ERROR_MSG = 1;
931 static final int SHOW_NOT_RESPONDING_MSG = 2;
932 static final int SHOW_FACTORY_ERROR_MSG = 3;
933 static final int UPDATE_CONFIGURATION_MSG = 4;
934 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
935 static final int WAIT_FOR_DEBUGGER_MSG = 6;
936 static final int BROADCAST_INTENT_MSG = 7;
937 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 static final int SERVICE_TIMEOUT_MSG = 12;
939 static final int UPDATE_TIME_ZONE = 13;
940 static final int SHOW_UID_ERROR_MSG = 14;
941 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700943 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700944 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800945 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700946 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
947 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700948 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700949 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950
951 AlertDialog mUidAlert;
952
953 final Handler mHandler = new Handler() {
954 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800955 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 //}
957
958 public void handleMessage(Message msg) {
959 switch (msg.what) {
960 case SHOW_ERROR_MSG: {
961 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 synchronized (ActivityManagerService.this) {
963 ProcessRecord proc = (ProcessRecord)data.get("app");
964 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800965 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 return;
967 }
968 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700969 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800970 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 d.show();
972 proc.crashDialog = d;
973 } else {
974 // The device is asleep, so just pretend that the user
975 // saw a crash dialog and hit "force quit".
976 res.set(0);
977 }
978 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700979
980 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 } break;
982 case SHOW_NOT_RESPONDING_MSG: {
983 synchronized (ActivityManagerService.this) {
984 HashMap data = (HashMap) msg.obj;
985 ProcessRecord proc = (ProcessRecord)data.get("app");
986 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800987 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 return;
989 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800990
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700991 Intent intent = new Intent("android.intent.action.ANR");
992 if (!mProcessesReady) {
993 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
994 }
995 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -0800996 null, null, 0, null, null, null,
997 false, false, MY_PID, Process.SYSTEM_UID);
998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001000 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 d.show();
1002 proc.anrDialog = d;
1003 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001004
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001005 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001007 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1008 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1009 synchronized (ActivityManagerService.this) {
1010 ProcessRecord proc = (ProcessRecord) data.get("app");
1011 if (proc == null) {
1012 Slog.e(TAG, "App not found when showing strict mode dialog.");
1013 break;
1014 }
1015 if (proc.crashDialog != null) {
1016 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1017 return;
1018 }
1019 AppErrorResult res = (AppErrorResult) data.get("result");
1020 if (!mSleeping && !mShuttingDown) {
1021 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1022 d.show();
1023 proc.crashDialog = d;
1024 } else {
1025 // The device is asleep, so just pretend that the user
1026 // saw a crash dialog and hit "force quit".
1027 res.set(0);
1028 }
1029 }
1030 ensureBootCompleted();
1031 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 case SHOW_FACTORY_ERROR_MSG: {
1033 Dialog d = new FactoryErrorDialog(
1034 mContext, msg.getData().getCharSequence("msg"));
1035 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001036 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 } break;
1038 case UPDATE_CONFIGURATION_MSG: {
1039 final ContentResolver resolver = mContext.getContentResolver();
1040 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1041 } break;
1042 case GC_BACKGROUND_PROCESSES_MSG: {
1043 synchronized (ActivityManagerService.this) {
1044 performAppGcsIfAppropriateLocked();
1045 }
1046 } break;
1047 case WAIT_FOR_DEBUGGER_MSG: {
1048 synchronized (ActivityManagerService.this) {
1049 ProcessRecord app = (ProcessRecord)msg.obj;
1050 if (msg.arg1 != 0) {
1051 if (!app.waitedForDebugger) {
1052 Dialog d = new AppWaitingForDebuggerDialog(
1053 ActivityManagerService.this,
1054 mContext, app);
1055 app.waitDialog = d;
1056 app.waitedForDebugger = true;
1057 d.show();
1058 }
1059 } else {
1060 if (app.waitDialog != null) {
1061 app.waitDialog.dismiss();
1062 app.waitDialog = null;
1063 }
1064 }
1065 }
1066 } break;
1067 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001068 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 TAG, "Received BROADCAST_INTENT_MSG");
1070 processNextBroadcast(true);
1071 } break;
1072 case BROADCAST_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001073 if (mDidDexOpt) {
1074 mDidDexOpt = false;
1075 Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
1076 mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
1077 return;
1078 }
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001079 // Only process broadcast timeouts if the system is ready. That way
1080 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
1081 // to do heavy lifting for system up
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001082 if (mProcessesReady) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001083 broadcastTimeout();
1084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001087 if (mDidDexOpt) {
1088 mDidDexOpt = false;
1089 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1090 nmsg.obj = msg.obj;
1091 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1092 return;
1093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 serviceTimeout((ProcessRecord)msg.obj);
1095 } break;
1096 case UPDATE_TIME_ZONE: {
1097 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001098 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1099 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 if (r.thread != null) {
1101 try {
1102 r.thread.updateTimeZone();
1103 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001104 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 }
1106 }
1107 }
1108 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001109 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 case SHOW_UID_ERROR_MSG: {
1111 // XXX This is a temporary dialog, no need to localize.
1112 AlertDialog d = new BaseErrorDialog(mContext);
1113 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1114 d.setCancelable(false);
1115 d.setTitle("System UIDs Inconsistent");
1116 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1117 d.setButton("I'm Feeling Lucky",
1118 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1119 mUidAlert = d;
1120 d.show();
1121 } break;
1122 case IM_FEELING_LUCKY_MSG: {
1123 if (mUidAlert != null) {
1124 mUidAlert.dismiss();
1125 mUidAlert = null;
1126 }
1127 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001129 if (mDidDexOpt) {
1130 mDidDexOpt = false;
1131 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1132 nmsg.obj = msg.obj;
1133 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1134 return;
1135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 ProcessRecord app = (ProcessRecord)msg.obj;
1137 synchronized (ActivityManagerService.this) {
1138 processStartTimedOutLocked(app);
1139 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001140 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001141 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1142 synchronized (ActivityManagerService.this) {
1143 doPendingActivityLaunchesLocked(true);
1144 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001145 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001146 case KILL_APPLICATION_MSG: {
1147 synchronized (ActivityManagerService.this) {
1148 int uid = msg.arg1;
1149 boolean restart = (msg.arg2 == 1);
1150 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001151 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001152 }
1153 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001154 case FINALIZE_PENDING_INTENT_MSG: {
1155 ((PendingIntentRecord)msg.obj).completeFinalize();
1156 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001157 case POST_HEAVY_NOTIFICATION_MSG: {
1158 INotificationManager inm = NotificationManager.getService();
1159 if (inm == null) {
1160 return;
1161 }
1162
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001163 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001164 ProcessRecord process = root.app;
1165 if (process == null) {
1166 return;
1167 }
1168
1169 try {
1170 Context context = mContext.createPackageContext(process.info.packageName, 0);
1171 String text = mContext.getString(R.string.heavy_weight_notification,
1172 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1173 Notification notification = new Notification();
1174 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1175 notification.when = 0;
1176 notification.flags = Notification.FLAG_ONGOING_EVENT;
1177 notification.tickerText = text;
1178 notification.defaults = 0; // please be quiet
1179 notification.sound = null;
1180 notification.vibrate = null;
1181 notification.setLatestEventInfo(context, text,
1182 mContext.getText(R.string.heavy_weight_notification_detail),
1183 PendingIntent.getActivity(mContext, 0, root.intent,
1184 PendingIntent.FLAG_CANCEL_CURRENT));
1185
1186 try {
1187 int[] outId = new int[1];
1188 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1189 notification, outId);
1190 } catch (RuntimeException e) {
1191 Slog.w(ActivityManagerService.TAG,
1192 "Error showing notification for heavy-weight app", e);
1193 } catch (RemoteException e) {
1194 }
1195 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001196 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001197 }
1198 } break;
1199 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1200 INotificationManager inm = NotificationManager.getService();
1201 if (inm == null) {
1202 return;
1203 }
1204 try {
1205 inm.cancelNotification("android",
1206 R.string.heavy_weight_notification);
1207 } catch (RuntimeException e) {
1208 Slog.w(ActivityManagerService.TAG,
1209 "Error canceling notification for service", e);
1210 } catch (RemoteException e) {
1211 }
1212 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001213 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1214 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001215 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001216 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001217 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1218 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001219 }
1220 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 }
1222 }
1223 };
1224
1225 public static void setSystemProcess() {
1226 try {
1227 ActivityManagerService m = mSelf;
1228
1229 ServiceManager.addService("activity", m);
1230 ServiceManager.addService("meminfo", new MemBinder(m));
1231 if (MONITOR_CPU_USAGE) {
1232 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 ServiceManager.addService("permission", new PermissionController(m));
1235
1236 ApplicationInfo info =
1237 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001238 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001239 mSystemThread.installSystemApplicationInfo(info);
1240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241 synchronized (mSelf) {
1242 ProcessRecord app = mSelf.newProcessRecordLocked(
1243 mSystemThread.getApplicationThread(), info,
1244 info.processName);
1245 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001246 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 app.maxAdj = SYSTEM_ADJ;
1248 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1249 synchronized (mSelf.mPidsSelfLocked) {
1250 mSelf.mPidsSelfLocked.put(app.pid, app);
1251 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001252 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 }
1254 } catch (PackageManager.NameNotFoundException e) {
1255 throw new RuntimeException(
1256 "Unable to find android system package", e);
1257 }
1258 }
1259
1260 public void setWindowManager(WindowManagerService wm) {
1261 mWindowManager = wm;
1262 }
1263
1264 public static final Context main(int factoryTest) {
1265 AThread thr = new AThread();
1266 thr.start();
1267
1268 synchronized (thr) {
1269 while (thr.mService == null) {
1270 try {
1271 thr.wait();
1272 } catch (InterruptedException e) {
1273 }
1274 }
1275 }
1276
1277 ActivityManagerService m = thr.mService;
1278 mSelf = m;
1279 ActivityThread at = ActivityThread.systemMain();
1280 mSystemThread = at;
1281 Context context = at.getSystemContext();
1282 m.mContext = context;
1283 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001284 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285
1286 m.mBatteryStatsService.publish(context);
1287 m.mUsageStatsService.publish(context);
1288
1289 synchronized (thr) {
1290 thr.mReady = true;
1291 thr.notifyAll();
1292 }
1293
1294 m.startRunning(null, null, null, null);
1295
1296 return context;
1297 }
1298
1299 public static ActivityManagerService self() {
1300 return mSelf;
1301 }
1302
1303 static class AThread extends Thread {
1304 ActivityManagerService mService;
1305 boolean mReady = false;
1306
1307 public AThread() {
1308 super("ActivityManager");
1309 }
1310
1311 public void run() {
1312 Looper.prepare();
1313
1314 android.os.Process.setThreadPriority(
1315 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001316 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001317
1318 ActivityManagerService m = new ActivityManagerService();
1319
1320 synchronized (this) {
1321 mService = m;
1322 notifyAll();
1323 }
1324
1325 synchronized (this) {
1326 while (!mReady) {
1327 try {
1328 wait();
1329 } catch (InterruptedException e) {
1330 }
1331 }
1332 }
1333
1334 Looper.loop();
1335 }
1336 }
1337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 static class MemBinder extends Binder {
1339 ActivityManagerService mActivityManagerService;
1340 MemBinder(ActivityManagerService activityManagerService) {
1341 mActivityManagerService = activityManagerService;
1342 }
1343
1344 @Override
1345 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1346 ActivityManagerService service = mActivityManagerService;
1347 ArrayList<ProcessRecord> procs;
1348 synchronized (mActivityManagerService) {
1349 if (args != null && args.length > 0
1350 && args[0].charAt(0) != '-') {
1351 procs = new ArrayList<ProcessRecord>();
1352 int pid = -1;
1353 try {
1354 pid = Integer.parseInt(args[0]);
1355 } catch (NumberFormatException e) {
1356
1357 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001358 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1359 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 if (proc.pid == pid) {
1361 procs.add(proc);
1362 } else if (proc.processName.equals(args[0])) {
1363 procs.add(proc);
1364 }
1365 }
1366 if (procs.size() <= 0) {
1367 pw.println("No process found for: " + args[0]);
1368 return;
1369 }
1370 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001371 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 }
1373 }
1374 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1375 }
1376 }
1377
1378 static class CpuBinder extends Binder {
1379 ActivityManagerService mActivityManagerService;
1380 CpuBinder(ActivityManagerService activityManagerService) {
1381 mActivityManagerService = activityManagerService;
1382 }
1383
1384 @Override
1385 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1386 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001387 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1388 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1389 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 }
1391 }
1392 }
1393
1394 private ActivityManagerService() {
1395 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1396 if (v != null && Integer.getInteger(v) != 0) {
1397 mSimpleProcessManagement = true;
1398 }
1399 v = System.getenv("ANDROID_DEBUG_APP");
1400 if (v != null) {
1401 mSimpleProcessManagement = true;
1402 }
1403
Joe Onorato8a9b2202010-02-26 18:56:32 -08001404 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 File dataDir = Environment.getDataDirectory();
1407 File systemDir = new File(dataDir, "system");
1408 systemDir.mkdirs();
1409 mBatteryStatsService = new BatteryStatsService(new File(
1410 systemDir, "batterystats.bin").toString());
1411 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001412 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001413 mOnBattery = DEBUG_POWER ? true
1414 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001415 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001417 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001418 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419
Jack Palevichb90d28c2009-07-22 15:35:24 -07001420 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1421 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1422
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001423 mConfiguration.setToDefaults();
1424 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 mProcessStats.init();
1426
1427 // Add ourself to the Watchdog monitors.
1428 Watchdog.getInstance().addMonitor(this);
1429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 mProcessStatsThread = new Thread("ProcessStats") {
1431 public void run() {
1432 while (true) {
1433 try {
1434 try {
1435 synchronized(this) {
1436 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001437 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001439 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 // + ", write delay=" + nextWriteDelay);
1441 if (nextWriteDelay < nextCpuDelay) {
1442 nextCpuDelay = nextWriteDelay;
1443 }
1444 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001445 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 this.wait(nextCpuDelay);
1447 }
1448 }
1449 } catch (InterruptedException e) {
1450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 updateCpuStatsNow();
1452 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001453 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 }
1455 }
1456 }
1457 };
1458 mProcessStatsThread.start();
1459 }
1460
1461 @Override
1462 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1463 throws RemoteException {
1464 try {
1465 return super.onTransact(code, data, reply, flags);
1466 } catch (RuntimeException e) {
1467 // The activity manager only throws security exceptions, so let's
1468 // log all others.
1469 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001470 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 }
1472 throw e;
1473 }
1474 }
1475
1476 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001477 final long now = SystemClock.uptimeMillis();
1478 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1479 return;
1480 }
1481 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1482 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 mProcessStatsThread.notify();
1484 }
1485 }
1486 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 void updateCpuStatsNow() {
1489 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001490 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 final long now = SystemClock.uptimeMillis();
1492 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001495 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1496 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 haveNewCpuStats = true;
1498 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001499 //Slog.i(TAG, mProcessStats.printCurrentState());
1500 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 // + mProcessStats.getTotalCpuPercent() + "%");
1502
Joe Onorato8a9b2202010-02-26 18:56:32 -08001503 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 if ("true".equals(SystemProperties.get("events.cpu"))) {
1505 int user = mProcessStats.getLastUserTime();
1506 int system = mProcessStats.getLastSystemTime();
1507 int iowait = mProcessStats.getLastIoWaitTime();
1508 int irq = mProcessStats.getLastIrqTime();
1509 int softIrq = mProcessStats.getLastSoftIrqTime();
1510 int idle = mProcessStats.getLastIdleTime();
1511
1512 int total = user + system + iowait + irq + softIrq + idle;
1513 if (total == 0) total = 1;
1514
Doug Zongker2bec3d42009-12-04 12:52:44 -08001515 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 ((user+system+iowait+irq+softIrq) * 100) / total,
1517 (user * 100) / total,
1518 (system * 100) / total,
1519 (iowait * 100) / total,
1520 (irq * 100) / total,
1521 (softIrq * 100) / total);
1522 }
1523 }
1524
Amith Yamasanie43530a2009-08-21 13:11:37 -07001525 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001526 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001527 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 synchronized(mPidsSelfLocked) {
1529 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001530 if (mOnBattery) {
1531 int perc = bstats.startAddingCpuLocked();
1532 int totalUTime = 0;
1533 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001534 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001536 ProcessStats.Stats st = mProcessStats.getStats(i);
1537 if (!st.working) {
1538 continue;
1539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001541 int otherUTime = (st.rel_utime*perc)/100;
1542 int otherSTime = (st.rel_stime*perc)/100;
1543 totalUTime += otherUTime;
1544 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 if (pr != null) {
1546 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001547 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1548 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001549 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001550 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001551 } else {
1552 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001553 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001554 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001555 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1556 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001557 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
1560 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001561 bstats.finishAddingCpuLocked(perc, totalUTime,
1562 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 }
1564 }
1565 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1568 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001569 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 }
1571 }
1572 }
1573 }
1574
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001575 @Override
1576 public void batteryNeedsCpuUpdate() {
1577 updateCpuStatsNow();
1578 }
1579
1580 @Override
1581 public void batteryPowerChanged(boolean onBattery) {
1582 // When plugging in, update the CPU stats first before changing
1583 // the plug state.
1584 updateCpuStatsNow();
1585 synchronized (this) {
1586 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001587 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001588 }
1589 }
1590 }
1591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 /**
1593 * Initialize the application bind args. These are passed to each
1594 * process when the bindApplication() IPC is sent to the process. They're
1595 * lazily setup to make sure the services are running when they're asked for.
1596 */
1597 private HashMap<String, IBinder> getCommonServicesLocked() {
1598 if (mAppBindArgs == null) {
1599 mAppBindArgs = new HashMap<String, IBinder>();
1600
1601 // Setup the application init args
1602 mAppBindArgs.put("package", ServiceManager.getService("package"));
1603 mAppBindArgs.put("window", ServiceManager.getService("window"));
1604 mAppBindArgs.put(Context.ALARM_SERVICE,
1605 ServiceManager.getService(Context.ALARM_SERVICE));
1606 }
1607 return mAppBindArgs;
1608 }
1609
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001610 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 if (mFocusedActivity != r) {
1612 mFocusedActivity = r;
1613 mWindowManager.setFocusedApp(r, true);
1614 }
1615 }
1616
Dianne Hackborn906497c2010-05-10 15:57:38 -07001617 private final void updateLruProcessInternalLocked(ProcessRecord app,
1618 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001620 int lrui = mLruProcesses.indexOf(app);
1621 if (lrui >= 0) mLruProcesses.remove(lrui);
1622
1623 int i = mLruProcesses.size()-1;
1624 int skipTop = 0;
1625
Dianne Hackborn906497c2010-05-10 15:57:38 -07001626 app.lruSeq = mLruSeq;
1627
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001628 // compute the new weight for this process.
1629 if (updateActivityTime) {
1630 app.lastActivityTime = SystemClock.uptimeMillis();
1631 }
1632 if (app.activities.size() > 0) {
1633 // If this process has activities, we more strongly want to keep
1634 // it around.
1635 app.lruWeight = app.lastActivityTime;
1636 } else if (app.pubProviders.size() > 0) {
1637 // If this process contains content providers, we want to keep
1638 // it a little more strongly.
1639 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1640 // Also don't let it kick out the first few "real" hidden processes.
1641 skipTop = MIN_HIDDEN_APPS;
1642 } else {
1643 // If this process doesn't have activities, we less strongly
1644 // want to keep it around, and generally want to avoid getting
1645 // in front of any very recently used activities.
1646 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1647 // Also don't let it kick out the first few "real" hidden processes.
1648 skipTop = MIN_HIDDEN_APPS;
1649 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001650
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001651 while (i >= 0) {
1652 ProcessRecord p = mLruProcesses.get(i);
1653 // If this app shouldn't be in front of the first N background
1654 // apps, then skip over that many that are currently hidden.
1655 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1656 skipTop--;
1657 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001658 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001659 mLruProcesses.add(i+1, app);
1660 break;
1661 }
1662 i--;
1663 }
1664 if (i < 0) {
1665 mLruProcesses.add(0, app);
1666 }
1667
Dianne Hackborn906497c2010-05-10 15:57:38 -07001668 // If the app is currently using a content provider or service,
1669 // bump those processes as well.
1670 if (app.connections.size() > 0) {
1671 for (ConnectionRecord cr : app.connections) {
1672 if (cr.binding != null && cr.binding.service != null
1673 && cr.binding.service.app != null
1674 && cr.binding.service.app.lruSeq != mLruSeq) {
1675 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1676 updateActivityTime, i+1);
1677 }
1678 }
1679 }
1680 if (app.conProviders.size() > 0) {
1681 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1682 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1683 updateLruProcessInternalLocked(cpr.app, oomAdj,
1684 updateActivityTime, i+1);
1685 }
1686 }
1687 }
1688
Joe Onorato8a9b2202010-02-26 18:56:32 -08001689 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 if (oomAdj) {
1691 updateOomAdjLocked();
1692 }
1693 }
1694
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001695 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001696 boolean oomAdj, boolean updateActivityTime) {
1697 mLruSeq++;
1698 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1699 }
1700
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001701 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 String processName, int uid) {
1703 if (uid == Process.SYSTEM_UID) {
1704 // The system gets to run in any process. If there are multiple
1705 // processes with the same uid, just pick the first (this
1706 // should never happen).
1707 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1708 processName);
1709 return procs != null ? procs.valueAt(0) : null;
1710 }
1711 ProcessRecord proc = mProcessNames.get(processName, uid);
1712 return proc;
1713 }
1714
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001715 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001716 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001717 try {
1718 if (pm.performDexOpt(packageName)) {
1719 mDidDexOpt = true;
1720 }
1721 } catch (RemoteException e) {
1722 }
1723 }
1724
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001725 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 int transit = mWindowManager.getPendingAppTransition();
1727 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1728 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1729 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1730 }
1731
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001732 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001734 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1736 // We don't have to do anything more if:
1737 // (1) There is an existing application record; and
1738 // (2) The caller doesn't think it is dead, OR there is no thread
1739 // object attached to it so we know it couldn't have crashed; and
1740 // (3) There is a pid assigned to it, so it is either starting or
1741 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001742 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 + " app=" + app + " knownToBeDead=" + knownToBeDead
1744 + " thread=" + (app != null ? app.thread : null)
1745 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001746 if (app != null && app.pid > 0) {
1747 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001748 // We already have the app running, or are waiting for it to
1749 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001750 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001751 return app;
1752 } else {
1753 // An application record is attached to a previous process,
1754 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001755 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001756 handleAppDiedLocked(app, true);
1757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 String hostingNameStr = hostingName != null
1761 ? hostingName.flattenToShortString() : null;
1762
1763 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1764 // If we are in the background, then check to see if this process
1765 // is bad. If so, we will just silently fail.
1766 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001767 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1768 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 return null;
1770 }
1771 } else {
1772 // When the user is explicitly starting a process, then clear its
1773 // crash count so that we won't make it bad until they see at
1774 // least one crash dialog again, and make the process good again
1775 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001776 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1777 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778 mProcessCrashTimes.remove(info.processName, info.uid);
1779 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001780 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 info.processName);
1782 mBadProcesses.remove(info.processName, info.uid);
1783 if (app != null) {
1784 app.bad = false;
1785 }
1786 }
1787 }
1788
1789 if (app == null) {
1790 app = newProcessRecordLocked(null, info, processName);
1791 mProcessNames.put(processName, info.uid, app);
1792 } else {
1793 // If this is a new package in the process, add the package to the list
1794 app.addPackage(info.packageName);
1795 }
1796
1797 // If the system is not ready yet, then hold off on starting this
1798 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001799 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001800 && !isAllowedWhileBooting(info)
1801 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 if (!mProcessesOnHold.contains(app)) {
1803 mProcessesOnHold.add(app);
1804 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001805 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 return app;
1807 }
1808
1809 startProcessLocked(app, hostingType, hostingNameStr);
1810 return (app.pid != 0) ? app : null;
1811 }
1812
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001813 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1814 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1815 }
1816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 private final void startProcessLocked(ProcessRecord app,
1818 String hostingType, String hostingNameStr) {
1819 if (app.pid > 0 && app.pid != MY_PID) {
1820 synchronized (mPidsSelfLocked) {
1821 mPidsSelfLocked.remove(app.pid);
1822 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1823 }
1824 app.pid = 0;
1825 }
1826
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001827 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1828 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 mProcessesOnHold.remove(app);
1830
1831 updateCpuStats();
1832
1833 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1834 mProcDeaths[0] = 0;
1835
1836 try {
1837 int uid = app.info.uid;
1838 int[] gids = null;
1839 try {
1840 gids = mContext.getPackageManager().getPackageGids(
1841 app.info.packageName);
1842 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001843 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 }
1845 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1846 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1847 && mTopComponent != null
1848 && app.processName.equals(mTopComponent.getPackageName())) {
1849 uid = 0;
1850 }
1851 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1852 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1853 uid = 0;
1854 }
1855 }
1856 int debugFlags = 0;
1857 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1858 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1859 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001860 // Run the app in safe mode if its manifest requests so or the
1861 // system is booted in safe mode.
1862 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1863 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001864 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001866 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1867 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1868 }
1869 if ("1".equals(SystemProperties.get("debug.assert"))) {
1870 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1871 }
1872 int pid = Process.start("android.app.ActivityThread",
1873 mSimpleProcessManagement ? app.processName : null, uid, uid,
1874 gids, debugFlags, null);
1875 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1876 synchronized (bs) {
1877 if (bs.isOnBattery()) {
1878 app.batteryStats.incStartsLocked();
1879 }
1880 }
1881
Doug Zongker2bec3d42009-12-04 12:52:44 -08001882 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 app.processName, hostingType,
1884 hostingNameStr != null ? hostingNameStr : "");
1885
1886 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001887 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 }
1889
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001890 StringBuilder buf = mStringBuilder;
1891 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 buf.append("Start proc ");
1893 buf.append(app.processName);
1894 buf.append(" for ");
1895 buf.append(hostingType);
1896 if (hostingNameStr != null) {
1897 buf.append(" ");
1898 buf.append(hostingNameStr);
1899 }
1900 buf.append(": pid=");
1901 buf.append(pid);
1902 buf.append(" uid=");
1903 buf.append(uid);
1904 buf.append(" gids={");
1905 if (gids != null) {
1906 for (int gi=0; gi<gids.length; gi++) {
1907 if (gi != 0) buf.append(", ");
1908 buf.append(gids[gi]);
1909
1910 }
1911 }
1912 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001913 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 if (pid == 0 || pid == MY_PID) {
1915 // Processes are being emulated with threads.
1916 app.pid = MY_PID;
1917 app.removed = false;
1918 mStartingProcesses.add(app);
1919 } else if (pid > 0) {
1920 app.pid = pid;
1921 app.removed = false;
1922 synchronized (mPidsSelfLocked) {
1923 this.mPidsSelfLocked.put(pid, app);
1924 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1925 msg.obj = app;
1926 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1927 }
1928 } else {
1929 app.pid = 0;
1930 RuntimeException e = new RuntimeException(
1931 "Failure starting process " + app.processName
1932 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001933 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 }
1935 } catch (RuntimeException e) {
1936 // XXX do better error recovery.
1937 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001938 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 }
1940 }
1941
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001942 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 if (resumed) {
1944 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1945 } else {
1946 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1947 }
1948 }
1949
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001950 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001951 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1952 && mTopAction == null) {
1953 // We are running in factory test mode, but unable to find
1954 // the factory test app, so just sit around displaying the
1955 // error message and don't try to start anything.
1956 return false;
1957 }
1958 Intent intent = new Intent(
1959 mTopAction,
1960 mTopData != null ? Uri.parse(mTopData) : null);
1961 intent.setComponent(mTopComponent);
1962 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1963 intent.addCategory(Intent.CATEGORY_HOME);
1964 }
1965 ActivityInfo aInfo =
1966 intent.resolveActivityInfo(mContext.getPackageManager(),
1967 STOCK_PM_FLAGS);
1968 if (aInfo != null) {
1969 intent.setComponent(new ComponentName(
1970 aInfo.applicationInfo.packageName, aInfo.name));
1971 // Don't do this if the home app is currently being
1972 // instrumented.
1973 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1974 aInfo.applicationInfo.uid);
1975 if (app == null || app.instrumentationClass == null) {
1976 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001977 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001978 null, null, 0, 0, 0, false, false);
1979 }
1980 }
1981
1982
1983 return true;
1984 }
1985
1986 /**
1987 * Starts the "new version setup screen" if appropriate.
1988 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001989 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001990 // Only do this once per boot.
1991 if (mCheckedForSetup) {
1992 return;
1993 }
1994
1995 // We will show this screen if the current one is a different
1996 // version than the last one shown, and we are not running in
1997 // low-level factory test mode.
1998 final ContentResolver resolver = mContext.getContentResolver();
1999 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2000 Settings.Secure.getInt(resolver,
2001 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2002 mCheckedForSetup = true;
2003
2004 // See if we should be showing the platform update setup UI.
2005 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2006 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2007 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2008
2009 // We don't allow third party apps to replace this.
2010 ResolveInfo ri = null;
2011 for (int i=0; ris != null && i<ris.size(); i++) {
2012 if ((ris.get(i).activityInfo.applicationInfo.flags
2013 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2014 ri = ris.get(i);
2015 break;
2016 }
2017 }
2018
2019 if (ri != null) {
2020 String vers = ri.activityInfo.metaData != null
2021 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2022 : null;
2023 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2024 vers = ri.activityInfo.applicationInfo.metaData.getString(
2025 Intent.METADATA_SETUP_VERSION);
2026 }
2027 String lastVers = Settings.Secure.getString(
2028 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2029 if (vers != null && !vers.equals(lastVers)) {
2030 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2031 intent.setComponent(new ComponentName(
2032 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002033 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002034 null, null, 0, 0, 0, false, false);
2035 }
2036 }
2037 }
2038 }
2039
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002040 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002041 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002042
2043 final int identHash = System.identityHashCode(r);
2044 updateUsageStats(r, true);
2045
2046 int i = mWatchers.beginBroadcast();
2047 while (i > 0) {
2048 i--;
2049 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2050 if (w != null) {
2051 try {
2052 w.activityResuming(identHash);
2053 } catch (RemoteException e) {
2054 }
2055 }
2056 }
2057 mWatchers.finishBroadcast();
2058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002060 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002061 final int N = mPendingActivityLaunches.size();
2062 if (N <= 0) {
2063 return;
2064 }
2065 for (int i=0; i<N; i++) {
2066 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002067 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002068 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2069 doResume && i == (N-1));
2070 }
2071 mPendingActivityLaunches.clear();
2072 }
2073
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002074 public final int startActivity(IApplicationThread caller,
2075 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2076 int grantedMode, IBinder resultTo,
2077 String resultWho, int requestCode, boolean onlyIfNeeded,
2078 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002079 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002080 grantedUriPermissions, grantedMode, resultTo, resultWho,
2081 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002082 }
2083
2084 public final WaitResult startActivityAndWait(IApplicationThread caller,
2085 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2086 int grantedMode, IBinder resultTo,
2087 String resultWho, int requestCode, boolean onlyIfNeeded,
2088 boolean debug) {
2089 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002090 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002091 grantedUriPermissions, grantedMode, resultTo, resultWho,
2092 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002093 return res;
2094 }
2095
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002096 public final int startActivityWithConfig(IApplicationThread caller,
2097 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2098 int grantedMode, IBinder resultTo,
2099 String resultWho, int requestCode, boolean onlyIfNeeded,
2100 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002101 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002102 grantedUriPermissions, grantedMode, resultTo, resultWho,
2103 requestCode, onlyIfNeeded, debug, null, config);
2104 }
2105
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002106 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002107 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002108 IBinder resultTo, String resultWho, int requestCode,
2109 int flagsMask, int flagsValues) {
2110 // Refuse possible leaked file descriptors
2111 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2112 throw new IllegalArgumentException("File descriptors passed in Intent");
2113 }
2114
2115 IIntentSender sender = intent.getTarget();
2116 if (!(sender instanceof PendingIntentRecord)) {
2117 throw new IllegalArgumentException("Bad PendingIntent object");
2118 }
2119
2120 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002121
2122 synchronized (this) {
2123 // If this is coming from the currently resumed activity, it is
2124 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002125 if (mMainStack.mResumedActivity != null
2126 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002127 Binder.getCallingUid()) {
2128 mAppSwitchesAllowedTime = 0;
2129 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002130 }
2131
2132 return pir.sendInner(0, fillInIntent, resolvedType,
2133 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2134 }
2135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 public boolean startNextMatchingActivity(IBinder callingActivity,
2137 Intent intent) {
2138 // Refuse possible leaked file descriptors
2139 if (intent != null && intent.hasFileDescriptors() == true) {
2140 throw new IllegalArgumentException("File descriptors passed in Intent");
2141 }
2142
2143 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002144 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 if (index < 0) {
2146 return false;
2147 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002148 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 if (r.app == null || r.app.thread == null) {
2150 // The caller is not running... d'oh!
2151 return false;
2152 }
2153 intent = new Intent(intent);
2154 // The caller is not allowed to change the data.
2155 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2156 // And we are resetting to find the next component...
2157 intent.setComponent(null);
2158
2159 ActivityInfo aInfo = null;
2160 try {
2161 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002162 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002164 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165
2166 // Look for the original activity in the list...
2167 final int N = resolves != null ? resolves.size() : 0;
2168 for (int i=0; i<N; i++) {
2169 ResolveInfo rInfo = resolves.get(i);
2170 if (rInfo.activityInfo.packageName.equals(r.packageName)
2171 && rInfo.activityInfo.name.equals(r.info.name)) {
2172 // We found the current one... the next matching is
2173 // after it.
2174 i++;
2175 if (i<N) {
2176 aInfo = resolves.get(i).activityInfo;
2177 }
2178 break;
2179 }
2180 }
2181 } catch (RemoteException e) {
2182 }
2183
2184 if (aInfo == null) {
2185 // Nobody who is next!
2186 return false;
2187 }
2188
2189 intent.setComponent(new ComponentName(
2190 aInfo.applicationInfo.packageName, aInfo.name));
2191 intent.setFlags(intent.getFlags()&~(
2192 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2193 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2194 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2195 Intent.FLAG_ACTIVITY_NEW_TASK));
2196
2197 // Okay now we need to start the new activity, replacing the
2198 // currently running activity. This is a little tricky because
2199 // we want to start the new one as if the current one is finished,
2200 // but not finish the current one first so that there is no flicker.
2201 // And thus...
2202 final boolean wasFinishing = r.finishing;
2203 r.finishing = true;
2204
2205 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002206 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 final String resultWho = r.resultWho;
2208 final int requestCode = r.requestCode;
2209 r.resultTo = null;
2210 if (resultTo != null) {
2211 resultTo.removeResultsLocked(r, resultWho, requestCode);
2212 }
2213
2214 final long origId = Binder.clearCallingIdentity();
2215 // XXX we are not dealing with propagating grantedUriPermissions...
2216 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002217 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002219 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 Binder.restoreCallingIdentity(origId);
2221
2222 r.finishing = wasFinishing;
2223 if (res != START_SUCCESS) {
2224 return false;
2225 }
2226 return true;
2227 }
2228 }
2229
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002230 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 Intent intent, String resolvedType, IBinder resultTo,
2232 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002233
2234 // This is so super not safe, that only the system (or okay root)
2235 // can do it.
2236 final int callingUid = Binder.getCallingUid();
2237 if (callingUid != 0 && callingUid != Process.myUid()) {
2238 throw new SecurityException(
2239 "startActivityInPackage only available to the system");
2240 }
2241
The Android Open Source Project4df24232009-03-05 14:34:35 -08002242 final boolean componentSpecified = intent.getComponent() != null;
2243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 // Don't modify the client's object!
2245 intent = new Intent(intent);
2246
2247 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 ActivityInfo aInfo;
2249 try {
2250 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002251 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002253 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 aInfo = rInfo != null ? rInfo.activityInfo : null;
2255 } catch (RemoteException e) {
2256 aInfo = null;
2257 }
2258
2259 if (aInfo != null) {
2260 // Store the found target back into the intent, because now that
2261 // we have it we never want to do this again. For example, if the
2262 // user navigates back to this point in the history, we should
2263 // always restart the exact same activity.
2264 intent.setComponent(new ComponentName(
2265 aInfo.applicationInfo.packageName, aInfo.name));
2266 }
2267
2268 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002269 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002271 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 }
2273 }
2274
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002275 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 // Remove any existing entries that are the same kind of task.
2277 int N = mRecentTasks.size();
2278 for (int i=0; i<N; i++) {
2279 TaskRecord tr = mRecentTasks.get(i);
2280 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2281 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2282 mRecentTasks.remove(i);
2283 i--;
2284 N--;
2285 if (task.intent == null) {
2286 // If the new recent task we are adding is not fully
2287 // specified, then replace it with the existing recent task.
2288 task = tr;
2289 }
2290 }
2291 }
2292 if (N >= MAX_RECENT_TASKS) {
2293 mRecentTasks.remove(N-1);
2294 }
2295 mRecentTasks.add(0, task);
2296 }
2297
2298 public void setRequestedOrientation(IBinder token,
2299 int requestedOrientation) {
2300 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002301 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302 if (index < 0) {
2303 return;
2304 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002305 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306 final long origId = Binder.clearCallingIdentity();
2307 mWindowManager.setAppOrientation(r, requestedOrientation);
2308 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002309 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002310 r.mayFreezeScreenLocked(r.app) ? r : null);
2311 if (config != null) {
2312 r.frozenBeforeDestroy = true;
2313 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002314 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 }
2316 }
2317 Binder.restoreCallingIdentity(origId);
2318 }
2319 }
2320
2321 public int getRequestedOrientation(IBinder token) {
2322 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002323 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 if (index < 0) {
2325 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2326 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002327 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 return mWindowManager.getAppOrientation(r);
2329 }
2330 }
2331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 /**
2333 * This is the internal entry point for handling Activity.finish().
2334 *
2335 * @param token The Binder token referencing the Activity we want to finish.
2336 * @param resultCode Result code, if any, from this Activity.
2337 * @param resultData Result data (Intent), if any, from this Activity.
2338 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002339 * @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 -08002340 */
2341 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2342 // Refuse possible leaked file descriptors
2343 if (resultData != null && resultData.hasFileDescriptors() == true) {
2344 throw new IllegalArgumentException("File descriptors passed in Intent");
2345 }
2346
2347 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002348 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002350 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 if (next != null) {
2352 // ask watcher if this is allowed
2353 boolean resumeOK = true;
2354 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002355 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002357 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 }
2359
2360 if (!resumeOK) {
2361 return false;
2362 }
2363 }
2364 }
2365 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002366 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 resultData, "app-request");
2368 Binder.restoreCallingIdentity(origId);
2369 return res;
2370 }
2371 }
2372
Dianne Hackborn860755f2010-06-03 18:47:52 -07002373 public final void finishHeavyWeightApp() {
2374 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2375 != PackageManager.PERMISSION_GRANTED) {
2376 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2377 + Binder.getCallingPid()
2378 + ", uid=" + Binder.getCallingUid()
2379 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2380 Slog.w(TAG, msg);
2381 throw new SecurityException(msg);
2382 }
2383
2384 synchronized(this) {
2385 if (mHeavyWeightProcess == null) {
2386 return;
2387 }
2388
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002389 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002390 mHeavyWeightProcess.activities);
2391 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002392 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002393 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002394 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002395 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002396 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002397 null, "finish-heavy");
2398 }
2399 }
2400 }
2401
2402 mHeavyWeightProcess = null;
2403 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2404 }
2405 }
2406
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002407 public void crashApplication(int uid, int initialPid, String packageName,
2408 String message) {
2409 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2410 != PackageManager.PERMISSION_GRANTED) {
2411 String msg = "Permission Denial: crashApplication() from pid="
2412 + Binder.getCallingPid()
2413 + ", uid=" + Binder.getCallingUid()
2414 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2415 Slog.w(TAG, msg);
2416 throw new SecurityException(msg);
2417 }
2418
2419 synchronized(this) {
2420 ProcessRecord proc = null;
2421
2422 // Figure out which process to kill. We don't trust that initialPid
2423 // still has any relation to current pids, so must scan through the
2424 // list.
2425 synchronized (mPidsSelfLocked) {
2426 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2427 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2428 if (p.info.uid != uid) {
2429 continue;
2430 }
2431 if (p.pid == initialPid) {
2432 proc = p;
2433 break;
2434 }
2435 for (String str : p.pkgList) {
2436 if (str.equals(packageName)) {
2437 proc = p;
2438 }
2439 }
2440 }
2441 }
2442
2443 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002444 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002445 + " initialPid=" + initialPid
2446 + " packageName=" + packageName);
2447 return;
2448 }
2449
2450 if (proc.thread != null) {
2451 long ident = Binder.clearCallingIdentity();
2452 try {
2453 proc.thread.scheduleCrash(message);
2454 } catch (RemoteException e) {
2455 }
2456 Binder.restoreCallingIdentity(ident);
2457 }
2458 }
2459 }
2460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461 public final void finishSubActivity(IBinder token, String resultWho,
2462 int requestCode) {
2463 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002464 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002465 if (index < 0) {
2466 return;
2467 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002468 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002469
2470 final long origId = Binder.clearCallingIdentity();
2471
2472 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002473 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2474 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002475 if (r.resultTo == self && r.requestCode == requestCode) {
2476 if ((r.resultWho == null && resultWho == null) ||
2477 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002478 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 Activity.RESULT_CANCELED, null, "request-sub");
2480 }
2481 }
2482 }
2483
2484 Binder.restoreCallingIdentity(origId);
2485 }
2486 }
2487
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002488 public boolean willActivityBeVisible(IBinder token) {
2489 synchronized(this) {
2490 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002491 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2492 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002493 if (r == token) {
2494 return true;
2495 }
2496 if (r.fullscreen && !r.finishing) {
2497 return false;
2498 }
2499 }
2500 return true;
2501 }
2502 }
2503
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002504 public void overridePendingTransition(IBinder token, String packageName,
2505 int enterAnim, int exitAnim) {
2506 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002507 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002508 if (index < 0) {
2509 return;
2510 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002511 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002512
2513 final long origId = Binder.clearCallingIdentity();
2514
2515 if (self.state == ActivityState.RESUMED
2516 || self.state == ActivityState.PAUSING) {
2517 mWindowManager.overridePendingAppTransition(packageName,
2518 enterAnim, exitAnim);
2519 }
2520
2521 Binder.restoreCallingIdentity(origId);
2522 }
2523 }
2524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002526 * Main function for removing an existing process from the activity manager
2527 * as a result of that process going away. Clears out all connections
2528 * to the process.
2529 */
2530 private final void handleAppDiedLocked(ProcessRecord app,
2531 boolean restarting) {
2532 cleanUpApplicationRecordLocked(app, restarting, -1);
2533 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002534 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 }
2536
2537 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002538 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2539 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2540 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002542 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2543 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 }
2545
2546 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002547 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002548
2549 boolean atTop = true;
2550 boolean hasVisibleActivities = false;
2551
2552 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002553 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002554 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 TAG, "Removing app " + app + " from history with " + i + " entries");
2556 while (i > 0) {
2557 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002558 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002559 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2561 if (r.app == app) {
2562 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002563 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002564 TAG, "Removing this entry! frozen=" + r.haveState
2565 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002566 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002567
2568 r.inHistory = false;
2569 mWindowManager.removeAppToken(r);
2570 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002571 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002572 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002573 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574
2575 } else {
2576 // We have the current state for this activity, so
2577 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002578 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002579 TAG, "Keeping entry, setting app to null");
2580 if (r.visible) {
2581 hasVisibleActivities = true;
2582 }
2583 r.app = null;
2584 r.nowVisible = false;
2585 if (!r.haveState) {
2586 r.icicle = null;
2587 }
2588 }
2589
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002590 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 r.state = ActivityState.STOPPED;
2592 }
2593 atTop = false;
2594 }
2595
2596 app.activities.clear();
2597
2598 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002599 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 + " running instrumentation " + app.instrumentationClass);
2601 Bundle info = new Bundle();
2602 info.putString("shortMsg", "Process crashed.");
2603 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2604 }
2605
2606 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002607 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 // If there was nothing to resume, and we are not already
2609 // restarting this process, but there is a visible activity that
2610 // is hosted by the process... then make sure all visible
2611 // activities are running, taking care of restarting this
2612 // process.
2613 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002614 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 }
2616 }
2617 }
2618 }
2619
2620 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2621 IBinder threadBinder = thread.asBinder();
2622
2623 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002624 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2625 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2627 return i;
2628 }
2629 }
2630 return -1;
2631 }
2632
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002633 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 IApplicationThread thread) {
2635 if (thread == null) {
2636 return null;
2637 }
2638
2639 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002640 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 }
2642
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002643 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 IApplicationThread thread) {
2645
2646 mProcDeaths[0]++;
2647
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002648 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2649 synchronized (stats) {
2650 stats.noteProcessDiedLocked(app.info.uid, pid);
2651 }
2652
Magnus Edlund7bb25812010-02-24 15:45:06 +01002653 // Clean up already done if the process has been re-started.
2654 if (app.pid == pid && app.thread != null &&
2655 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002656 if (!app.killedBackground) {
2657 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2658 + ") has died.");
2659 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002660 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002661 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662 TAG, "Dying app: " + app + ", pid: " + pid
2663 + ", thread: " + thread.asBinder());
2664 boolean doLowMem = app.instrumentationClass == null;
2665 handleAppDiedLocked(app, false);
2666
2667 if (doLowMem) {
2668 // If there are no longer any background processes running,
2669 // and the app that died was not running instrumentation,
2670 // then tell everyone we are now low on memory.
2671 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002672 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2673 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2675 haveBg = true;
2676 break;
2677 }
2678 }
2679
2680 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002681 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002682 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002683 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002684 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2685 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002686 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002687 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2688 // The low memory report is overriding any current
2689 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002690 // heavy/important/visible/foreground processes first.
2691 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002692 rec.lastRequestedGc = 0;
2693 } else {
2694 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002695 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002696 rec.reportLowMemory = true;
2697 rec.lastLowMemory = now;
2698 mProcessesToGc.remove(rec);
2699 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700 }
2701 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002702 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 }
2704 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002705 } else if (app.pid != pid) {
2706 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002707 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002708 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002709 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002710 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002711 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 + thread.asBinder());
2713 }
2714 }
2715
Dan Egnor42471dd2010-01-07 17:25:22 -08002716 /**
2717 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002718 * @param clearTraces causes the dump file to be erased prior to the new
2719 * traces being written, if true; when false, the new traces will be
2720 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002721 * @param firstPids of dalvik VM processes to dump stack traces for first
2722 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002723 * @return file containing stack traces, or null if no dump file is configured
2724 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002725 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2726 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002727 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2728 if (tracesPath == null || tracesPath.length() == 0) {
2729 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002731
2732 File tracesFile = new File(tracesPath);
2733 try {
2734 File tracesDir = tracesFile.getParentFile();
2735 if (!tracesDir.exists()) tracesFile.mkdirs();
2736 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2737
Christopher Tate6ee412d2010-05-28 12:01:56 -07002738 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002739 tracesFile.createNewFile();
2740 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2741 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002742 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002743 return null;
2744 }
2745
2746 // Use a FileObserver to detect when traces finish writing.
2747 // The order of traces is considered important to maintain for legibility.
2748 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2749 public synchronized void onEvent(int event, String path) { notify(); }
2750 };
2751
2752 try {
2753 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002754
2755 // First collect all of the stacks of the most important pids.
2756 try {
2757 int num = firstPids.size();
2758 for (int i = 0; i < num; i++) {
2759 synchronized (observer) {
2760 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2761 observer.wait(200); // Wait for write-close, give up after 200msec
2762 }
2763 }
2764 } catch (InterruptedException e) {
2765 Log.wtf(TAG, e);
2766 }
2767
2768 // Next measure CPU usage.
2769 if (processStats != null) {
2770 processStats.init();
2771 System.gc();
2772 processStats.update();
2773 try {
2774 synchronized (processStats) {
2775 processStats.wait(500); // measure over 1/2 second.
2776 }
2777 } catch (InterruptedException e) {
2778 }
2779 processStats.update();
2780
2781 // We'll take the stack crawls of just the top apps using CPU.
2782 final int N = processStats.countWorkingStats();
2783 int numProcs = 0;
2784 for (int i=0; i<N && numProcs<5; i++) {
2785 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2786 if (lastPids.indexOfKey(stats.pid) >= 0) {
2787 numProcs++;
2788 try {
2789 synchronized (observer) {
2790 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2791 observer.wait(200); // Wait for write-close, give up after 200msec
2792 }
2793 } catch (InterruptedException e) {
2794 Log.wtf(TAG, e);
2795 }
2796
2797 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002798 }
2799 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002800
2801 return tracesFile;
2802
Dan Egnor42471dd2010-01-07 17:25:22 -08002803 } finally {
2804 observer.stopWatching();
2805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002806 }
2807
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002808 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2809 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002810 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2811 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2812
Dianne Hackborn287952c2010-09-22 22:34:31 -07002813 if (mController != null) {
2814 try {
2815 // 0 == continue, -1 = kill process immediately
2816 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2817 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2818 } catch (RemoteException e) {
2819 mController = null;
2820 }
2821 }
2822
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002823 long anrTime = SystemClock.uptimeMillis();
2824 if (MONITOR_CPU_USAGE) {
2825 updateCpuStatsNow();
2826 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002827
2828 synchronized (this) {
2829 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2830 if (mShuttingDown) {
2831 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2832 return;
2833 } else if (app.notResponding) {
2834 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2835 return;
2836 } else if (app.crashing) {
2837 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2838 return;
2839 }
2840
2841 // In case we come through here for the same app before completing
2842 // this one, mark as anring now so we will bail out.
2843 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002844
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002845 // Log the ANR to the event log.
2846 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2847 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002848
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002849 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002850 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002851
2852 int parentPid = app.pid;
2853 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002854 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002855
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002856 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002857
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002858 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2859 ProcessRecord r = mLruProcesses.get(i);
2860 if (r != null && r.thread != null) {
2861 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002862 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2863 if (r.persistent) {
2864 firstPids.add(pid);
2865 } else {
2866 lastPids.put(pid, Boolean.TRUE);
2867 }
2868 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002870 }
2871 }
2872
Dan Egnor42471dd2010-01-07 17:25:22 -08002873 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002874 StringBuilder info = mStringBuilder;
2875 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002876 info.append("ANR in ").append(app.processName);
2877 if (activity != null && activity.shortComponentName != null) {
2878 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002879 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002880 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002881 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002882 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002884 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002885 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887
Dianne Hackborn287952c2010-09-22 22:34:31 -07002888 final ProcessStats processStats = new ProcessStats(true);
2889
2890 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2891
Dan Egnor42471dd2010-01-07 17:25:22 -08002892 String cpuInfo = null;
2893 if (MONITOR_CPU_USAGE) {
2894 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002895 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002896 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002897 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002898 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002899 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 }
2901
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002902 info.append(processStats.printCurrentState(anrTime));
2903
Joe Onorato8a9b2202010-02-26 18:56:32 -08002904 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002905 if (tracesFile == null) {
2906 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2907 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2908 }
2909
2910 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2911
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002912 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002914 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2915 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002916 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002917 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2918 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002919 }
2920 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002921 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002922 }
2923 }
2924
Dan Egnor42471dd2010-01-07 17:25:22 -08002925 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2926 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2927 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002928
2929 synchronized (this) {
2930 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2931 Process.killProcess(app.pid);
2932 return;
2933 }
2934
2935 // Set the app's notResponding state, and look up the errorReportReceiver
2936 makeAppNotRespondingLocked(app,
2937 activity != null ? activity.shortComponentName : null,
2938 annotation != null ? "ANR " + annotation : "ANR",
2939 info.toString());
2940
2941 // Bring up the infamous App Not Responding dialog
2942 Message msg = Message.obtain();
2943 HashMap map = new HashMap();
2944 msg.what = SHOW_NOT_RESPONDING_MSG;
2945 msg.obj = map;
2946 map.put("app", app);
2947 if (activity != null) {
2948 map.put("activity", activity);
2949 }
2950
2951 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 }
2954
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002955 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2956 if (!mLaunchWarningShown) {
2957 mLaunchWarningShown = true;
2958 mHandler.post(new Runnable() {
2959 @Override
2960 public void run() {
2961 synchronized (ActivityManagerService.this) {
2962 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2963 d.show();
2964 mHandler.postDelayed(new Runnable() {
2965 @Override
2966 public void run() {
2967 synchronized (ActivityManagerService.this) {
2968 d.dismiss();
2969 mLaunchWarningShown = false;
2970 }
2971 }
2972 }, 4000);
2973 }
2974 }
2975 });
2976 }
2977 }
2978
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002979 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 app.persistentActivities--;
2981 if (app.persistentActivities > 0) {
2982 // Still more of 'em...
2983 return;
2984 }
2985 if (app.persistent) {
2986 // Ah, but the application itself is persistent. Whatever!
2987 return;
2988 }
2989
2990 // App is no longer persistent... make sure it and the ones
2991 // following it in the LRU list have the correc oom_adj.
2992 updateOomAdjLocked();
2993 }
2994
2995 public void setPersistent(IBinder token, boolean isPersistent) {
2996 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
2997 != PackageManager.PERMISSION_GRANTED) {
2998 String msg = "Permission Denial: setPersistent() from pid="
2999 + Binder.getCallingPid()
3000 + ", uid=" + Binder.getCallingUid()
3001 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003002 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 throw new SecurityException(msg);
3004 }
3005
3006 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003007 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 if (index < 0) {
3009 return;
3010 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003011 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 ProcessRecord app = r.app;
3013
Joe Onorato8a9b2202010-02-26 18:56:32 -08003014 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 TAG, "Setting persistence " + isPersistent + ": " + r);
3016
3017 if (isPersistent) {
3018 if (r.persistent) {
3019 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003020 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 return;
3022 }
3023 r.persistent = true;
3024 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003025 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 if (app.persistentActivities > 1) {
3027 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003028 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003029 return;
3030 }
3031 if (app.persistent) {
3032 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003033 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 return;
3035 }
3036
3037 // App is now persistent... make sure it and the ones
3038 // following it now have the correct oom_adj.
3039 final long origId = Binder.clearCallingIdentity();
3040 updateOomAdjLocked();
3041 Binder.restoreCallingIdentity(origId);
3042
3043 } else {
3044 if (!r.persistent) {
3045 // Okay okay, I heard you already!
3046 return;
3047 }
3048 r.persistent = false;
3049 final long origId = Binder.clearCallingIdentity();
3050 decPersistentCountLocked(app);
3051 Binder.restoreCallingIdentity(origId);
3052
3053 }
3054 }
3055 }
3056
3057 public boolean clearApplicationUserData(final String packageName,
3058 final IPackageDataObserver observer) {
3059 int uid = Binder.getCallingUid();
3060 int pid = Binder.getCallingPid();
3061 long callingId = Binder.clearCallingIdentity();
3062 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003063 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 int pkgUid = -1;
3065 synchronized(this) {
3066 try {
3067 pkgUid = pm.getPackageUid(packageName);
3068 } catch (RemoteException e) {
3069 }
3070 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003071 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 return false;
3073 }
3074 if (uid == pkgUid || checkComponentPermission(
3075 android.Manifest.permission.CLEAR_APP_USER_DATA,
3076 pid, uid, -1)
3077 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003078 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079 } else {
3080 throw new SecurityException(pid+" does not have permission:"+
3081 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3082 "for process:"+packageName);
3083 }
3084 }
3085
3086 try {
3087 //clear application user data
3088 pm.clearApplicationUserData(packageName, observer);
3089 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3090 Uri.fromParts("package", packageName, null));
3091 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003092 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3093 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 } catch (RemoteException e) {
3095 }
3096 } finally {
3097 Binder.restoreCallingIdentity(callingId);
3098 }
3099 return true;
3100 }
3101
Dianne Hackborn03abb812010-01-04 18:43:19 -08003102 public void killBackgroundProcesses(final String packageName) {
3103 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3104 != PackageManager.PERMISSION_GRANTED &&
3105 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3106 != PackageManager.PERMISSION_GRANTED) {
3107 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 + Binder.getCallingPid()
3109 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003110 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003111 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003112 throw new SecurityException(msg);
3113 }
3114
3115 long callingId = Binder.clearCallingIdentity();
3116 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003117 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003118 int pkgUid = -1;
3119 synchronized(this) {
3120 try {
3121 pkgUid = pm.getPackageUid(packageName);
3122 } catch (RemoteException e) {
3123 }
3124 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003125 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 return;
3127 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003128 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003129 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003130 }
3131 } finally {
3132 Binder.restoreCallingIdentity(callingId);
3133 }
3134 }
3135
3136 public void forceStopPackage(final String packageName) {
3137 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3138 != PackageManager.PERMISSION_GRANTED) {
3139 String msg = "Permission Denial: forceStopPackage() from pid="
3140 + Binder.getCallingPid()
3141 + ", uid=" + Binder.getCallingUid()
3142 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003143 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003144 throw new SecurityException(msg);
3145 }
3146
3147 long callingId = Binder.clearCallingIdentity();
3148 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003149 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003150 int pkgUid = -1;
3151 synchronized(this) {
3152 try {
3153 pkgUid = pm.getPackageUid(packageName);
3154 } catch (RemoteException e) {
3155 }
3156 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003157 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003158 return;
3159 }
3160 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003161 }
3162 } finally {
3163 Binder.restoreCallingIdentity(callingId);
3164 }
3165 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003166
3167 /*
3168 * The pkg name and uid have to be specified.
3169 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3170 */
3171 public void killApplicationWithUid(String pkg, int uid) {
3172 if (pkg == null) {
3173 return;
3174 }
3175 // Make sure the uid is valid.
3176 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003177 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003178 return;
3179 }
3180 int callerUid = Binder.getCallingUid();
3181 // Only the system server can kill an application
3182 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003183 // Post an aysnc message to kill the application
3184 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3185 msg.arg1 = uid;
3186 msg.arg2 = 0;
3187 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003188 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003189 } else {
3190 throw new SecurityException(callerUid + " cannot kill pkg: " +
3191 pkg);
3192 }
3193 }
3194
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003195 public void closeSystemDialogs(String reason) {
3196 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003197 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003198 if (reason != null) {
3199 intent.putExtra("reason", reason);
3200 }
3201
3202 final int uid = Binder.getCallingUid();
3203 final long origId = Binder.clearCallingIdentity();
3204 synchronized (this) {
3205 int i = mWatchers.beginBroadcast();
3206 while (i > 0) {
3207 i--;
3208 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3209 if (w != null) {
3210 try {
3211 w.closingSystemDialogs(reason);
3212 } catch (RemoteException e) {
3213 }
3214 }
3215 }
3216 mWatchers.finishBroadcast();
3217
Dianne Hackbornffa42482009-09-23 22:20:11 -07003218 mWindowManager.closeSystemDialogs(reason);
3219
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003220 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3221 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003222 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003223 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003224 Activity.RESULT_CANCELED, null, "close-sys");
3225 }
3226 }
3227
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003228 broadcastIntentLocked(null, null, intent, null,
3229 null, 0, null, null, null, false, false, -1, uid);
3230 }
3231 Binder.restoreCallingIdentity(origId);
3232 }
3233
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003234 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003235 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003236 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3237 for (int i=pids.length-1; i>=0; i--) {
3238 infos[i] = new Debug.MemoryInfo();
3239 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003240 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003241 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003242 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003243
3244 public void killApplicationProcess(String processName, int uid) {
3245 if (processName == null) {
3246 return;
3247 }
3248
3249 int callerUid = Binder.getCallingUid();
3250 // Only the system server can kill an application
3251 if (callerUid == Process.SYSTEM_UID) {
3252 synchronized (this) {
3253 ProcessRecord app = getProcessRecordLocked(processName, uid);
3254 if (app != null) {
3255 try {
3256 app.thread.scheduleSuicide();
3257 } catch (RemoteException e) {
3258 // If the other end already died, then our work here is done.
3259 }
3260 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003261 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003262 + processName + " / " + uid);
3263 }
3264 }
3265 } else {
3266 throw new SecurityException(callerUid + " cannot kill app process: " +
3267 processName);
3268 }
3269 }
3270
Dianne Hackborn03abb812010-01-04 18:43:19 -08003271 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003272 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3274 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003275 if (!mProcessesReady) {
3276 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 intent.putExtra(Intent.EXTRA_UID, uid);
3279 broadcastIntentLocked(null, null, intent,
3280 null, null, 0, null, null, null,
3281 false, false, MY_PID, Process.SYSTEM_UID);
3282 }
3283
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003284 private final boolean killPackageProcessesLocked(String packageName, int uid,
3285 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003286 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287
Dianne Hackborn03abb812010-01-04 18:43:19 -08003288 // Remove all processes this package may have touched: all with the
3289 // same UID (except for the system or root user), and all whose name
3290 // matches the package name.
3291 final String procNamePrefix = packageName + ":";
3292 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3293 final int NA = apps.size();
3294 for (int ia=0; ia<NA; ia++) {
3295 ProcessRecord app = apps.valueAt(ia);
3296 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003297 if (doit) {
3298 procs.add(app);
3299 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003300 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3301 || app.processName.equals(packageName)
3302 || app.processName.startsWith(procNamePrefix)) {
3303 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003304 if (!doit) {
3305 return true;
3306 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003307 app.removed = true;
3308 procs.add(app);
3309 }
3310 }
3311 }
3312 }
3313
3314 int N = procs.size();
3315 for (int i=0; i<N; i++) {
3316 removeProcessLocked(procs.get(i), callerWillRestart);
3317 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003318 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003319 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003320
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003321 private final boolean forceStopPackageLocked(String name, int uid,
3322 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 int i, N;
3324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 if (uid < 0) {
3326 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003327 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 } catch (RemoteException e) {
3329 }
3330 }
3331
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003332 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003333 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003334
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003335 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3336 while (badApps.hasNext()) {
3337 SparseArray<Long> ba = badApps.next();
3338 if (ba.get(uid) != null) {
3339 badApps.remove();
3340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 }
3342 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003343
3344 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3345 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003347 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3348 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003350 if (!doit) {
3351 return true;
3352 }
3353 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003354 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003355 if (r.app != null) {
3356 r.app.removed = true;
3357 }
3358 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003359 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003360 }
3361 }
3362
3363 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3364 for (ServiceRecord service : mServices.values()) {
3365 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003366 if (!doit) {
3367 return true;
3368 }
3369 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003370 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 if (service.app != null) {
3372 service.app.removed = true;
3373 }
3374 service.app = null;
3375 services.add(service);
3376 }
3377 }
3378
3379 N = services.size();
3380 for (i=0; i<N; i++) {
3381 bringDownServiceLocked(services.get(i), true);
3382 }
3383
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003384 if (doit) {
3385 if (purgeCache) {
3386 AttributeCache ac = AttributeCache.instance();
3387 if (ac != null) {
3388 ac.removePackage(name);
3389 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003390 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003391 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003392 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003393
3394 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 }
3396
3397 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3398 final String name = app.processName;
3399 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003400 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 TAG, "Force removing process " + app + " (" + name
3402 + "/" + uid + ")");
3403
3404 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003405 if (mHeavyWeightProcess == app) {
3406 mHeavyWeightProcess = null;
3407 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 boolean needRestart = false;
3410 if (app.pid > 0 && app.pid != MY_PID) {
3411 int pid = app.pid;
3412 synchronized (mPidsSelfLocked) {
3413 mPidsSelfLocked.remove(pid);
3414 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3415 }
3416 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003417 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 Process.killProcess(pid);
3419
3420 if (app.persistent) {
3421 if (!callerWillRestart) {
3422 addAppLocked(app.info);
3423 } else {
3424 needRestart = true;
3425 }
3426 }
3427 } else {
3428 mRemovedProcesses.add(app);
3429 }
3430
3431 return needRestart;
3432 }
3433
3434 private final void processStartTimedOutLocked(ProcessRecord app) {
3435 final int pid = app.pid;
3436 boolean gone = false;
3437 synchronized (mPidsSelfLocked) {
3438 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3439 if (knownApp != null && knownApp.thread == null) {
3440 mPidsSelfLocked.remove(pid);
3441 gone = true;
3442 }
3443 }
3444
3445 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003446 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003447 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003448 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003450 if (mHeavyWeightProcess == app) {
3451 mHeavyWeightProcess = null;
3452 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3453 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003454 // Take care of any launching providers waiting for this process.
3455 checkAppInLaunchingProvidersLocked(app, true);
3456 // Take care of any services that are waiting for the process.
3457 for (int i=0; i<mPendingServices.size(); i++) {
3458 ServiceRecord sr = mPendingServices.get(i);
3459 if (app.info.uid == sr.appInfo.uid
3460 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003461 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003462 mPendingServices.remove(i);
3463 i--;
3464 bringDownServiceLocked(sr, true);
3465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003467 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003468 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003469 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003470 try {
3471 IBackupManager bm = IBackupManager.Stub.asInterface(
3472 ServiceManager.getService(Context.BACKUP_SERVICE));
3473 bm.agentDisconnected(app.info.packageName);
3474 } catch (RemoteException e) {
3475 // Can't happen; the backup manager is local
3476 }
3477 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003478 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003479 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003480 mPendingBroadcast.state = BroadcastRecord.IDLE;
3481 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003482 mPendingBroadcast = null;
3483 scheduleBroadcastsLocked();
3484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003486 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003487 }
3488 }
3489
3490 private final boolean attachApplicationLocked(IApplicationThread thread,
3491 int pid) {
3492
3493 // Find the application record that is being attached... either via
3494 // the pid if we are running in multiple processes, or just pull the
3495 // next app record if we are emulating process with anonymous threads.
3496 ProcessRecord app;
3497 if (pid != MY_PID && pid >= 0) {
3498 synchronized (mPidsSelfLocked) {
3499 app = mPidsSelfLocked.get(pid);
3500 }
3501 } else if (mStartingProcesses.size() > 0) {
3502 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003503 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 } else {
3505 app = null;
3506 }
3507
3508 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003509 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003511 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 if (pid > 0 && pid != MY_PID) {
3513 Process.killProcess(pid);
3514 } else {
3515 try {
3516 thread.scheduleExit();
3517 } catch (Exception e) {
3518 // Ignore exceptions.
3519 }
3520 }
3521 return false;
3522 }
3523
3524 // If this application record is still attached to a previous
3525 // process, clean it up now.
3526 if (app.thread != null) {
3527 handleAppDiedLocked(app, true);
3528 }
3529
3530 // Tell the process all about itself.
3531
Joe Onorato8a9b2202010-02-26 18:56:32 -08003532 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 TAG, "Binding process pid " + pid + " to record " + app);
3534
3535 String processName = app.processName;
3536 try {
3537 thread.asBinder().linkToDeath(new AppDeathRecipient(
3538 app, pid, thread), 0);
3539 } catch (RemoteException e) {
3540 app.resetPackageList();
3541 startProcessLocked(app, "link fail", processName);
3542 return false;
3543 }
3544
Doug Zongker2bec3d42009-12-04 12:52:44 -08003545 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546
3547 app.thread = thread;
3548 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003549 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3550 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 app.forcingToForeground = null;
3552 app.foregroundServices = false;
3553 app.debugging = false;
3554
3555 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3556
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003557 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003558 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003560 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003561 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003562 }
3563
Joe Onorato8a9b2202010-02-26 18:56:32 -08003564 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 TAG, "New app record " + app
3566 + " thread=" + thread.asBinder() + " pid=" + pid);
3567 try {
3568 int testMode = IApplicationThread.DEBUG_OFF;
3569 if (mDebugApp != null && mDebugApp.equals(processName)) {
3570 testMode = mWaitForDebugger
3571 ? IApplicationThread.DEBUG_WAIT
3572 : IApplicationThread.DEBUG_ON;
3573 app.debugging = true;
3574 if (mDebugTransient) {
3575 mDebugApp = mOrigDebugApp;
3576 mWaitForDebugger = mOrigWaitForDebugger;
3577 }
3578 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003579
Christopher Tate181fafa2009-05-14 11:12:14 -07003580 // If the app is being launched for restore or full backup, set it up specially
3581 boolean isRestrictedBackupMode = false;
3582 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3583 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3584 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3585 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003586
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003587 ensurePackageDexOpt(app.instrumentationInfo != null
3588 ? app.instrumentationInfo.packageName
3589 : app.info.packageName);
3590 if (app.instrumentationClass != null) {
3591 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003592 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003593 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003594 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003595 thread.bindApplication(processName, app.instrumentationInfo != null
3596 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003597 app.instrumentationClass, app.instrumentationProfileFile,
3598 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003599 isRestrictedBackupMode || !normalMode,
3600 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003601 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003602 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 } catch (Exception e) {
3604 // todo: Yikes! What should we do? For now we will try to
3605 // start another process, but that could easily get us in
3606 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003607 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608
3609 app.resetPackageList();
3610 startProcessLocked(app, "bind fail", processName);
3611 return false;
3612 }
3613
3614 // Remove this record from the list of starting applications.
3615 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003616 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3617 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003618 mProcessesOnHold.remove(app);
3619
3620 boolean badApp = false;
3621 boolean didSomething = false;
3622
3623 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003624 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003625 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3627 && processName.equals(hr.processName)) {
3628 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003629 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 didSomething = true;
3631 }
3632 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003633 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 + hr.intent.getComponent().flattenToShortString(), e);
3635 badApp = true;
3636 }
3637 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003638 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003639 }
3640 }
3641
3642 // Find any services that should be running in this process...
3643 if (!badApp && mPendingServices.size() > 0) {
3644 ServiceRecord sr = null;
3645 try {
3646 for (int i=0; i<mPendingServices.size(); i++) {
3647 sr = mPendingServices.get(i);
3648 if (app.info.uid != sr.appInfo.uid
3649 || !processName.equals(sr.processName)) {
3650 continue;
3651 }
3652
3653 mPendingServices.remove(i);
3654 i--;
3655 realStartServiceLocked(sr, app);
3656 didSomething = true;
3657 }
3658 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003659 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 + sr.shortName, e);
3661 badApp = true;
3662 }
3663 }
3664
3665 // Check if the next broadcast receiver is in this process...
3666 BroadcastRecord br = mPendingBroadcast;
3667 if (!badApp && br != null && br.curApp == app) {
3668 try {
3669 mPendingBroadcast = null;
3670 processCurBroadcastLocked(br, app);
3671 didSomething = true;
3672 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003673 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 + br.curComponent.flattenToShortString(), e);
3675 badApp = true;
3676 logBroadcastReceiverDiscard(br);
3677 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3678 br.resultExtras, br.resultAbort, true);
3679 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003680 // We need to reset the state if we fails to start the receiver.
3681 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 }
3683 }
3684
Christopher Tate181fafa2009-05-14 11:12:14 -07003685 // Check whether the next backup agent is in this process...
3686 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003687 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003688 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003689 try {
3690 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3691 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003692 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003693 e.printStackTrace();
3694 }
3695 }
3696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 if (badApp) {
3698 // todo: Also need to kill application to deal with all
3699 // kinds of exceptions.
3700 handleAppDiedLocked(app, false);
3701 return false;
3702 }
3703
3704 if (!didSomething) {
3705 updateOomAdjLocked();
3706 }
3707
3708 return true;
3709 }
3710
3711 public final void attachApplication(IApplicationThread thread) {
3712 synchronized (this) {
3713 int callingPid = Binder.getCallingPid();
3714 final long origId = Binder.clearCallingIdentity();
3715 attachApplicationLocked(thread, callingPid);
3716 Binder.restoreCallingIdentity(origId);
3717 }
3718 }
3719
Dianne Hackborne88846e2009-09-30 21:34:25 -07003720 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003722 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003723 Binder.restoreCallingIdentity(origId);
3724 }
3725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003726 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003727 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003728 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 mWindowManager.enableScreenAfterBoot();
3730 }
3731
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003732 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003733 IntentFilter pkgFilter = new IntentFilter();
3734 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3735 pkgFilter.addDataScheme("package");
3736 mContext.registerReceiver(new BroadcastReceiver() {
3737 @Override
3738 public void onReceive(Context context, Intent intent) {
3739 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3740 if (pkgs != null) {
3741 for (String pkg : pkgs) {
3742 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3743 setResultCode(Activity.RESULT_OK);
3744 return;
3745 }
3746 }
3747 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003748 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003749 }, pkgFilter);
3750
3751 synchronized (this) {
3752 // Ensure that any processes we had put on hold are now started
3753 // up.
3754 final int NP = mProcessesOnHold.size();
3755 if (NP > 0) {
3756 ArrayList<ProcessRecord> procs =
3757 new ArrayList<ProcessRecord>(mProcessesOnHold);
3758 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003759 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3760 + procs.get(ip));
3761 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003762 }
3763 }
3764
3765 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003766 // Start looking for apps that are abusing wake locks.
3767 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003768 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003769 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003770 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003771 broadcastIntentLocked(null, null,
3772 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3773 null, null, 0, null, null,
3774 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3775 false, false, MY_PID, Process.SYSTEM_UID);
3776 }
3777 }
3778 }
3779
3780 final void ensureBootCompleted() {
3781 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003782 boolean enableScreen;
3783 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003784 booting = mBooting;
3785 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003786 enableScreen = !mBooted;
3787 mBooted = true;
3788 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003789
3790 if (booting) {
3791 finishBooting();
3792 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003793
3794 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003795 enableScreenAfterBoot();
3796 }
3797 }
3798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 public final void activityPaused(IBinder token, Bundle icicle) {
3800 // Refuse possible leaked file descriptors
3801 if (icicle != null && icicle.hasFileDescriptors()) {
3802 throw new IllegalArgumentException("File descriptors passed in Bundle");
3803 }
3804
3805 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003806 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 Binder.restoreCallingIdentity(origId);
3808 }
3809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 public final void activityStopped(IBinder token, Bitmap thumbnail,
3811 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003812 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 TAG, "Activity stopped: token=" + token);
3814
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003815 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816
3817 final long origId = Binder.clearCallingIdentity();
3818
3819 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003820 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003822 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 r.thumbnail = thumbnail;
3824 r.description = description;
3825 r.stopped = true;
3826 r.state = ActivityState.STOPPED;
3827 if (!r.finishing) {
3828 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003829 r.stack.destroyActivityLocked(r, true);
3830 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 }
3832 }
3833 }
3834 }
3835
3836 if (r != null) {
3837 sendPendingThumbnail(r, null, null, null, false);
3838 }
3839
3840 trimApplications();
3841
3842 Binder.restoreCallingIdentity(origId);
3843 }
3844
3845 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003846 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003847 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003848 }
3849
3850 public String getCallingPackage(IBinder token) {
3851 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003852 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003853 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 }
3855 }
3856
3857 public ComponentName getCallingActivity(IBinder token) {
3858 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003859 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 return r != null ? r.intent.getComponent() : null;
3861 }
3862 }
3863
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003864 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003865 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003867 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003868 if (r != null) {
3869 return r.resultTo;
3870 }
3871 }
3872 return null;
3873 }
3874
3875 public ComponentName getActivityClassForToken(IBinder token) {
3876 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003877 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003878 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003879 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003880 return r.intent.getComponent();
3881 }
3882 return null;
3883 }
3884 }
3885
3886 public String getPackageForToken(IBinder token) {
3887 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003888 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003890 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003891 return r.packageName;
3892 }
3893 return null;
3894 }
3895 }
3896
3897 public IIntentSender getIntentSender(int type,
3898 String packageName, IBinder token, String resultWho,
3899 int requestCode, Intent intent, String resolvedType, int flags) {
3900 // Refuse possible leaked file descriptors
3901 if (intent != null && intent.hasFileDescriptors() == true) {
3902 throw new IllegalArgumentException("File descriptors passed in Intent");
3903 }
3904
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003905 if (type == INTENT_SENDER_BROADCAST) {
3906 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3907 throw new IllegalArgumentException(
3908 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3909 }
3910 }
3911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 synchronized(this) {
3913 int callingUid = Binder.getCallingUid();
3914 try {
3915 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3916 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003917 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 .getPackageUid(packageName);
3919 if (uid != Binder.getCallingUid()) {
3920 String msg = "Permission Denial: getIntentSender() from pid="
3921 + Binder.getCallingPid()
3922 + ", uid=" + Binder.getCallingUid()
3923 + ", (need uid=" + uid + ")"
3924 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003925 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 throw new SecurityException(msg);
3927 }
3928 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003929
3930 return getIntentSenderLocked(type, packageName, callingUid,
3931 token, resultWho, requestCode, intent, resolvedType, flags);
3932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 } catch (RemoteException e) {
3934 throw new SecurityException(e);
3935 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003936 }
3937 }
3938
3939 IIntentSender getIntentSenderLocked(int type,
3940 String packageName, int callingUid, IBinder token, String resultWho,
3941 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003942 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003943 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003944 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003945 if (index < 0) {
3946 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003947 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003948 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003949 if (activity.finishing) {
3950 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003952 }
3953
3954 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3955 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3956 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3957 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3958 |PendingIntent.FLAG_UPDATE_CURRENT);
3959
3960 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3961 type, packageName, activity, resultWho,
3962 requestCode, intent, resolvedType, flags);
3963 WeakReference<PendingIntentRecord> ref;
3964 ref = mIntentSenderRecords.get(key);
3965 PendingIntentRecord rec = ref != null ? ref.get() : null;
3966 if (rec != null) {
3967 if (!cancelCurrent) {
3968 if (updateCurrent) {
3969 rec.key.requestIntent.replaceExtras(intent);
3970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 return rec;
3972 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003973 rec.canceled = true;
3974 mIntentSenderRecords.remove(key);
3975 }
3976 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 return rec;
3978 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003979 rec = new PendingIntentRecord(this, key, callingUid);
3980 mIntentSenderRecords.put(key, rec.ref);
3981 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3982 if (activity.pendingResults == null) {
3983 activity.pendingResults
3984 = new HashSet<WeakReference<PendingIntentRecord>>();
3985 }
3986 activity.pendingResults.add(rec.ref);
3987 }
3988 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003989 }
3990
3991 public void cancelIntentSender(IIntentSender sender) {
3992 if (!(sender instanceof PendingIntentRecord)) {
3993 return;
3994 }
3995 synchronized(this) {
3996 PendingIntentRecord rec = (PendingIntentRecord)sender;
3997 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003998 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 .getPackageUid(rec.key.packageName);
4000 if (uid != Binder.getCallingUid()) {
4001 String msg = "Permission Denial: cancelIntentSender() from pid="
4002 + Binder.getCallingPid()
4003 + ", uid=" + Binder.getCallingUid()
4004 + " is not allowed to cancel packges "
4005 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004006 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 throw new SecurityException(msg);
4008 }
4009 } catch (RemoteException e) {
4010 throw new SecurityException(e);
4011 }
4012 cancelIntentSenderLocked(rec, true);
4013 }
4014 }
4015
4016 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4017 rec.canceled = true;
4018 mIntentSenderRecords.remove(rec.key);
4019 if (cleanActivity && rec.key.activity != null) {
4020 rec.key.activity.pendingResults.remove(rec.ref);
4021 }
4022 }
4023
4024 public String getPackageForIntentSender(IIntentSender pendingResult) {
4025 if (!(pendingResult instanceof PendingIntentRecord)) {
4026 return null;
4027 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004028 try {
4029 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4030 return res.key.packageName;
4031 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 }
4033 return null;
4034 }
4035
4036 public void setProcessLimit(int max) {
4037 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4038 "setProcessLimit()");
4039 mProcessLimit = max;
4040 }
4041
4042 public int getProcessLimit() {
4043 return mProcessLimit;
4044 }
4045
4046 void foregroundTokenDied(ForegroundToken token) {
4047 synchronized (ActivityManagerService.this) {
4048 synchronized (mPidsSelfLocked) {
4049 ForegroundToken cur
4050 = mForegroundProcesses.get(token.pid);
4051 if (cur != token) {
4052 return;
4053 }
4054 mForegroundProcesses.remove(token.pid);
4055 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4056 if (pr == null) {
4057 return;
4058 }
4059 pr.forcingToForeground = null;
4060 pr.foregroundServices = false;
4061 }
4062 updateOomAdjLocked();
4063 }
4064 }
4065
4066 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4067 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4068 "setProcessForeground()");
4069 synchronized(this) {
4070 boolean changed = false;
4071
4072 synchronized (mPidsSelfLocked) {
4073 ProcessRecord pr = mPidsSelfLocked.get(pid);
4074 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004075 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004076 return;
4077 }
4078 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4079 if (oldToken != null) {
4080 oldToken.token.unlinkToDeath(oldToken, 0);
4081 mForegroundProcesses.remove(pid);
4082 pr.forcingToForeground = null;
4083 changed = true;
4084 }
4085 if (isForeground && token != null) {
4086 ForegroundToken newToken = new ForegroundToken() {
4087 public void binderDied() {
4088 foregroundTokenDied(this);
4089 }
4090 };
4091 newToken.pid = pid;
4092 newToken.token = token;
4093 try {
4094 token.linkToDeath(newToken, 0);
4095 mForegroundProcesses.put(pid, newToken);
4096 pr.forcingToForeground = token;
4097 changed = true;
4098 } catch (RemoteException e) {
4099 // If the process died while doing this, we will later
4100 // do the cleanup with the process death link.
4101 }
4102 }
4103 }
4104
4105 if (changed) {
4106 updateOomAdjLocked();
4107 }
4108 }
4109 }
4110
4111 // =========================================================
4112 // PERMISSIONS
4113 // =========================================================
4114
4115 static class PermissionController extends IPermissionController.Stub {
4116 ActivityManagerService mActivityManagerService;
4117 PermissionController(ActivityManagerService activityManagerService) {
4118 mActivityManagerService = activityManagerService;
4119 }
4120
4121 public boolean checkPermission(String permission, int pid, int uid) {
4122 return mActivityManagerService.checkPermission(permission, pid,
4123 uid) == PackageManager.PERMISSION_GRANTED;
4124 }
4125 }
4126
4127 /**
4128 * This can be called with or without the global lock held.
4129 */
4130 int checkComponentPermission(String permission, int pid, int uid,
4131 int reqUid) {
4132 // We might be performing an operation on behalf of an indirect binder
4133 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4134 // client identity accordingly before proceeding.
4135 Identity tlsIdentity = sCallerIdentity.get();
4136 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004137 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004138 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4139 uid = tlsIdentity.uid;
4140 pid = tlsIdentity.pid;
4141 }
4142
4143 // Root, system server and our own process get to do everything.
4144 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4145 !Process.supportsProcesses()) {
4146 return PackageManager.PERMISSION_GRANTED;
4147 }
4148 // If the target requires a specific UID, always fail for others.
4149 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004150 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004151 return PackageManager.PERMISSION_DENIED;
4152 }
4153 if (permission == null) {
4154 return PackageManager.PERMISSION_GRANTED;
4155 }
4156 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004157 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 .checkUidPermission(permission, uid);
4159 } catch (RemoteException e) {
4160 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004161 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 }
4163 return PackageManager.PERMISSION_DENIED;
4164 }
4165
4166 /**
4167 * As the only public entry point for permissions checking, this method
4168 * can enforce the semantic that requesting a check on a null global
4169 * permission is automatically denied. (Internally a null permission
4170 * string is used when calling {@link #checkComponentPermission} in cases
4171 * when only uid-based security is needed.)
4172 *
4173 * This can be called with or without the global lock held.
4174 */
4175 public int checkPermission(String permission, int pid, int uid) {
4176 if (permission == null) {
4177 return PackageManager.PERMISSION_DENIED;
4178 }
4179 return checkComponentPermission(permission, pid, uid, -1);
4180 }
4181
4182 /**
4183 * Binder IPC calls go through the public entry point.
4184 * This can be called with or without the global lock held.
4185 */
4186 int checkCallingPermission(String permission) {
4187 return checkPermission(permission,
4188 Binder.getCallingPid(),
4189 Binder.getCallingUid());
4190 }
4191
4192 /**
4193 * This can be called with or without the global lock held.
4194 */
4195 void enforceCallingPermission(String permission, String func) {
4196 if (checkCallingPermission(permission)
4197 == PackageManager.PERMISSION_GRANTED) {
4198 return;
4199 }
4200
4201 String msg = "Permission Denial: " + func + " from pid="
4202 + Binder.getCallingPid()
4203 + ", uid=" + Binder.getCallingUid()
4204 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004205 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206 throw new SecurityException(msg);
4207 }
4208
4209 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
4210 ProviderInfo pi, int uid, int modeFlags) {
4211 try {
4212 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4213 if ((pi.readPermission != null) &&
4214 (pm.checkUidPermission(pi.readPermission, uid)
4215 != PackageManager.PERMISSION_GRANTED)) {
4216 return false;
4217 }
4218 }
4219 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4220 if ((pi.writePermission != null) &&
4221 (pm.checkUidPermission(pi.writePermission, uid)
4222 != PackageManager.PERMISSION_GRANTED)) {
4223 return false;
4224 }
4225 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004226 if (!pi.exported && pi.applicationInfo.uid != uid) {
4227 return false;
4228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 return true;
4230 } catch (RemoteException e) {
4231 return false;
4232 }
4233 }
4234
4235 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4236 int modeFlags) {
4237 // Root gets to do everything.
4238 if (uid == 0 || !Process.supportsProcesses()) {
4239 return true;
4240 }
4241 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4242 if (perms == null) return false;
4243 UriPermission perm = perms.get(uri);
4244 if (perm == null) return false;
4245 return (modeFlags&perm.modeFlags) == modeFlags;
4246 }
4247
4248 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4249 // Another redirected-binder-call permissions check as in
4250 // {@link checkComponentPermission}.
4251 Identity tlsIdentity = sCallerIdentity.get();
4252 if (tlsIdentity != null) {
4253 uid = tlsIdentity.uid;
4254 pid = tlsIdentity.pid;
4255 }
4256
4257 // Our own process gets to do everything.
4258 if (pid == MY_PID) {
4259 return PackageManager.PERMISSION_GRANTED;
4260 }
4261 synchronized(this) {
4262 return checkUriPermissionLocked(uri, uid, modeFlags)
4263 ? PackageManager.PERMISSION_GRANTED
4264 : PackageManager.PERMISSION_DENIED;
4265 }
4266 }
4267
Dianne Hackborn39792d22010-08-19 18:01:52 -07004268 /**
4269 * Check if the targetPkg can be granted permission to access uri by
4270 * the callingUid using the given modeFlags. Throws a security exception
4271 * if callingUid is not allowed to do this. Returns the uid of the target
4272 * if the URI permission grant should be performed; returns -1 if it is not
4273 * needed (for example targetPkg already has permission to access the URI).
4274 */
4275 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4276 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4278 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4279 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004280 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 }
4282
Joe Onorato8a9b2202010-02-26 18:56:32 -08004283 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004284 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004285
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004286 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287
4288 // If this is not a content: uri, we can't do anything with it.
4289 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004290 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004291 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004292 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 }
4294
4295 String name = uri.getAuthority();
4296 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004297 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 if (cpr != null) {
4299 pi = cpr.info;
4300 } else {
4301 try {
4302 pi = pm.resolveContentProvider(name,
4303 PackageManager.GET_URI_PERMISSION_PATTERNS);
4304 } catch (RemoteException ex) {
4305 }
4306 }
4307 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004308 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004309 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 }
4311
4312 int targetUid;
4313 try {
4314 targetUid = pm.getPackageUid(targetPkg);
4315 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004316 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004317 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004318 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004319 }
4320 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004321 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004322 }
4323
4324 // First... does the target actually need this permission?
4325 if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
4326 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004327 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004328 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004329 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004330 }
4331
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004332 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004333 if (!pi.grantUriPermissions) {
4334 throw new SecurityException("Provider " + pi.packageName
4335 + "/" + pi.name
4336 + " does not allow granting of Uri permissions (uri "
4337 + uri + ")");
4338 }
4339 if (pi.uriPermissionPatterns != null) {
4340 final int N = pi.uriPermissionPatterns.length;
4341 boolean allowed = false;
4342 for (int i=0; i<N; i++) {
4343 if (pi.uriPermissionPatterns[i] != null
4344 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4345 allowed = true;
4346 break;
4347 }
4348 }
4349 if (!allowed) {
4350 throw new SecurityException("Provider " + pi.packageName
4351 + "/" + pi.name
4352 + " does not allow granting of permission to path of Uri "
4353 + uri);
4354 }
4355 }
4356
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004357 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 // this uri?
4359 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4360 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4361 throw new SecurityException("Uid " + callingUid
4362 + " does not have permission to uri " + uri);
4363 }
4364 }
4365
Dianne Hackborn39792d22010-08-19 18:01:52 -07004366 return targetUid;
4367 }
4368
4369 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4370 Uri uri, int modeFlags, UriPermissionOwner owner) {
4371 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4372 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4373 if (modeFlags == 0) {
4374 return;
4375 }
4376
4377 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004378 // to the uri, and the target doesn't. Let's now give this to
4379 // the target.
4380
Joe Onorato8a9b2202010-02-26 18:56:32 -08004381 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004382 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 HashMap<Uri, UriPermission> targetUris
4385 = mGrantedUriPermissions.get(targetUid);
4386 if (targetUris == null) {
4387 targetUris = new HashMap<Uri, UriPermission>();
4388 mGrantedUriPermissions.put(targetUid, targetUris);
4389 }
4390
4391 UriPermission perm = targetUris.get(uri);
4392 if (perm == null) {
4393 perm = new UriPermission(targetUid, uri);
4394 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004398 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399 perm.globalModeFlags |= modeFlags;
4400 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004401 perm.readOwners.add(owner);
4402 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004404 perm.writeOwners.add(owner);
4405 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 }
4407 }
4408
Dianne Hackborn39792d22010-08-19 18:01:52 -07004409 void grantUriPermissionLocked(int callingUid,
4410 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4411 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4412 if (targetUid < 0) {
4413 return;
4414 }
4415
4416 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4417 }
4418
4419 /**
4420 * Like checkGrantUriPermissionLocked, but takes an Intent.
4421 */
4422 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4423 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004424 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004425 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004426 + " from " + intent + "; flags=0x"
4427 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004430 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 }
4432 Uri data = intent.getData();
4433 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004434 return -1;
4435 }
4436 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4437 intent.getFlags());
4438 }
4439
4440 /**
4441 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4442 */
4443 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4444 String targetPkg, Intent intent, UriPermissionOwner owner) {
4445 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4446 intent.getFlags(), owner);
4447 }
4448
4449 void grantUriPermissionFromIntentLocked(int callingUid,
4450 String targetPkg, Intent intent, UriPermissionOwner owner) {
4451 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4452 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 return;
4454 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004455
4456 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 }
4458
4459 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4460 Uri uri, int modeFlags) {
4461 synchronized(this) {
4462 final ProcessRecord r = getRecordForAppLocked(caller);
4463 if (r == null) {
4464 throw new SecurityException("Unable to find app for caller "
4465 + caller
4466 + " when granting permission to uri " + uri);
4467 }
4468 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004469 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004470 }
4471 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004472 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 }
4474
4475 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4476 null);
4477 }
4478 }
4479
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004480 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004481 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4482 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4483 HashMap<Uri, UriPermission> perms
4484 = mGrantedUriPermissions.get(perm.uid);
4485 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004486 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004487 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 perms.remove(perm.uri);
4489 if (perms.size() == 0) {
4490 mGrantedUriPermissions.remove(perm.uid);
4491 }
4492 }
4493 }
4494 }
4495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4497 int modeFlags) {
4498 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4499 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4500 if (modeFlags == 0) {
4501 return;
4502 }
4503
Joe Onorato8a9b2202010-02-26 18:56:32 -08004504 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004505 "Revoking all granted permissions to " + uri);
4506
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004507 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508
4509 final String authority = uri.getAuthority();
4510 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004511 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 if (cpr != null) {
4513 pi = cpr.info;
4514 } else {
4515 try {
4516 pi = pm.resolveContentProvider(authority,
4517 PackageManager.GET_URI_PERMISSION_PATTERNS);
4518 } catch (RemoteException ex) {
4519 }
4520 }
4521 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004522 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 return;
4524 }
4525
4526 // Does the caller have this permission on the URI?
4527 if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
4528 // Right now, if you are not the original owner of the permission,
4529 // you are not allowed to revoke it.
4530 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4531 throw new SecurityException("Uid " + callingUid
4532 + " does not have permission to uri " + uri);
4533 //}
4534 }
4535
4536 // Go through all of the permissions and remove any that match.
4537 final List<String> SEGMENTS = uri.getPathSegments();
4538 if (SEGMENTS != null) {
4539 final int NS = SEGMENTS.size();
4540 int N = mGrantedUriPermissions.size();
4541 for (int i=0; i<N; i++) {
4542 HashMap<Uri, UriPermission> perms
4543 = mGrantedUriPermissions.valueAt(i);
4544 Iterator<UriPermission> it = perms.values().iterator();
4545 toploop:
4546 while (it.hasNext()) {
4547 UriPermission perm = it.next();
4548 Uri targetUri = perm.uri;
4549 if (!authority.equals(targetUri.getAuthority())) {
4550 continue;
4551 }
4552 List<String> targetSegments = targetUri.getPathSegments();
4553 if (targetSegments == null) {
4554 continue;
4555 }
4556 if (targetSegments.size() < NS) {
4557 continue;
4558 }
4559 for (int j=0; j<NS; j++) {
4560 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4561 continue toploop;
4562 }
4563 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004564 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004565 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004566 perm.clearModes(modeFlags);
4567 if (perm.modeFlags == 0) {
4568 it.remove();
4569 }
4570 }
4571 if (perms.size() == 0) {
4572 mGrantedUriPermissions.remove(
4573 mGrantedUriPermissions.keyAt(i));
4574 N--;
4575 i--;
4576 }
4577 }
4578 }
4579 }
4580
4581 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4582 int modeFlags) {
4583 synchronized(this) {
4584 final ProcessRecord r = getRecordForAppLocked(caller);
4585 if (r == null) {
4586 throw new SecurityException("Unable to find app for caller "
4587 + caller
4588 + " when revoking permission to uri " + uri);
4589 }
4590 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004591 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592 return;
4593 }
4594
4595 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4596 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4597 if (modeFlags == 0) {
4598 return;
4599 }
4600
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004601 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602
4603 final String authority = uri.getAuthority();
4604 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004605 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 if (cpr != null) {
4607 pi = cpr.info;
4608 } else {
4609 try {
4610 pi = pm.resolveContentProvider(authority,
4611 PackageManager.GET_URI_PERMISSION_PATTERNS);
4612 } catch (RemoteException ex) {
4613 }
4614 }
4615 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004616 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617 return;
4618 }
4619
4620 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4621 }
4622 }
4623
Dianne Hackborn7e269642010-08-25 19:50:20 -07004624 @Override
4625 public IBinder newUriPermissionOwner(String name) {
4626 synchronized(this) {
4627 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4628 return owner.getExternalTokenLocked();
4629 }
4630 }
4631
4632 @Override
4633 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4634 Uri uri, int modeFlags) {
4635 synchronized(this) {
4636 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4637 if (owner == null) {
4638 throw new IllegalArgumentException("Unknown owner: " + token);
4639 }
4640 if (fromUid != Binder.getCallingUid()) {
4641 if (Binder.getCallingUid() != Process.myUid()) {
4642 // Only system code can grant URI permissions on behalf
4643 // of other users.
4644 throw new SecurityException("nice try");
4645 }
4646 }
4647 if (targetPkg == null) {
4648 throw new IllegalArgumentException("null target");
4649 }
4650 if (uri == null) {
4651 throw new IllegalArgumentException("null uri");
4652 }
4653
4654 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4655 }
4656 }
4657
4658 @Override
4659 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4660 synchronized(this) {
4661 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4662 if (owner == null) {
4663 throw new IllegalArgumentException("Unknown owner: " + token);
4664 }
4665
4666 if (uri == null) {
4667 owner.removeUriPermissionsLocked(mode);
4668 } else {
4669 owner.removeUriPermissionLocked(uri, mode);
4670 }
4671 }
4672 }
4673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004674 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4675 synchronized (this) {
4676 ProcessRecord app =
4677 who != null ? getRecordForAppLocked(who) : null;
4678 if (app == null) return;
4679
4680 Message msg = Message.obtain();
4681 msg.what = WAIT_FOR_DEBUGGER_MSG;
4682 msg.obj = app;
4683 msg.arg1 = waiting ? 1 : 0;
4684 mHandler.sendMessage(msg);
4685 }
4686 }
4687
4688 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4689 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004690 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004692 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004693 }
4694
4695 // =========================================================
4696 // TASK MANAGEMENT
4697 // =========================================================
4698
4699 public List getTasks(int maxNum, int flags,
4700 IThumbnailReceiver receiver) {
4701 ArrayList list = new ArrayList();
4702
4703 PendingThumbnailsRecord pending = null;
4704 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004705 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004706
4707 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004708 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4710 + ", receiver=" + receiver);
4711
4712 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4713 != PackageManager.PERMISSION_GRANTED) {
4714 if (receiver != null) {
4715 // If the caller wants to wait for pending thumbnails,
4716 // it ain't gonna get them.
4717 try {
4718 receiver.finished();
4719 } catch (RemoteException ex) {
4720 }
4721 }
4722 String msg = "Permission Denial: getTasks() from pid="
4723 + Binder.getCallingPid()
4724 + ", uid=" + Binder.getCallingUid()
4725 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004726 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 throw new SecurityException(msg);
4728 }
4729
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004730 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004731 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004732 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004733 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 CharSequence topDescription = null;
4735 TaskRecord curTask = null;
4736 int numActivities = 0;
4737 int numRunning = 0;
4738 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004739 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004741 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742
4743 // Initialize state for next task if needed.
4744 if (top == null ||
4745 (top.state == ActivityState.INITIALIZING
4746 && top.task == r.task)) {
4747 top = r;
4748 topDescription = r.description;
4749 curTask = r.task;
4750 numActivities = numRunning = 0;
4751 }
4752
4753 // Add 'r' into the current task.
4754 numActivities++;
4755 if (r.app != null && r.app.thread != null) {
4756 numRunning++;
4757 }
4758 if (topDescription == null) {
4759 topDescription = r.description;
4760 }
4761
Joe Onorato8a9b2202010-02-26 18:56:32 -08004762 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 TAG, r.intent.getComponent().flattenToShortString()
4764 + ": task=" + r.task);
4765
4766 // If the next one is a different task, generate a new
4767 // TaskInfo entry for what we have.
4768 if (next == null || next.task != curTask) {
4769 ActivityManager.RunningTaskInfo ci
4770 = new ActivityManager.RunningTaskInfo();
4771 ci.id = curTask.taskId;
4772 ci.baseActivity = r.intent.getComponent();
4773 ci.topActivity = top.intent.getComponent();
4774 ci.thumbnail = top.thumbnail;
4775 ci.description = topDescription;
4776 ci.numActivities = numActivities;
4777 ci.numRunning = numRunning;
4778 //System.out.println(
4779 // "#" + maxNum + ": " + " descr=" + ci.description);
4780 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004781 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004782 TAG, "State=" + top.state + "Idle=" + top.idle
4783 + " app=" + top.app
4784 + " thr=" + (top.app != null ? top.app.thread : null));
4785 if (top.state == ActivityState.RESUMED
4786 || top.state == ActivityState.PAUSING) {
4787 if (top.idle && top.app != null
4788 && top.app.thread != null) {
4789 topRecord = top;
4790 topThumbnail = top.app.thread;
4791 } else {
4792 top.thumbnailNeeded = true;
4793 }
4794 }
4795 if (pending == null) {
4796 pending = new PendingThumbnailsRecord(receiver);
4797 }
4798 pending.pendingRecords.add(top);
4799 }
4800 list.add(ci);
4801 maxNum--;
4802 top = null;
4803 }
4804 }
4805
4806 if (pending != null) {
4807 mPendingThumbnails.add(pending);
4808 }
4809 }
4810
Joe Onorato8a9b2202010-02-26 18:56:32 -08004811 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004812
4813 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004814 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 try {
4816 topThumbnail.requestThumbnail(topRecord);
4817 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004818 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004819 sendPendingThumbnail(null, topRecord, null, null, true);
4820 }
4821 }
4822
4823 if (pending == null && receiver != null) {
4824 // In this case all thumbnails were available and the client
4825 // is being asked to be told when the remaining ones come in...
4826 // which is unusually, since the top-most currently running
4827 // activity should never have a canned thumbnail! Oh well.
4828 try {
4829 receiver.finished();
4830 } catch (RemoteException ex) {
4831 }
4832 }
4833
4834 return list;
4835 }
4836
4837 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4838 int flags) {
4839 synchronized (this) {
4840 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4841 "getRecentTasks()");
4842
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004843 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 final int N = mRecentTasks.size();
4846 ArrayList<ActivityManager.RecentTaskInfo> res
4847 = new ArrayList<ActivityManager.RecentTaskInfo>(
4848 maxNum < N ? maxNum : N);
4849 for (int i=0; i<N && maxNum > 0; i++) {
4850 TaskRecord tr = mRecentTasks.get(i);
4851 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4852 || (tr.intent == null)
4853 || ((tr.intent.getFlags()
4854 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4855 ActivityManager.RecentTaskInfo rti
4856 = new ActivityManager.RecentTaskInfo();
4857 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4858 rti.baseIntent = new Intent(
4859 tr.intent != null ? tr.intent : tr.affinityIntent);
4860 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004861
4862 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4863 // Check whether this activity is currently available.
4864 try {
4865 if (rti.origActivity != null) {
4866 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4867 continue;
4868 }
4869 } else if (rti.baseIntent != null) {
4870 if (pm.queryIntentActivities(rti.baseIntent,
4871 null, 0) == null) {
4872 continue;
4873 }
4874 }
4875 } catch (RemoteException e) {
4876 // Will never happen.
4877 }
4878 }
4879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 res.add(rti);
4881 maxNum--;
4882 }
4883 }
4884 return res;
4885 }
4886 }
4887
4888 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4889 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004890 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 TaskRecord jt = startTask;
4892
4893 // First look backwards
4894 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004895 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 if (r.task != jt) {
4897 jt = r.task;
4898 if (affinity.equals(jt.affinity)) {
4899 return j;
4900 }
4901 }
4902 }
4903
4904 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004905 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004906 jt = startTask;
4907 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004908 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004909 if (r.task != jt) {
4910 if (affinity.equals(jt.affinity)) {
4911 return j;
4912 }
4913 jt = r.task;
4914 }
4915 }
4916
4917 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004918 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004919 return N-1;
4920 }
4921
4922 return -1;
4923 }
4924
4925 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004926 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 */
4928 public void moveTaskToFront(int task) {
4929 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4930 "moveTaskToFront()");
4931
4932 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004933 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4934 Binder.getCallingUid(), "Task to front")) {
4935 return;
4936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 final long origId = Binder.clearCallingIdentity();
4938 try {
4939 int N = mRecentTasks.size();
4940 for (int i=0; i<N; i++) {
4941 TaskRecord tr = mRecentTasks.get(i);
4942 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004943 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 return;
4945 }
4946 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004947 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
4948 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004950 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 return;
4952 }
4953 }
4954 } finally {
4955 Binder.restoreCallingIdentity(origId);
4956 }
4957 }
4958 }
4959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 public void moveTaskToBack(int task) {
4961 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4962 "moveTaskToBack()");
4963
4964 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004965 if (mMainStack.mResumedActivity != null
4966 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004967 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4968 Binder.getCallingUid(), "Task to back")) {
4969 return;
4970 }
4971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004972 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004973 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004974 Binder.restoreCallingIdentity(origId);
4975 }
4976 }
4977
4978 /**
4979 * Moves an activity, and all of the other activities within the same task, to the bottom
4980 * of the history stack. The activity's order within the task is unchanged.
4981 *
4982 * @param token A reference to the activity we wish to move
4983 * @param nonRoot If false then this only works if the activity is the root
4984 * of a task; if true it will work for any activity in a task.
4985 * @return Returns true if the move completed, false if not.
4986 */
4987 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
4988 synchronized(this) {
4989 final long origId = Binder.clearCallingIdentity();
4990 int taskId = getTaskForActivityLocked(token, !nonRoot);
4991 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004992 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 }
4994 Binder.restoreCallingIdentity(origId);
4995 }
4996 return false;
4997 }
4998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 public void moveTaskBackwards(int task) {
5000 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5001 "moveTaskBackwards()");
5002
5003 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005004 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5005 Binder.getCallingUid(), "Task backwards")) {
5006 return;
5007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 final long origId = Binder.clearCallingIdentity();
5009 moveTaskBackwardsLocked(task);
5010 Binder.restoreCallingIdentity(origId);
5011 }
5012 }
5013
5014 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005015 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 }
5017
5018 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5019 synchronized(this) {
5020 return getTaskForActivityLocked(token, onlyRoot);
5021 }
5022 }
5023
5024 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005025 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 TaskRecord lastTask = null;
5027 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005028 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005029 if (r == token) {
5030 if (!onlyRoot || lastTask != r.task) {
5031 return r.task.taskId;
5032 }
5033 return -1;
5034 }
5035 lastTask = r.task;
5036 }
5037
5038 return -1;
5039 }
5040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 public void finishOtherInstances(IBinder token, ComponentName className) {
5042 synchronized(this) {
5043 final long origId = Binder.clearCallingIdentity();
5044
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005045 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 TaskRecord lastTask = null;
5047 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005048 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 if (r.realActivity.equals(className)
5050 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005051 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 null, "others")) {
5053 i--;
5054 N--;
5055 }
5056 }
5057 lastTask = r.task;
5058 }
5059
5060 Binder.restoreCallingIdentity(origId);
5061 }
5062 }
5063
5064 // =========================================================
5065 // THUMBNAILS
5066 // =========================================================
5067
5068 public void reportThumbnail(IBinder token,
5069 Bitmap thumbnail, CharSequence description) {
5070 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5071 final long origId = Binder.clearCallingIdentity();
5072 sendPendingThumbnail(null, token, thumbnail, description, true);
5073 Binder.restoreCallingIdentity(origId);
5074 }
5075
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005076 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 Bitmap thumbnail, CharSequence description, boolean always) {
5078 TaskRecord task = null;
5079 ArrayList receivers = null;
5080
5081 //System.out.println("Send pending thumbnail: " + r);
5082
5083 synchronized(this) {
5084 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005085 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005086 if (index < 0) {
5087 return;
5088 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005089 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 }
5091 if (thumbnail == null) {
5092 thumbnail = r.thumbnail;
5093 description = r.description;
5094 }
5095 if (thumbnail == null && !always) {
5096 // If there is no thumbnail, and this entry is not actually
5097 // going away, then abort for now and pick up the next
5098 // thumbnail we get.
5099 return;
5100 }
5101 task = r.task;
5102
5103 int N = mPendingThumbnails.size();
5104 int i=0;
5105 while (i<N) {
5106 PendingThumbnailsRecord pr =
5107 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5108 //System.out.println("Looking in " + pr.pendingRecords);
5109 if (pr.pendingRecords.remove(r)) {
5110 if (receivers == null) {
5111 receivers = new ArrayList();
5112 }
5113 receivers.add(pr);
5114 if (pr.pendingRecords.size() == 0) {
5115 pr.finished = true;
5116 mPendingThumbnails.remove(i);
5117 N--;
5118 continue;
5119 }
5120 }
5121 i++;
5122 }
5123 }
5124
5125 if (receivers != null) {
5126 final int N = receivers.size();
5127 for (int i=0; i<N; i++) {
5128 try {
5129 PendingThumbnailsRecord pr =
5130 (PendingThumbnailsRecord)receivers.get(i);
5131 pr.receiver.newThumbnail(
5132 task != null ? task.taskId : -1, thumbnail, description);
5133 if (pr.finished) {
5134 pr.receiver.finished();
5135 }
5136 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005137 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 }
5139 }
5140 }
5141 }
5142
5143 // =========================================================
5144 // CONTENT PROVIDERS
5145 // =========================================================
5146
5147 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5148 List providers = null;
5149 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005150 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005152 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 } catch (RemoteException ex) {
5154 }
5155 if (providers != null) {
5156 final int N = providers.size();
5157 for (int i=0; i<N; i++) {
5158 ProviderInfo cpi =
5159 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005160 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005161 if (cpr == null) {
5162 cpr = new ContentProviderRecord(cpi, app.info);
5163 mProvidersByClass.put(cpi.name, cpr);
5164 }
5165 app.pubProviders.put(cpi.name, cpr);
5166 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005167 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 }
5169 }
5170 return providers;
5171 }
5172
5173 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005174 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5176 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5177 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5178 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005179 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005180 return null;
5181 }
5182 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5183 cpi.exported ? -1 : cpi.applicationInfo.uid)
5184 == PackageManager.PERMISSION_GRANTED) {
5185 return null;
5186 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005187
5188 PathPermission[] pps = cpi.pathPermissions;
5189 if (pps != null) {
5190 int i = pps.length;
5191 while (i > 0) {
5192 i--;
5193 PathPermission pp = pps[i];
5194 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5195 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005196 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005197 return null;
5198 }
5199 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5200 cpi.exported ? -1 : cpi.applicationInfo.uid)
5201 == PackageManager.PERMISSION_GRANTED) {
5202 return null;
5203 }
5204 }
5205 }
5206
Dianne Hackbornb424b632010-08-18 15:59:05 -07005207 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5208 if (perms != null) {
5209 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5210 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5211 return null;
5212 }
5213 }
5214 }
5215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005216 String msg = "Permission Denial: opening provider " + cpi.name
5217 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5218 + ", uid=" + callingUid + ") requires "
5219 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005220 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221 return msg;
5222 }
5223
5224 private final ContentProviderHolder getContentProviderImpl(
5225 IApplicationThread caller, String name) {
5226 ContentProviderRecord cpr;
5227 ProviderInfo cpi = null;
5228
5229 synchronized(this) {
5230 ProcessRecord r = null;
5231 if (caller != null) {
5232 r = getRecordForAppLocked(caller);
5233 if (r == null) {
5234 throw new SecurityException(
5235 "Unable to find app for caller " + caller
5236 + " (pid=" + Binder.getCallingPid()
5237 + ") when getting content provider " + name);
5238 }
5239 }
5240
5241 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005242 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 if (cpr != null) {
5244 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005245 String msg;
5246 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5247 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 }
5249
5250 if (r != null && cpr.canRunHere(r)) {
5251 // This provider has been published or is in the process
5252 // of being published... but it is also allowed to run
5253 // in the caller's process, so don't make a connection
5254 // and just let the caller instantiate its own instance.
5255 if (cpr.provider != null) {
5256 // don't give caller the provider object, it needs
5257 // to make its own.
5258 cpr = new ContentProviderRecord(cpr);
5259 }
5260 return cpr;
5261 }
5262
5263 final long origId = Binder.clearCallingIdentity();
5264
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005265 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 // return it right away.
5267 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005268 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005269 "Adding provider requested by "
5270 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005271 + cpr.info.processName);
5272 Integer cnt = r.conProviders.get(cpr);
5273 if (cnt == null) {
5274 r.conProviders.put(cpr, new Integer(1));
5275 } else {
5276 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005279 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5280 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005281 // make sure to count it as being accessed and thus
5282 // back up on the LRU list. This is good because
5283 // content providers are often expensive to start.
5284 updateLruProcessLocked(cpr.app, false, true);
5285 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005286 } else {
5287 cpr.externals++;
5288 }
5289
5290 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005291 updateOomAdjLocked(cpr.app);
5292 }
5293
5294 Binder.restoreCallingIdentity(origId);
5295
5296 } else {
5297 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005298 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005299 resolveContentProvider(name,
5300 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 } catch (RemoteException ex) {
5302 }
5303 if (cpi == null) {
5304 return null;
5305 }
5306
Dianne Hackbornb424b632010-08-18 15:59:05 -07005307 String msg;
5308 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5309 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 }
5311
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005312 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005313 && !cpi.processName.equals("system")) {
5314 // If this content provider does not run in the system
5315 // process, and the system is not yet ready to run other
5316 // processes, then fail fast instead of hanging.
5317 throw new IllegalArgumentException(
5318 "Attempt to launch content provider before system ready");
5319 }
5320
Dianne Hackborn860755f2010-06-03 18:47:52 -07005321 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 final boolean firstClass = cpr == null;
5323 if (firstClass) {
5324 try {
5325 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005326 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 getApplicationInfo(
5328 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005329 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005331 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005332 + cpi.name);
5333 return null;
5334 }
5335 cpr = new ContentProviderRecord(cpi, ai);
5336 } catch (RemoteException ex) {
5337 // pm is in same process, this will never happen.
5338 }
5339 }
5340
5341 if (r != null && cpr.canRunHere(r)) {
5342 // If this is a multiprocess provider, then just return its
5343 // info and allow the caller to instantiate it. Only do
5344 // this if the provider is the same user as the caller's
5345 // process, or can run as root (so can be in any process).
5346 return cpr;
5347 }
5348
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005349 if (DEBUG_PROVIDER) {
5350 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005351 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005352 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 }
5354
5355 // This is single process, and our app is now connecting to it.
5356 // See if we are already in the process of launching this
5357 // provider.
5358 final int N = mLaunchingProviders.size();
5359 int i;
5360 for (i=0; i<N; i++) {
5361 if (mLaunchingProviders.get(i) == cpr) {
5362 break;
5363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 }
5365
5366 // If the provider is not already being launched, then get it
5367 // started.
5368 if (i >= N) {
5369 final long origId = Binder.clearCallingIdentity();
5370 ProcessRecord proc = startProcessLocked(cpi.processName,
5371 cpr.appInfo, false, 0, "content provider",
5372 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005373 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005374 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005375 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005376 + cpi.applicationInfo.packageName + "/"
5377 + cpi.applicationInfo.uid + " for provider "
5378 + name + ": process is bad");
5379 return null;
5380 }
5381 cpr.launchingApp = proc;
5382 mLaunchingProviders.add(cpr);
5383 Binder.restoreCallingIdentity(origId);
5384 }
5385
5386 // Make sure the provider is published (the same provider class
5387 // may be published under multiple names).
5388 if (firstClass) {
5389 mProvidersByClass.put(cpi.name, cpr);
5390 }
5391 mProvidersByName.put(name, cpr);
5392
5393 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005394 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005395 "Adding provider requested by "
5396 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005397 + cpr.info.processName);
5398 Integer cnt = r.conProviders.get(cpr);
5399 if (cnt == null) {
5400 r.conProviders.put(cpr, new Integer(1));
5401 } else {
5402 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 cpr.clients.add(r);
5405 } else {
5406 cpr.externals++;
5407 }
5408 }
5409 }
5410
5411 // Wait for the provider to be published...
5412 synchronized (cpr) {
5413 while (cpr.provider == null) {
5414 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005415 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 + cpi.applicationInfo.packageName + "/"
5417 + cpi.applicationInfo.uid + " for provider "
5418 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005419 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 cpi.applicationInfo.packageName,
5421 cpi.applicationInfo.uid, name);
5422 return null;
5423 }
5424 try {
5425 cpr.wait();
5426 } catch (InterruptedException ex) {
5427 }
5428 }
5429 }
5430 return cpr;
5431 }
5432
5433 public final ContentProviderHolder getContentProvider(
5434 IApplicationThread caller, String name) {
5435 if (caller == null) {
5436 String msg = "null IApplicationThread when getting content provider "
5437 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005438 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005439 throw new SecurityException(msg);
5440 }
5441
5442 return getContentProviderImpl(caller, name);
5443 }
5444
5445 private ContentProviderHolder getContentProviderExternal(String name) {
5446 return getContentProviderImpl(null, name);
5447 }
5448
5449 /**
5450 * Drop a content provider from a ProcessRecord's bookkeeping
5451 * @param cpr
5452 */
5453 public void removeContentProvider(IApplicationThread caller, String name) {
5454 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005455 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005456 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005457 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005458 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005459 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005460 return;
5461 }
5462 final ProcessRecord r = getRecordForAppLocked(caller);
5463 if (r == null) {
5464 throw new SecurityException(
5465 "Unable to find app for caller " + caller +
5466 " when removing content provider " + name);
5467 }
5468 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005469 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005470 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005471 + r.info.processName + " from process "
5472 + localCpr.appInfo.processName);
5473 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005475 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005476 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477 return;
5478 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005479 Integer cnt = r.conProviders.get(localCpr);
5480 if (cnt == null || cnt.intValue() <= 1) {
5481 localCpr.clients.remove(r);
5482 r.conProviders.remove(localCpr);
5483 } else {
5484 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005486 }
5487 updateOomAdjLocked();
5488 }
5489 }
5490
5491 private void removeContentProviderExternal(String name) {
5492 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005493 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 if(cpr == null) {
5495 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005496 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005497 return;
5498 }
5499
5500 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005501 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005502 localCpr.externals--;
5503 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005504 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005505 }
5506 updateOomAdjLocked();
5507 }
5508 }
5509
5510 public final void publishContentProviders(IApplicationThread caller,
5511 List<ContentProviderHolder> providers) {
5512 if (providers == null) {
5513 return;
5514 }
5515
5516 synchronized(this) {
5517 final ProcessRecord r = getRecordForAppLocked(caller);
5518 if (r == null) {
5519 throw new SecurityException(
5520 "Unable to find app for caller " + caller
5521 + " (pid=" + Binder.getCallingPid()
5522 + ") when publishing content providers");
5523 }
5524
5525 final long origId = Binder.clearCallingIdentity();
5526
5527 final int N = providers.size();
5528 for (int i=0; i<N; i++) {
5529 ContentProviderHolder src = providers.get(i);
5530 if (src == null || src.info == null || src.provider == null) {
5531 continue;
5532 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005533 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 if (dst != null) {
5535 mProvidersByClass.put(dst.info.name, dst);
5536 String names[] = dst.info.authority.split(";");
5537 for (int j = 0; j < names.length; j++) {
5538 mProvidersByName.put(names[j], dst);
5539 }
5540
5541 int NL = mLaunchingProviders.size();
5542 int j;
5543 for (j=0; j<NL; j++) {
5544 if (mLaunchingProviders.get(j) == dst) {
5545 mLaunchingProviders.remove(j);
5546 j--;
5547 NL--;
5548 }
5549 }
5550 synchronized (dst) {
5551 dst.provider = src.provider;
5552 dst.app = r;
5553 dst.notifyAll();
5554 }
5555 updateOomAdjLocked(r);
5556 }
5557 }
5558
5559 Binder.restoreCallingIdentity(origId);
5560 }
5561 }
5562
5563 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005564 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005565 synchronized (mSelf) {
5566 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5567 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005568 if (providers != null) {
5569 for (int i=providers.size()-1; i>=0; i--) {
5570 ProviderInfo pi = (ProviderInfo)providers.get(i);
5571 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5572 Slog.w(TAG, "Not installing system proc provider " + pi.name
5573 + ": not system .apk");
5574 providers.remove(i);
5575 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005576 }
5577 }
5578 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005579 if (providers != null) {
5580 mSystemThread.installSystemProviders(providers);
5581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005582 }
5583
5584 // =========================================================
5585 // GLOBAL MANAGEMENT
5586 // =========================================================
5587
5588 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5589 ApplicationInfo info, String customProcess) {
5590 String proc = customProcess != null ? customProcess : info.processName;
5591 BatteryStatsImpl.Uid.Proc ps = null;
5592 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5593 synchronized (stats) {
5594 ps = stats.getProcessStatsLocked(info.uid, proc);
5595 }
5596 return new ProcessRecord(ps, thread, info, proc);
5597 }
5598
5599 final ProcessRecord addAppLocked(ApplicationInfo info) {
5600 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5601
5602 if (app == null) {
5603 app = newProcessRecordLocked(null, info, null);
5604 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005605 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005606 }
5607
5608 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5609 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5610 app.persistent = true;
5611 app.maxAdj = CORE_SERVER_ADJ;
5612 }
5613 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5614 mPersistentStartingProcesses.add(app);
5615 startProcessLocked(app, "added application", app.processName);
5616 }
5617
5618 return app;
5619 }
5620
5621 public void unhandledBack() {
5622 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5623 "unhandledBack()");
5624
5625 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005626 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005627 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628 TAG, "Performing unhandledBack(): stack size = " + count);
5629 if (count > 1) {
5630 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005631 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5633 Binder.restoreCallingIdentity(origId);
5634 }
5635 }
5636 }
5637
5638 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5639 String name = uri.getAuthority();
5640 ContentProviderHolder cph = getContentProviderExternal(name);
5641 ParcelFileDescriptor pfd = null;
5642 if (cph != null) {
5643 // We record the binder invoker's uid in thread-local storage before
5644 // going to the content provider to open the file. Later, in the code
5645 // that handles all permissions checks, we look for this uid and use
5646 // that rather than the Activity Manager's own uid. The effect is that
5647 // we do the check against the caller's permissions even though it looks
5648 // to the content provider like the Activity Manager itself is making
5649 // the request.
5650 sCallerIdentity.set(new Identity(
5651 Binder.getCallingPid(), Binder.getCallingUid()));
5652 try {
5653 pfd = cph.provider.openFile(uri, "r");
5654 } catch (FileNotFoundException e) {
5655 // do nothing; pfd will be returned null
5656 } finally {
5657 // Ensure that whatever happens, we clean up the identity state
5658 sCallerIdentity.remove();
5659 }
5660
5661 // We've got the fd now, so we're done with the provider.
5662 removeContentProviderExternal(name);
5663 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005664 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 }
5666 return pfd;
5667 }
5668
5669 public void goingToSleep() {
5670 synchronized(this) {
5671 mSleeping = true;
5672 mWindowManager.setEventDispatching(false);
5673
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005674 if (mMainStack.mResumedActivity != null) {
5675 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005677 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005679
5680 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005681 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005682 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5683 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005684 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 }
5686 }
5687
Dianne Hackborn55280a92009-05-07 15:53:46 -07005688 public boolean shutdown(int timeout) {
5689 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5690 != PackageManager.PERMISSION_GRANTED) {
5691 throw new SecurityException("Requires permission "
5692 + android.Manifest.permission.SHUTDOWN);
5693 }
5694
5695 boolean timedout = false;
5696
5697 synchronized(this) {
5698 mShuttingDown = true;
5699 mWindowManager.setEventDispatching(false);
5700
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005701 if (mMainStack.mResumedActivity != null) {
5702 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005703 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005704 while (mMainStack.mResumedActivity != null
5705 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005706 long delay = endTime - System.currentTimeMillis();
5707 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005708 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005709 timedout = true;
5710 break;
5711 }
5712 try {
5713 this.wait();
5714 } catch (InterruptedException e) {
5715 }
5716 }
5717 }
5718 }
5719
5720 mUsageStatsService.shutdown();
5721 mBatteryStatsService.shutdown();
5722
5723 return timedout;
5724 }
5725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 public void wakingUp() {
5727 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005728 if (mMainStack.mGoingToSleep.isHeld()) {
5729 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 }
5731 mWindowManager.setEventDispatching(true);
5732 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005733 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005734 }
5735 }
5736
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005737 public void stopAppSwitches() {
5738 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5739 != PackageManager.PERMISSION_GRANTED) {
5740 throw new SecurityException("Requires permission "
5741 + android.Manifest.permission.STOP_APP_SWITCHES);
5742 }
5743
5744 synchronized(this) {
5745 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5746 + APP_SWITCH_DELAY_TIME;
5747 mDidAppSwitch = false;
5748 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5749 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5750 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5751 }
5752 }
5753
5754 public void resumeAppSwitches() {
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 // Note that we don't execute any pending app switches... we will
5763 // let those wait until either the timeout, or the next start
5764 // activity request.
5765 mAppSwitchesAllowedTime = 0;
5766 }
5767 }
5768
5769 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5770 String name) {
5771 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5772 return true;
5773 }
5774
5775 final int perm = checkComponentPermission(
5776 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5777 callingUid, -1);
5778 if (perm == PackageManager.PERMISSION_GRANTED) {
5779 return true;
5780 }
5781
Joe Onorato8a9b2202010-02-26 18:56:32 -08005782 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005783 return false;
5784 }
5785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 public void setDebugApp(String packageName, boolean waitForDebugger,
5787 boolean persistent) {
5788 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5789 "setDebugApp()");
5790
5791 // Note that this is not really thread safe if there are multiple
5792 // callers into it at the same time, but that's not a situation we
5793 // care about.
5794 if (persistent) {
5795 final ContentResolver resolver = mContext.getContentResolver();
5796 Settings.System.putString(
5797 resolver, Settings.System.DEBUG_APP,
5798 packageName);
5799 Settings.System.putInt(
5800 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5801 waitForDebugger ? 1 : 0);
5802 }
5803
5804 synchronized (this) {
5805 if (!persistent) {
5806 mOrigDebugApp = mDebugApp;
5807 mOrigWaitForDebugger = mWaitForDebugger;
5808 }
5809 mDebugApp = packageName;
5810 mWaitForDebugger = waitForDebugger;
5811 mDebugTransient = !persistent;
5812 if (packageName != null) {
5813 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005814 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 Binder.restoreCallingIdentity(origId);
5816 }
5817 }
5818 }
5819
5820 public void setAlwaysFinish(boolean enabled) {
5821 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5822 "setAlwaysFinish()");
5823
5824 Settings.System.putInt(
5825 mContext.getContentResolver(),
5826 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5827
5828 synchronized (this) {
5829 mAlwaysFinishActivities = enabled;
5830 }
5831 }
5832
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005833 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005834 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005835 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005836 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005837 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005838 }
5839 }
5840
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005841 public boolean isUserAMonkey() {
5842 // For now the fact that there is a controller implies
5843 // we have a monkey.
5844 synchronized (this) {
5845 return mController != null;
5846 }
5847 }
5848
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005849 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005850 synchronized (this) {
5851 mWatchers.register(watcher);
5852 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005853 }
5854
5855 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005856 synchronized (this) {
5857 mWatchers.unregister(watcher);
5858 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005859 }
5860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005861 public final void enterSafeMode() {
5862 synchronized(this) {
5863 // It only makes sense to do this before the system is ready
5864 // and started launching other packages.
5865 if (!mSystemReady) {
5866 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005867 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 } catch (RemoteException e) {
5869 }
5870
5871 View v = LayoutInflater.from(mContext).inflate(
5872 com.android.internal.R.layout.safe_mode, null);
5873 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5874 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5875 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5876 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5877 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5878 lp.format = v.getBackground().getOpacity();
5879 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5880 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5881 ((WindowManager)mContext.getSystemService(
5882 Context.WINDOW_SERVICE)).addView(v, lp);
5883 }
5884 }
5885 }
5886
5887 public void noteWakeupAlarm(IIntentSender sender) {
5888 if (!(sender instanceof PendingIntentRecord)) {
5889 return;
5890 }
5891 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5892 synchronized (stats) {
5893 if (mBatteryStatsService.isOnBattery()) {
5894 mBatteryStatsService.enforceCallingPermission();
5895 PendingIntentRecord rec = (PendingIntentRecord)sender;
5896 int MY_UID = Binder.getCallingUid();
5897 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5898 BatteryStatsImpl.Uid.Pkg pkg =
5899 stats.getPackageStatsLocked(uid, rec.key.packageName);
5900 pkg.incWakeupsLocked();
5901 }
5902 }
5903 }
5904
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005905 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005906 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005907 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005908 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005909 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005910 // XXX Note: don't acquire main activity lock here, because the window
5911 // manager calls in with its locks held.
5912
5913 boolean killed = false;
5914 synchronized (mPidsSelfLocked) {
5915 int[] types = new int[pids.length];
5916 int worstType = 0;
5917 for (int i=0; i<pids.length; i++) {
5918 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5919 if (proc != null) {
5920 int type = proc.setAdj;
5921 types[i] = type;
5922 if (type > worstType) {
5923 worstType = type;
5924 }
5925 }
5926 }
5927
5928 // If the worse oom_adj is somewhere in the hidden proc LRU range,
5929 // then constrain it so we will kill all hidden procs.
5930 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
5931 worstType = HIDDEN_APP_MIN_ADJ;
5932 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005933 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934 for (int i=0; i<pids.length; i++) {
5935 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
5936 if (proc == null) {
5937 continue;
5938 }
5939 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005940 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07005941 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005942 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
5943 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005944 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07005945 proc.killedBackground = true;
5946 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 }
5948 }
5949 }
5950 return killed;
5951 }
5952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005953 public final void startRunning(String pkg, String cls, String action,
5954 String data) {
5955 synchronized(this) {
5956 if (mStartRunning) {
5957 return;
5958 }
5959 mStartRunning = true;
5960 mTopComponent = pkg != null && cls != null
5961 ? new ComponentName(pkg, cls) : null;
5962 mTopAction = action != null ? action : Intent.ACTION_MAIN;
5963 mTopData = data;
5964 if (!mSystemReady) {
5965 return;
5966 }
5967 }
5968
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07005969 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 }
5971
5972 private void retrieveSettings() {
5973 final ContentResolver resolver = mContext.getContentResolver();
5974 String debugApp = Settings.System.getString(
5975 resolver, Settings.System.DEBUG_APP);
5976 boolean waitForDebugger = Settings.System.getInt(
5977 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
5978 boolean alwaysFinishActivities = Settings.System.getInt(
5979 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
5980
5981 Configuration configuration = new Configuration();
5982 Settings.System.getConfiguration(resolver, configuration);
5983
5984 synchronized (this) {
5985 mDebugApp = mOrigDebugApp = debugApp;
5986 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
5987 mAlwaysFinishActivities = alwaysFinishActivities;
5988 // This happens before any activities are started, so we can
5989 // change mConfiguration in-place.
5990 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08005991 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005992 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005993 }
5994 }
5995
5996 public boolean testIsSystemReady() {
5997 // no need to synchronize(this) just to read & return the value
5998 return mSystemReady;
5999 }
6000
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006001 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006002 // In the simulator, startRunning will never have been called, which
6003 // normally sets a few crucial variables. Do it here instead.
6004 if (!Process.supportsProcesses()) {
6005 mStartRunning = true;
6006 mTopAction = Intent.ACTION_MAIN;
6007 }
6008
6009 synchronized(this) {
6010 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006011 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 return;
6013 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006014
6015 // Check to see if there are any update receivers to run.
6016 if (!mDidUpdate) {
6017 if (mWaitingUpdate) {
6018 return;
6019 }
6020 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6021 List<ResolveInfo> ris = null;
6022 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006023 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006024 intent, null, 0);
6025 } catch (RemoteException e) {
6026 }
6027 if (ris != null) {
6028 for (int i=ris.size()-1; i>=0; i--) {
6029 if ((ris.get(i).activityInfo.applicationInfo.flags
6030 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6031 ris.remove(i);
6032 }
6033 }
6034 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
6035 for (int i=0; i<ris.size(); i++) {
6036 ActivityInfo ai = ris.get(i).activityInfo;
6037 intent.setComponent(new ComponentName(ai.packageName, ai.name));
6038 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006039 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006040 finisher = new IIntentReceiver.Stub() {
6041 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006042 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006043 boolean sticky) {
6044 // The raw IIntentReceiver interface is called
6045 // with the AM lock held, so redispatch to
6046 // execute our code without the lock.
6047 mHandler.post(new Runnable() {
6048 public void run() {
6049 synchronized (ActivityManagerService.this) {
6050 mDidUpdate = true;
6051 }
6052 systemReady(goingCallback);
6053 }
6054 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006055 }
6056 };
6057 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006058 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006059 broadcastIntentLocked(null, null, intent, null, finisher,
6060 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006061 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006062 mWaitingUpdate = true;
6063 }
6064 }
6065 }
6066 if (mWaitingUpdate) {
6067 return;
6068 }
6069 mDidUpdate = true;
6070 }
6071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006072 mSystemReady = true;
6073 if (!mStartRunning) {
6074 return;
6075 }
6076 }
6077
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006078 ArrayList<ProcessRecord> procsToKill = null;
6079 synchronized(mPidsSelfLocked) {
6080 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6081 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6082 if (!isAllowedWhileBooting(proc.info)){
6083 if (procsToKill == null) {
6084 procsToKill = new ArrayList<ProcessRecord>();
6085 }
6086 procsToKill.add(proc);
6087 }
6088 }
6089 }
6090
6091 if (procsToKill != null) {
6092 synchronized(this) {
6093 for (int i=procsToKill.size()-1; i>=0; i--) {
6094 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006095 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006096 removeProcessLocked(proc, true);
6097 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07006098
6099 // Now that we have cleaned up any update processes, we
6100 // are ready to start launching real processes and know that
6101 // we won't trample on them any more.
6102 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006103 }
6104 }
6105
Joe Onorato8a9b2202010-02-26 18:56:32 -08006106 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006107 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006108 SystemClock.uptimeMillis());
6109
6110 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006111 // Make sure we have no pre-ready processes sitting around.
6112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006113 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6114 ResolveInfo ri = mContext.getPackageManager()
6115 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006116 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006117 CharSequence errorMsg = null;
6118 if (ri != null) {
6119 ActivityInfo ai = ri.activityInfo;
6120 ApplicationInfo app = ai.applicationInfo;
6121 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6122 mTopAction = Intent.ACTION_FACTORY_TEST;
6123 mTopData = null;
6124 mTopComponent = new ComponentName(app.packageName,
6125 ai.name);
6126 } else {
6127 errorMsg = mContext.getResources().getText(
6128 com.android.internal.R.string.factorytest_not_system);
6129 }
6130 } else {
6131 errorMsg = mContext.getResources().getText(
6132 com.android.internal.R.string.factorytest_no_action);
6133 }
6134 if (errorMsg != null) {
6135 mTopAction = null;
6136 mTopData = null;
6137 mTopComponent = null;
6138 Message msg = Message.obtain();
6139 msg.what = SHOW_FACTORY_ERROR_MSG;
6140 msg.getData().putCharSequence("msg", errorMsg);
6141 mHandler.sendMessage(msg);
6142 }
6143 }
6144 }
6145
6146 retrieveSettings();
6147
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006148 if (goingCallback != null) goingCallback.run();
6149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006150 synchronized (this) {
6151 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6152 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006153 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006154 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006155 if (apps != null) {
6156 int N = apps.size();
6157 int i;
6158 for (i=0; i<N; i++) {
6159 ApplicationInfo info
6160 = (ApplicationInfo)apps.get(i);
6161 if (info != null &&
6162 !info.packageName.equals("android")) {
6163 addAppLocked(info);
6164 }
6165 }
6166 }
6167 } catch (RemoteException ex) {
6168 // pm is in same process, this will never happen.
6169 }
6170 }
6171
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006172 // Start up initial activity.
6173 mBooting = true;
6174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006175 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006176 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006177 Message msg = Message.obtain();
6178 msg.what = SHOW_UID_ERROR_MSG;
6179 mHandler.sendMessage(msg);
6180 }
6181 } catch (RemoteException e) {
6182 }
6183
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006184 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006185 }
6186 }
6187
Dan Egnorb7f03672009-12-09 16:22:32 -08006188 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006189 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006190 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006191 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006192 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006193 startAppProblemLocked(app);
6194 app.stopFreezingAllLocked();
6195 return handleAppCrashLocked(app);
6196 }
6197
Dan Egnorb7f03672009-12-09 16:22:32 -08006198 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006199 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006200 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006201 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006202 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6203 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006204 startAppProblemLocked(app);
6205 app.stopFreezingAllLocked();
6206 }
6207
6208 /**
6209 * Generate a process error record, suitable for attachment to a ProcessRecord.
6210 *
6211 * @param app The ProcessRecord in which the error occurred.
6212 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6213 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006214 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 * @param shortMsg Short message describing the crash.
6216 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006217 * @param stackTrace Full crash stack trace, may be null.
6218 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 * @return Returns a fully-formed AppErrorStateInfo record.
6220 */
6221 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006222 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006223 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006225 report.condition = condition;
6226 report.processName = app.processName;
6227 report.pid = app.pid;
6228 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006229 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 report.shortMsg = shortMsg;
6231 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006232 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006233
6234 return report;
6235 }
6236
Dan Egnor42471dd2010-01-07 17:25:22 -08006237 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006238 synchronized (this) {
6239 app.crashing = false;
6240 app.crashingReport = null;
6241 app.notResponding = false;
6242 app.notRespondingReport = null;
6243 if (app.anrDialog == fromDialog) {
6244 app.anrDialog = null;
6245 }
6246 if (app.waitDialog == fromDialog) {
6247 app.waitDialog = null;
6248 }
6249 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006250 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006251 Slog.i(ActivityManagerService.TAG, "Killing "
6252 + app.processName + " (pid=" + app.pid + "): user's request");
6253 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6254 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006255 Process.killProcess(app.pid);
6256 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006257 }
6258 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006259
Dan Egnorb7f03672009-12-09 16:22:32 -08006260 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006261 long now = SystemClock.uptimeMillis();
6262
6263 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6264 app.info.uid);
6265 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6266 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006267 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006268 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006269 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006270 app.info.processName, app.info.uid);
6271 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006272 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6273 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006275 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006276 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006277 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006278 }
6279 }
6280 if (!app.persistent) {
6281 // We don't want to start this process again until the user
6282 // explicitly does so... but for persistent process, we really
6283 // need to keep it running. If a persistent process is actually
6284 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006285 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006286 app.info.processName);
6287 mBadProcesses.put(app.info.processName, app.info.uid, now);
6288 app.bad = true;
6289 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6290 app.removed = true;
6291 removeProcessLocked(app, false);
6292 return false;
6293 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006294 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006295 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006296 if (r.app == app) {
6297 // If the top running activity is from this crashing
6298 // process, then terminate it to avoid getting in a loop.
6299 Slog.w(TAG, " Force finishing activity "
6300 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006301 int index = mMainStack.indexOfTokenLocked(r);
6302 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006303 Activity.RESULT_CANCELED, null, "crashed");
6304 // Also terminate an activities below it that aren't yet
6305 // stopped, to avoid a situation where one will get
6306 // re-start our crashing activity once it gets resumed again.
6307 index--;
6308 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006309 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006310 if (r.state == ActivityState.RESUMED
6311 || r.state == ActivityState.PAUSING
6312 || r.state == ActivityState.PAUSED) {
6313 if (!r.isHomeActivity) {
6314 Slog.w(TAG, " Force finishing activity "
6315 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006316 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006317 Activity.RESULT_CANCELED, null, "crashed");
6318 }
6319 }
6320 }
6321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 }
6323
6324 // Bump up the crash count of any services currently running in the proc.
6325 if (app.services.size() != 0) {
6326 // Any services running in the application need to be placed
6327 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006328 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006330 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 sr.crashCount++;
6332 }
6333 }
6334
6335 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6336 return true;
6337 }
6338
6339 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006340 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6341 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 skipCurrentReceiverLocked(app);
6343 }
6344
6345 void skipCurrentReceiverLocked(ProcessRecord app) {
6346 boolean reschedule = false;
6347 BroadcastRecord r = app.curReceiver;
6348 if (r != null) {
6349 // The current broadcast is waiting for this app's receiver
6350 // to be finished. Looks like that's not going to happen, so
6351 // let the broadcast continue.
6352 logBroadcastReceiverDiscard(r);
6353 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6354 r.resultExtras, r.resultAbort, true);
6355 reschedule = true;
6356 }
6357 r = mPendingBroadcast;
6358 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006359 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006360 "skip & discard pending app " + r);
6361 logBroadcastReceiverDiscard(r);
6362 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6363 r.resultExtras, r.resultAbort, true);
6364 reschedule = true;
6365 }
6366 if (reschedule) {
6367 scheduleBroadcastsLocked();
6368 }
6369 }
6370
Dan Egnor60d87622009-12-16 16:32:58 -08006371 /**
6372 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6373 * The application process will exit immediately after this call returns.
6374 * @param app object of the crashing app, null for the system server
6375 * @param crashInfo describing the exception
6376 */
6377 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6378 ProcessRecord r = findAppProcess(app);
6379
6380 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6381 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006382 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006383 crashInfo.exceptionClassName,
6384 crashInfo.exceptionMessage,
6385 crashInfo.throwFileName,
6386 crashInfo.throwLineNumber);
6387
Dan Egnor42471dd2010-01-07 17:25:22 -08006388 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006389
6390 crashApplication(r, crashInfo);
6391 }
6392
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006393 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006394 IBinder app,
6395 int violationMask,
6396 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006397 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006398
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006399 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006400 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006401 boolean logIt = true;
6402 synchronized (mAlreadyLoggedViolatedStacks) {
6403 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6404 logIt = false;
6405 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006406 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006407 // the relative pain numbers, without logging all
6408 // the stack traces repeatedly. We'd want to do
6409 // likewise in the client code, which also does
6410 // dup suppression, before the Binder call.
6411 } else {
6412 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6413 mAlreadyLoggedViolatedStacks.clear();
6414 }
6415 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6416 }
6417 }
6418 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006419 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006420 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006421 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006422
6423 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6424 AppErrorResult result = new AppErrorResult();
6425 synchronized (this) {
6426 final long origId = Binder.clearCallingIdentity();
6427
6428 Message msg = Message.obtain();
6429 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6430 HashMap<String, Object> data = new HashMap<String, Object>();
6431 data.put("result", result);
6432 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006433 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006434 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006435 msg.obj = data;
6436 mHandler.sendMessage(msg);
6437
6438 Binder.restoreCallingIdentity(origId);
6439 }
6440 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006441 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006442 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006443 }
6444
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006445 // Depending on the policy in effect, there could be a bunch of
6446 // these in quick succession so we try to batch these together to
6447 // minimize disk writes, number of dropbox entries, and maximize
6448 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006449 private void logStrictModeViolationToDropBox(
6450 ProcessRecord process,
6451 StrictMode.ViolationInfo info) {
6452 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006453 return;
6454 }
6455 final boolean isSystemApp = process == null ||
6456 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6457 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6458 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6459 final DropBoxManager dbox = (DropBoxManager)
6460 mContext.getSystemService(Context.DROPBOX_SERVICE);
6461
6462 // Exit early if the dropbox isn't configured to accept this report type.
6463 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6464
6465 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006466 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006467 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6468 synchronized (sb) {
6469 bufferWasEmpty = sb.length() == 0;
6470 appendDropBoxProcessHeaders(process, sb);
6471 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6472 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006473 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6474 if (info.violationNumThisLoop != 0) {
6475 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6476 }
6477 if (info != null && info.durationMillis != -1) {
6478 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006479 }
6480 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006481 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6482 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006483 }
6484 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006485
6486 // Only buffer up to ~64k. Various logging bits truncate
6487 // things at 128k.
6488 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006489 }
6490
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006491 // Flush immediately if the buffer's grown too large, or this
6492 // is a non-system app. Non-system apps are isolated with a
6493 // different tag & policy and not batched.
6494 //
6495 // Batching is useful during internal testing with
6496 // StrictMode settings turned up high. Without batching,
6497 // thousands of separate files could be created on boot.
6498 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006499 new Thread("Error dump: " + dropboxTag) {
6500 @Override
6501 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006502 String report;
6503 synchronized (sb) {
6504 report = sb.toString();
6505 sb.delete(0, sb.length());
6506 sb.trimToSize();
6507 }
6508 if (report.length() != 0) {
6509 dbox.addText(dropboxTag, report);
6510 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006511 }
6512 }.start();
6513 return;
6514 }
6515
6516 // System app batching:
6517 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006518 // An existing dropbox-writing thread is outstanding, so
6519 // we don't need to start it up. The existing thread will
6520 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006521 return;
6522 }
6523
6524 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6525 // (After this point, we shouldn't access AMS internal data structures.)
6526 new Thread("Error dump: " + dropboxTag) {
6527 @Override
6528 public void run() {
6529 // 5 second sleep to let stacks arrive and be batched together
6530 try {
6531 Thread.sleep(5000); // 5 seconds
6532 } catch (InterruptedException e) {}
6533
6534 String errorReport;
6535 synchronized (mStrictModeBuffer) {
6536 errorReport = mStrictModeBuffer.toString();
6537 if (errorReport.length() == 0) {
6538 return;
6539 }
6540 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6541 mStrictModeBuffer.trimToSize();
6542 }
6543 dbox.addText(dropboxTag, errorReport);
6544 }
6545 }.start();
6546 }
6547
Dan Egnor60d87622009-12-16 16:32:58 -08006548 /**
6549 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6550 * @param app object of the crashing app, null for the system server
6551 * @param tag reported by the caller
6552 * @param crashInfo describing the context of the error
6553 * @return true if the process should exit immediately (WTF is fatal)
6554 */
6555 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006556 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006557 ProcessRecord r = findAppProcess(app);
6558
6559 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6560 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006561 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006562 tag, crashInfo.exceptionMessage);
6563
Dan Egnor42471dd2010-01-07 17:25:22 -08006564 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006565
Doug Zongker43866e02010-01-07 12:09:54 -08006566 if (Settings.Secure.getInt(mContext.getContentResolver(),
6567 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006568 crashApplication(r, crashInfo);
6569 return true;
6570 } else {
6571 return false;
6572 }
6573 }
6574
6575 /**
6576 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6577 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6578 */
6579 private ProcessRecord findAppProcess(IBinder app) {
6580 if (app == null) {
6581 return null;
6582 }
6583
6584 synchronized (this) {
6585 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6586 final int NA = apps.size();
6587 for (int ia=0; ia<NA; ia++) {
6588 ProcessRecord p = apps.valueAt(ia);
6589 if (p.thread != null && p.thread.asBinder() == app) {
6590 return p;
6591 }
6592 }
6593 }
6594
Joe Onorato8a9b2202010-02-26 18:56:32 -08006595 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006596 return null;
6597 }
6598 }
6599
6600 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006601 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6602 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006603 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006604 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6605 // Note: ProcessRecord 'process' is guarded by the service
6606 // instance. (notably process.pkgList, which could otherwise change
6607 // concurrently during execution of this method)
6608 synchronized (this) {
6609 if (process == null || process.pid == MY_PID) {
6610 sb.append("Process: system_server\n");
6611 } else {
6612 sb.append("Process: ").append(process.processName).append("\n");
6613 }
6614 if (process == null) {
6615 return;
6616 }
Dan Egnora455d192010-03-12 08:52:28 -08006617 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006618 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006619 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6620 for (String pkg : process.pkgList) {
6621 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006622 try {
Dan Egnora455d192010-03-12 08:52:28 -08006623 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6624 if (pi != null) {
6625 sb.append(" v").append(pi.versionCode);
6626 if (pi.versionName != null) {
6627 sb.append(" (").append(pi.versionName).append(")");
6628 }
6629 }
6630 } catch (RemoteException e) {
6631 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006632 }
Dan Egnora455d192010-03-12 08:52:28 -08006633 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006634 }
Dan Egnora455d192010-03-12 08:52:28 -08006635 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006636 }
6637
6638 private static String processClass(ProcessRecord process) {
6639 if (process == null || process.pid == MY_PID) {
6640 return "system_server";
6641 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6642 return "system_app";
6643 } else {
6644 return "data_app";
6645 }
6646 }
6647
6648 /**
6649 * Write a description of an error (crash, WTF, ANR) to the drop box.
6650 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6651 * @param process which caused the error, null means the system server
6652 * @param activity which triggered the error, null if unknown
6653 * @param parent activity related to the error, null if unknown
6654 * @param subject line related to the error, null if absent
6655 * @param report in long form describing the error, null if absent
6656 * @param logFile to include in the report, null if none
6657 * @param crashInfo giving an application stack trace, null if absent
6658 */
6659 public void addErrorToDropBox(String eventType,
6660 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6661 final String report, final File logFile,
6662 final ApplicationErrorReport.CrashInfo crashInfo) {
6663 // NOTE -- this must never acquire the ActivityManagerService lock,
6664 // otherwise the watchdog may be prevented from resetting the system.
6665
6666 final String dropboxTag = processClass(process) + "_" + eventType;
6667 final DropBoxManager dbox = (DropBoxManager)
6668 mContext.getSystemService(Context.DROPBOX_SERVICE);
6669
6670 // Exit early if the dropbox isn't configured to accept this report type.
6671 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6672
6673 final StringBuilder sb = new StringBuilder(1024);
6674 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006675 if (activity != null) {
6676 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6677 }
6678 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6679 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6680 }
6681 if (parent != null && parent != activity) {
6682 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6683 }
6684 if (subject != null) {
6685 sb.append("Subject: ").append(subject).append("\n");
6686 }
6687 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6688 sb.append("\n");
6689
6690 // Do the rest in a worker thread to avoid blocking the caller on I/O
6691 // (After this point, we shouldn't access AMS internal data structures.)
6692 Thread worker = new Thread("Error dump: " + dropboxTag) {
6693 @Override
6694 public void run() {
6695 if (report != null) {
6696 sb.append(report);
6697 }
6698 if (logFile != null) {
6699 try {
6700 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6701 } catch (IOException e) {
6702 Slog.e(TAG, "Error reading " + logFile, e);
6703 }
6704 }
6705 if (crashInfo != null && crashInfo.stackTrace != null) {
6706 sb.append(crashInfo.stackTrace);
6707 }
6708
6709 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6710 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6711 if (lines > 0) {
6712 sb.append("\n");
6713
6714 // Merge several logcat streams, and take the last N lines
6715 InputStreamReader input = null;
6716 try {
6717 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6718 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6719 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6720
6721 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6722 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6723 input = new InputStreamReader(logcat.getInputStream());
6724
6725 int num;
6726 char[] buf = new char[8192];
6727 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6728 } catch (IOException e) {
6729 Slog.e(TAG, "Error running logcat", e);
6730 } finally {
6731 if (input != null) try { input.close(); } catch (IOException e) {}
6732 }
6733 }
6734
6735 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006736 }
Dan Egnora455d192010-03-12 08:52:28 -08006737 };
6738
6739 if (process == null || process.pid == MY_PID) {
6740 worker.run(); // We may be about to die -- need to run this synchronously
6741 } else {
6742 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006743 }
6744 }
6745
6746 /**
6747 * Bring up the "unexpected error" dialog box for a crashing app.
6748 * Deal with edge cases (intercepts from instrumented applications,
6749 * ActivityController, error intent receivers, that sort of thing).
6750 * @param r the application crashing
6751 * @param crashInfo describing the failure
6752 */
6753 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006754 long timeMillis = System.currentTimeMillis();
6755 String shortMsg = crashInfo.exceptionClassName;
6756 String longMsg = crashInfo.exceptionMessage;
6757 String stackTrace = crashInfo.stackTrace;
6758 if (shortMsg != null && longMsg != null) {
6759 longMsg = shortMsg + ": " + longMsg;
6760 } else if (shortMsg != null) {
6761 longMsg = shortMsg;
6762 }
6763
Dan Egnor60d87622009-12-16 16:32:58 -08006764 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006765 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006766 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006767 try {
6768 String name = r != null ? r.processName : null;
6769 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006770 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006771 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006772 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006773 + " at watcher's request");
6774 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006775 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 }
6777 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006778 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006779 }
6780 }
6781
6782 final long origId = Binder.clearCallingIdentity();
6783
6784 // If this process is running instrumentation, finish it.
6785 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006786 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006787 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006788 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6789 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006790 Bundle info = new Bundle();
6791 info.putString("shortMsg", shortMsg);
6792 info.putString("longMsg", longMsg);
6793 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6794 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006795 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006796 }
6797
Dan Egnor60d87622009-12-16 16:32:58 -08006798 // If we can't identify the process or it's already exceeded its crash quota,
6799 // quit right away without showing a crash dialog.
6800 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006802 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006803 }
6804
6805 Message msg = Message.obtain();
6806 msg.what = SHOW_ERROR_MSG;
6807 HashMap data = new HashMap();
6808 data.put("result", result);
6809 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006810 msg.obj = data;
6811 mHandler.sendMessage(msg);
6812
6813 Binder.restoreCallingIdentity(origId);
6814 }
6815
6816 int res = result.get();
6817
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006818 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006819 synchronized (this) {
6820 if (r != null) {
6821 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6822 SystemClock.uptimeMillis());
6823 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006824 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006825 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006826 }
6827 }
6828
6829 if (appErrorIntent != null) {
6830 try {
6831 mContext.startActivity(appErrorIntent);
6832 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006833 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006836 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006837
6838 Intent createAppErrorIntentLocked(ProcessRecord r,
6839 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6840 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006841 if (report == null) {
6842 return null;
6843 }
6844 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6845 result.setComponent(r.errorReportReceiver);
6846 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6847 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6848 return result;
6849 }
6850
Dan Egnorb7f03672009-12-09 16:22:32 -08006851 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6852 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006853 if (r.errorReportReceiver == null) {
6854 return null;
6855 }
6856
6857 if (!r.crashing && !r.notResponding) {
6858 return null;
6859 }
6860
Dan Egnorb7f03672009-12-09 16:22:32 -08006861 ApplicationErrorReport report = new ApplicationErrorReport();
6862 report.packageName = r.info.packageName;
6863 report.installerPackageName = r.errorReportReceiver.getPackageName();
6864 report.processName = r.processName;
6865 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006866 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006867
Dan Egnorb7f03672009-12-09 16:22:32 -08006868 if (r.crashing) {
6869 report.type = ApplicationErrorReport.TYPE_CRASH;
6870 report.crashInfo = crashInfo;
6871 } else if (r.notResponding) {
6872 report.type = ApplicationErrorReport.TYPE_ANR;
6873 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006874
Dan Egnorb7f03672009-12-09 16:22:32 -08006875 report.anrInfo.activity = r.notRespondingReport.tag;
6876 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6877 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006878 }
6879
Dan Egnorb7f03672009-12-09 16:22:32 -08006880 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006881 }
6882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006883 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6884 // assume our apps are happy - lazy create the list
6885 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6886
6887 synchronized (this) {
6888
6889 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006890 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6891 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006892 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6893 // This one's in trouble, so we'll generate a report for it
6894 // crashes are higher priority (in case there's a crash *and* an anr)
6895 ActivityManager.ProcessErrorStateInfo report = null;
6896 if (app.crashing) {
6897 report = app.crashingReport;
6898 } else if (app.notResponding) {
6899 report = app.notRespondingReport;
6900 }
6901
6902 if (report != null) {
6903 if (errList == null) {
6904 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6905 }
6906 errList.add(report);
6907 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006908 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006909 " crashing = " + app.crashing +
6910 " notResponding = " + app.notResponding);
6911 }
6912 }
6913 }
6914 }
6915
6916 return errList;
6917 }
6918
6919 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
6920 // Lazy instantiation of list
6921 List<ActivityManager.RunningAppProcessInfo> runList = null;
6922 synchronized (this) {
6923 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006924 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6925 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006926 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
6927 // Generate process state info for running application
6928 ActivityManager.RunningAppProcessInfo currApp =
6929 new ActivityManager.RunningAppProcessInfo(app.processName,
6930 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07006931 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006932 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07006933 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07006934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006935 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006936 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
6938 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
6939 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08006940 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
6941 } else if (adj >= HOME_APP_ADJ) {
6942 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
6943 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006944 } else if (adj >= SECONDARY_SERVER_ADJ) {
6945 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07006946 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
6947 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
6948 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
6949 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006950 } else if (adj >= VISIBLE_APP_ADJ) {
6951 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
6952 } else {
6953 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
6954 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006955 currApp.importanceReasonCode = app.adjTypeCode;
6956 if (app.adjSource instanceof ProcessRecord) {
6957 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006958 } else if (app.adjSource instanceof ActivityRecord) {
6959 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07006960 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
6961 }
6962 if (app.adjTarget instanceof ComponentName) {
6963 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
6964 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006965 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006966 // + " lru=" + currApp.lru);
6967 if (runList == null) {
6968 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
6969 }
6970 runList.add(currApp);
6971 }
6972 }
6973 }
6974 return runList;
6975 }
6976
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006977 public List<ApplicationInfo> getRunningExternalApplications() {
6978 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
6979 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
6980 if (runningApps != null && runningApps.size() > 0) {
6981 Set<String> extList = new HashSet<String>();
6982 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
6983 if (app.pkgList != null) {
6984 for (String pkg : app.pkgList) {
6985 extList.add(pkg);
6986 }
6987 }
6988 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006989 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006990 for (String pkg : extList) {
6991 try {
6992 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
6993 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
6994 retList.add(info);
6995 }
6996 } catch (RemoteException e) {
6997 }
6998 }
6999 }
7000 return retList;
7001 }
7002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007003 @Override
7004 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007005 if (checkCallingPermission(android.Manifest.permission.DUMP)
7006 != PackageManager.PERMISSION_GRANTED) {
7007 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7008 + Binder.getCallingPid()
7009 + ", uid=" + Binder.getCallingUid()
7010 + " without permission "
7011 + android.Manifest.permission.DUMP);
7012 return;
7013 }
7014
7015 boolean dumpAll = false;
7016
7017 int opti = 0;
7018 while (opti < args.length) {
7019 String opt = args[opti];
7020 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7021 break;
7022 }
7023 opti++;
7024 if ("-a".equals(opt)) {
7025 dumpAll = true;
7026 } else if ("-h".equals(opt)) {
7027 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007028 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007029 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007030 pw.println(" a[ctivities]: activity stack state");
7031 pw.println(" b[roadcasts]: broadcast state");
7032 pw.println(" i[ntents]: pending intent state");
7033 pw.println(" p[rocesses]: process state");
7034 pw.println(" o[om]: out of memory management");
7035 pw.println(" prov[iders]: content provider state");
7036 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007037 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007038 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007039 } else {
7040 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007041 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007042 }
7043
7044 // Is the caller requesting to dump a particular piece of data?
7045 if (opti < args.length) {
7046 String cmd = args[opti];
7047 opti++;
7048 if ("activities".equals(cmd) || "a".equals(cmd)) {
7049 synchronized (this) {
7050 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007051 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007052 return;
7053 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7054 synchronized (this) {
7055 dumpBroadcastsLocked(fd, pw, args, opti, true);
7056 }
7057 return;
7058 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7059 synchronized (this) {
7060 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7061 }
7062 return;
7063 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7064 synchronized (this) {
7065 dumpProcessesLocked(fd, pw, args, opti, true);
7066 }
7067 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007068 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7069 synchronized (this) {
7070 dumpOomLocked(fd, pw, args, opti, true);
7071 }
7072 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007073 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7074 synchronized (this) {
7075 dumpProvidersLocked(fd, pw, args, opti, true);
7076 }
7077 return;
7078 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007079 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007080 return;
7081 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7082 synchronized (this) {
7083 dumpServicesLocked(fd, pw, args, opti, true);
7084 }
7085 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007086 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007087 }
7088
7089 // No piece of data specified, dump everything.
7090 synchronized (this) {
7091 boolean needSep;
7092 if (dumpAll) {
7093 pw.println("Providers in Current Activity Manager State:");
7094 }
7095 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7096 if (needSep) {
7097 pw.println(" ");
7098 }
7099 if (dumpAll) {
7100 pw.println("-------------------------------------------------------------------------------");
7101 pw.println("Broadcasts in Current Activity Manager State:");
7102 }
7103 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7104 if (needSep) {
7105 pw.println(" ");
7106 }
7107 if (dumpAll) {
7108 pw.println("-------------------------------------------------------------------------------");
7109 pw.println("Services in Current Activity Manager State:");
7110 }
7111 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7112 if (needSep) {
7113 pw.println(" ");
7114 }
7115 if (dumpAll) {
7116 pw.println("-------------------------------------------------------------------------------");
7117 pw.println("PendingIntents in Current Activity Manager State:");
7118 }
7119 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7120 if (needSep) {
7121 pw.println(" ");
7122 }
7123 if (dumpAll) {
7124 pw.println("-------------------------------------------------------------------------------");
7125 pw.println("Activities in Current Activity Manager State:");
7126 }
7127 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7128 if (needSep) {
7129 pw.println(" ");
7130 }
7131 if (dumpAll) {
7132 pw.println("-------------------------------------------------------------------------------");
7133 pw.println("Processes in Current Activity Manager State:");
7134 }
7135 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7136 }
7137 }
7138
7139 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7140 int opti, boolean dumpAll, boolean needHeader) {
7141 if (needHeader) {
7142 pw.println(" Activity stack:");
7143 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007144 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007145 pw.println(" ");
7146 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007147 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7148 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007150 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007151 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007152 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007153 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007154 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007155 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007156 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007157 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007158 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007159 pw.println(" ");
7160 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007161 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007163
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007164 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007165 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7166 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007167 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007168 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007169
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007170 if (dumpAll && mRecentTasks.size() > 0) {
7171 pw.println(" ");
7172 pw.println("Recent tasks in Current Activity Manager State:");
7173
7174 final int N = mRecentTasks.size();
7175 for (int i=0; i<N; i++) {
7176 TaskRecord tr = mRecentTasks.get(i);
7177 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7178 pw.println(tr);
7179 mRecentTasks.get(i).dump(pw, " ");
7180 }
7181 }
7182
7183 pw.println(" ");
7184 pw.println(" mCurTask: " + mCurTask);
7185
7186 return true;
7187 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007188
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007189 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7190 int opti, boolean dumpAll) {
7191 boolean needSep = false;
7192 int numPers = 0;
7193
7194 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007195 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7196 final int NA = procs.size();
7197 for (int ia=0; ia<NA; ia++) {
7198 if (!needSep) {
7199 pw.println(" All known processes:");
7200 needSep = true;
7201 }
7202 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007203 pw.print(r.persistent ? " *PERS*" : " *APP*");
7204 pw.print(" UID "); pw.print(procs.keyAt(ia));
7205 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007206 r.dump(pw, " ");
7207 if (r.persistent) {
7208 numPers++;
7209 }
7210 }
7211 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007212 }
7213
7214 if (mLruProcesses.size() > 0) {
7215 if (needSep) pw.println(" ");
7216 needSep = true;
7217 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007218 dumpProcessOomList(pw, this, mLruProcesses, " ",
7219 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007220 needSep = true;
7221 }
7222
7223 synchronized (mPidsSelfLocked) {
7224 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 if (needSep) pw.println(" ");
7226 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007227 pw.println(" PID mappings:");
7228 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7229 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7230 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007231 }
7232 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007233 }
7234
7235 if (mForegroundProcesses.size() > 0) {
7236 if (needSep) pw.println(" ");
7237 needSep = true;
7238 pw.println(" Foreground Processes:");
7239 for (int i=0; i<mForegroundProcesses.size(); i++) {
7240 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7241 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007242 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007243 }
7244
7245 if (mPersistentStartingProcesses.size() > 0) {
7246 if (needSep) pw.println(" ");
7247 needSep = true;
7248 pw.println(" Persisent processes that are starting:");
7249 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007250 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007253 if (mStartingProcesses.size() > 0) {
7254 if (needSep) pw.println(" ");
7255 needSep = true;
7256 pw.println(" Processes that are starting:");
7257 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007258 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007260
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007261 if (mRemovedProcesses.size() > 0) {
7262 if (needSep) pw.println(" ");
7263 needSep = true;
7264 pw.println(" Processes that are being removed:");
7265 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007266 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007267 }
7268
7269 if (mProcessesOnHold.size() > 0) {
7270 if (needSep) pw.println(" ");
7271 needSep = true;
7272 pw.println(" Processes that are on old until the system is ready:");
7273 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007274 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007276
Dianne Hackborn287952c2010-09-22 22:34:31 -07007277 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007278
7279 if (mProcessCrashTimes.getMap().size() > 0) {
7280 if (needSep) pw.println(" ");
7281 needSep = true;
7282 pw.println(" Time since processes crashed:");
7283 long now = SystemClock.uptimeMillis();
7284 for (Map.Entry<String, SparseArray<Long>> procs
7285 : mProcessCrashTimes.getMap().entrySet()) {
7286 SparseArray<Long> uids = procs.getValue();
7287 final int N = uids.size();
7288 for (int i=0; i<N; i++) {
7289 pw.print(" Process "); pw.print(procs.getKey());
7290 pw.print(" uid "); pw.print(uids.keyAt(i));
7291 pw.print(": last crashed ");
7292 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007293 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007294 }
7295 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007296 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007298 if (mBadProcesses.getMap().size() > 0) {
7299 if (needSep) pw.println(" ");
7300 needSep = true;
7301 pw.println(" Bad processes:");
7302 for (Map.Entry<String, SparseArray<Long>> procs
7303 : mBadProcesses.getMap().entrySet()) {
7304 SparseArray<Long> uids = procs.getValue();
7305 final int N = uids.size();
7306 for (int i=0; i<N; i++) {
7307 pw.print(" Bad process "); pw.print(procs.getKey());
7308 pw.print(" uid "); pw.print(uids.keyAt(i));
7309 pw.print(": crashed at time ");
7310 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007311 }
7312 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007315 pw.println(" ");
7316 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007317 if (mHeavyWeightProcess != null) {
7318 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7319 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007320 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007321 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007322 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7323 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7324 || mOrigWaitForDebugger) {
7325 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7326 + " mDebugTransient=" + mDebugTransient
7327 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7328 }
7329 if (mAlwaysFinishActivities || mController != null) {
7330 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7331 + " mController=" + mController);
7332 }
7333 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007334 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007335 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007336 + " mProcessesReady=" + mProcessesReady
7337 + " mSystemReady=" + mSystemReady);
7338 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339 + " mBooted=" + mBooted
7340 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007341 pw.print(" mLastPowerCheckRealtime=");
7342 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7343 pw.println("");
7344 pw.print(" mLastPowerCheckUptime=");
7345 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7346 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007347 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7348 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007349 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007351
7352 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 }
7354
Dianne Hackborn287952c2010-09-22 22:34:31 -07007355 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7356 int opti, boolean needSep, boolean dumpAll) {
7357 if (mProcessesToGc.size() > 0) {
7358 if (needSep) pw.println(" ");
7359 needSep = true;
7360 pw.println(" Processes that are waiting to GC:");
7361 long now = SystemClock.uptimeMillis();
7362 for (int i=0; i<mProcessesToGc.size(); i++) {
7363 ProcessRecord proc = mProcessesToGc.get(i);
7364 pw.print(" Process "); pw.println(proc);
7365 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7366 pw.print(", last gced=");
7367 pw.print(now-proc.lastRequestedGc);
7368 pw.print(" ms ago, last lowMem=");
7369 pw.print(now-proc.lastLowMemory);
7370 pw.println(" ms ago");
7371
7372 }
7373 }
7374 return needSep;
7375 }
7376
7377 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7378 int opti, boolean dumpAll) {
7379 boolean needSep = false;
7380
7381 if (mLruProcesses.size() > 0) {
7382 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7383
7384 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7385 @Override
7386 public int compare(ProcessRecord object1, ProcessRecord object2) {
7387 if (object1.setAdj != object2.setAdj) {
7388 return object1.setAdj > object2.setAdj ? -1 : 1;
7389 }
7390 if (object1.setSchedGroup != object2.setSchedGroup) {
7391 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7392 }
7393 if (object1.keeping != object2.keeping) {
7394 return object1.keeping ? -1 : 1;
7395 }
7396 if (object1.pid != object2.pid) {
7397 return object1.pid > object2.pid ? -1 : 1;
7398 }
7399 return 0;
7400 }
7401 };
7402
7403 Collections.sort(procs, comparator);
7404
7405 if (needSep) pw.println(" ");
7406 needSep = true;
7407 pw.println(" Process OOM control:");
7408 dumpProcessOomList(pw, this, procs, " ",
7409 "Proc", "PERS", true);
7410 needSep = true;
7411 }
7412
7413 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7414
7415 pw.println(" ");
7416 pw.println(" mHomeProcess: " + mHomeProcess);
7417 if (mHeavyWeightProcess != null) {
7418 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7419 }
7420
7421 return true;
7422 }
7423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 /**
7425 * There are three ways to call this:
7426 * - no service specified: dump all the services
7427 * - a flattened component name that matched an existing service was specified as the
7428 * first arg: dump that one service
7429 * - the first arg isn't the flattened component name of an existing service:
7430 * dump all services whose component contains the first arg as a substring
7431 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007432 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7433 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 String[] newArgs;
7435 String componentNameString;
7436 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007437 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 componentNameString = null;
7439 newArgs = EMPTY_STRING_ARRAY;
7440 r = null;
7441 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007442 componentNameString = args[opti];
7443 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007444 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007445 synchronized (this) {
7446 r = componentName != null ? mServices.get(componentName) : null;
7447 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007448 newArgs = new String[args.length - opti];
7449 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007450 }
7451
7452 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007453 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007454 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007455 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7456 synchronized (this) {
7457 for (ServiceRecord r1 : mServices.values()) {
7458 if (componentNameString == null
7459 || r1.name.flattenToString().contains(componentNameString)) {
7460 services.add(r1);
7461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007462 }
7463 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007464 for (int i=0; i<services.size(); i++) {
7465 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007467 }
7468 }
7469
7470 /**
7471 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7472 * there is a thread associated with the service.
7473 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007474 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7475 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007477 if (dumpAll) {
7478 synchronized (this) {
7479 pw.print(" * "); pw.println(r);
7480 r.dump(pw, " ");
7481 }
7482 pw.println("");
7483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484 if (r.app != null && r.app.thread != null) {
7485 try {
7486 // flush anything that is already in the PrintWriter since the thread is going
7487 // to write to the file descriptor directly
7488 pw.flush();
7489 r.app.thread.dumpService(fd, r, args);
7490 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007491 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007492 } catch (RemoteException e) {
7493 pw.println("got a RemoteException while dumping the service");
7494 }
7495 }
7496 }
7497
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007498 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7499 int opti, boolean dumpAll) {
7500 boolean needSep = false;
7501
7502 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007503 if (mRegisteredReceivers.size() > 0) {
7504 pw.println(" ");
7505 pw.println(" Registered Receivers:");
7506 Iterator it = mRegisteredReceivers.values().iterator();
7507 while (it.hasNext()) {
7508 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007509 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007510 r.dump(pw, " ");
7511 }
7512 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514 pw.println(" ");
7515 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007516 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007517 needSep = true;
7518 }
7519
7520 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7521 || mPendingBroadcast != null) {
7522 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007524 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007525 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007526 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7527 pw.println(" Broadcast #" + i + ":");
7528 mParallelBroadcasts.get(i).dump(pw, " ");
7529 }
7530 if (mOrderedBroadcasts.size() > 0) {
7531 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007532 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007533 }
7534 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7535 pw.println(" Serialized Broadcast #" + i + ":");
7536 mOrderedBroadcasts.get(i).dump(pw, " ");
7537 }
7538 pw.println(" ");
7539 pw.println(" Pending broadcast:");
7540 if (mPendingBroadcast != null) {
7541 mPendingBroadcast.dump(pw, " ");
7542 } else {
7543 pw.println(" (null)");
7544 }
7545 needSep = true;
7546 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007547
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007548 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007550 pw.println(" Historical broadcasts:");
7551 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7552 BroadcastRecord r = mBroadcastHistory[i];
7553 if (r == null) {
7554 break;
7555 }
7556 pw.println(" Historical Broadcast #" + i + ":");
7557 r.dump(pw, " ");
7558 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007559 needSep = true;
7560 }
7561
7562 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007563 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007564 pw.println(" Sticky broadcasts:");
7565 StringBuilder sb = new StringBuilder(128);
7566 for (Map.Entry<String, ArrayList<Intent>> ent
7567 : mStickyBroadcasts.entrySet()) {
7568 pw.print(" * Sticky action "); pw.print(ent.getKey());
7569 pw.println(":");
7570 ArrayList<Intent> intents = ent.getValue();
7571 final int N = intents.size();
7572 for (int i=0; i<N; i++) {
7573 sb.setLength(0);
7574 sb.append(" Intent: ");
7575 intents.get(i).toShortString(sb, true, false);
7576 pw.println(sb.toString());
7577 Bundle bundle = intents.get(i).getExtras();
7578 if (bundle != null) {
7579 pw.print(" ");
7580 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 }
7582 }
7583 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007584 needSep = true;
7585 }
7586
7587 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007588 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007589 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 pw.println(" mHandler:");
7591 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007592 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007593 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007594
7595 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007596 }
7597
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007598 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7599 int opti, boolean dumpAll) {
7600 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007601
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007602 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 if (mServices.size() > 0) {
7604 pw.println(" Active services:");
7605 Iterator<ServiceRecord> it = mServices.values().iterator();
7606 while (it.hasNext()) {
7607 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007608 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007609 r.dump(pw, " ");
7610 }
7611 needSep = true;
7612 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007613 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007615 if (mPendingServices.size() > 0) {
7616 if (needSep) pw.println(" ");
7617 pw.println(" Pending services:");
7618 for (int i=0; i<mPendingServices.size(); i++) {
7619 ServiceRecord r = mPendingServices.get(i);
7620 pw.print(" * Pending "); pw.println(r);
7621 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007622 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007623 needSep = true;
7624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007626 if (mRestartingServices.size() > 0) {
7627 if (needSep) pw.println(" ");
7628 pw.println(" Restarting services:");
7629 for (int i=0; i<mRestartingServices.size(); i++) {
7630 ServiceRecord r = mRestartingServices.get(i);
7631 pw.print(" * Restarting "); pw.println(r);
7632 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007634 needSep = true;
7635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007637 if (mStoppingServices.size() > 0) {
7638 if (needSep) pw.println(" ");
7639 pw.println(" Stopping services:");
7640 for (int i=0; i<mStoppingServices.size(); i++) {
7641 ServiceRecord r = mStoppingServices.get(i);
7642 pw.print(" * Stopping "); pw.println(r);
7643 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007644 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007645 needSep = true;
7646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007647
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007648 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007649 if (mServiceConnections.size() > 0) {
7650 if (needSep) pw.println(" ");
7651 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007652 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 = mServiceConnections.values().iterator();
7654 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007655 ArrayList<ConnectionRecord> r = it.next();
7656 for (int i=0; i<r.size(); i++) {
7657 pw.print(" * "); pw.println(r.get(i));
7658 r.get(i).dump(pw, " ");
7659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007660 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007661 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007662 }
7663 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007664
7665 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 }
7667
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007668 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7669 int opti, boolean dumpAll) {
7670 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007671
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007672 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 if (mProvidersByClass.size() > 0) {
7674 if (needSep) pw.println(" ");
7675 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007676 Iterator<Map.Entry<String, ContentProviderRecord>> it
7677 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007679 Map.Entry<String, ContentProviderRecord> e = it.next();
7680 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007681 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 r.dump(pw, " ");
7683 }
7684 needSep = true;
7685 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007686
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007687 if (mProvidersByName.size() > 0) {
7688 pw.println(" ");
7689 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007690 Iterator<Map.Entry<String, ContentProviderRecord>> it
7691 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007692 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007693 Map.Entry<String, ContentProviderRecord> e = it.next();
7694 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007695 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7696 pw.println(r);
7697 }
7698 needSep = true;
7699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007700 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007701
7702 if (mLaunchingProviders.size() > 0) {
7703 if (needSep) pw.println(" ");
7704 pw.println(" Launching content providers:");
7705 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7706 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7707 pw.println(mLaunchingProviders.get(i));
7708 }
7709 needSep = true;
7710 }
7711
7712 if (mGrantedUriPermissions.size() > 0) {
7713 pw.println();
7714 pw.println("Granted Uri Permissions:");
7715 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7716 int uid = mGrantedUriPermissions.keyAt(i);
7717 HashMap<Uri, UriPermission> perms
7718 = mGrantedUriPermissions.valueAt(i);
7719 pw.print(" * UID "); pw.print(uid);
7720 pw.println(" holds:");
7721 for (UriPermission perm : perms.values()) {
7722 pw.print(" "); pw.println(perm);
7723 perm.dump(pw, " ");
7724 }
7725 }
7726 needSep = true;
7727 }
7728
7729 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 }
7731
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007732 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7733 int opti, boolean dumpAll) {
7734 boolean needSep = false;
7735
7736 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007737 if (this.mIntentSenderRecords.size() > 0) {
7738 Iterator<WeakReference<PendingIntentRecord>> it
7739 = mIntentSenderRecords.values().iterator();
7740 while (it.hasNext()) {
7741 WeakReference<PendingIntentRecord> ref = it.next();
7742 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007743 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007744 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007745 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 rec.dump(pw, " ");
7747 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007748 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 }
7750 }
7751 }
7752 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753
7754 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755 }
7756
7757 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007758 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007759 TaskRecord lastTask = null;
7760 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007761 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007762 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007763 if (lastTask != r.task) {
7764 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007765 pw.print(prefix);
7766 pw.print(full ? "* " : " ");
7767 pw.println(lastTask);
7768 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007769 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007772 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7773 pw.print(" #"); pw.print(i); pw.print(": ");
7774 pw.println(r);
7775 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007776 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007777 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007778 }
7779 }
7780
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007781 private static String buildOomTag(String prefix, String space, int val, int base) {
7782 if (val == base) {
7783 if (space == null) return prefix;
7784 return prefix + " ";
7785 }
7786 return prefix + "+" + Integer.toString(val-base);
7787 }
7788
7789 private static final int dumpProcessList(PrintWriter pw,
7790 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07007791 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007793 final int N = list.size()-1;
7794 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007796 pw.println(String.format("%s%s #%2d: %s",
7797 prefix, (r.persistent ? persistentLabel : normalLabel),
7798 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 if (r.persistent) {
7800 numPers++;
7801 }
7802 }
7803 return numPers;
7804 }
7805
Dianne Hackborn287952c2010-09-22 22:34:31 -07007806 private static final void dumpProcessOomList(PrintWriter pw,
7807 ActivityManagerService service, List<ProcessRecord> list,
7808 String prefix, String normalLabel, String persistentLabel,
7809 boolean inclDetails) {
7810
7811 final long curRealtime = SystemClock.elapsedRealtime();
7812 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
7813 final long curUptime = SystemClock.uptimeMillis();
7814 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
7815
7816 final int N = list.size()-1;
7817 for (int i=N; i>=0; i--) {
7818 ProcessRecord r = list.get(i);
7819 String oomAdj;
7820 if (r.setAdj >= EMPTY_APP_ADJ) {
7821 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
7822 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
7823 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7824 } else if (r.setAdj >= HOME_APP_ADJ) {
7825 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7826 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7827 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7828 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7829 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
7830 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7831 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7832 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7833 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
7834 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7835 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7836 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7837 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
7838 } else if (r.setAdj >= CORE_SERVER_ADJ) {
7839 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
7840 } else if (r.setAdj >= SYSTEM_ADJ) {
7841 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
7842 } else {
7843 oomAdj = Integer.toString(r.setAdj);
7844 }
7845 String schedGroup;
7846 switch (r.setSchedGroup) {
7847 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7848 schedGroup = "B";
7849 break;
7850 case Process.THREAD_GROUP_DEFAULT:
7851 schedGroup = "F";
7852 break;
7853 default:
7854 schedGroup = Integer.toString(r.setSchedGroup);
7855 break;
7856 }
7857 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
7858 prefix, (r.persistent ? persistentLabel : normalLabel),
7859 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
7860 if (r.adjSource != null || r.adjTarget != null) {
7861 pw.print(prefix);
7862 pw.print(" ");
7863 if (r.adjTarget instanceof ComponentName) {
7864 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7865 } else if (r.adjTarget != null) {
7866 pw.print(r.adjTarget.toString());
7867 } else {
7868 pw.print("{null}");
7869 }
7870 pw.print("<=");
7871 if (r.adjSource instanceof ProcessRecord) {
7872 pw.print("Proc{");
7873 pw.print(((ProcessRecord)r.adjSource).toShortString());
7874 pw.println("}");
7875 } else if (r.adjSource != null) {
7876 pw.println(r.adjSource.toString());
7877 } else {
7878 pw.println("{null}");
7879 }
7880 }
7881 if (inclDetails) {
7882 pw.print(prefix);
7883 pw.print(" ");
7884 pw.print("oom: max="); pw.print(r.maxAdj);
7885 pw.print(" hidden="); pw.print(r.hiddenAdj);
7886 pw.print(" curRaw="); pw.print(r.curRawAdj);
7887 pw.print(" setRaw="); pw.print(r.setRawAdj);
7888 pw.print(" cur="); pw.print(r.curAdj);
7889 pw.print(" set="); pw.println(r.setAdj);
7890 pw.print(prefix);
7891 pw.print(" ");
7892 pw.print("keeping="); pw.print(r.keeping);
7893 pw.print(" hidden="); pw.print(r.hidden);
7894 pw.print(" empty="); pw.println(r.empty);
7895
7896 if (!r.keeping) {
7897 if (r.lastWakeTime != 0) {
7898 long wtime;
7899 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
7900 synchronized (stats) {
7901 wtime = stats.getProcessWakeTime(r.info.uid,
7902 r.pid, curRealtime);
7903 }
7904 long timeUsed = wtime - r.lastWakeTime;
7905 pw.print(prefix);
7906 pw.print(" ");
7907 pw.print("keep awake over ");
7908 TimeUtils.formatDuration(realtimeSince, pw);
7909 pw.print(" used ");
7910 TimeUtils.formatDuration(timeUsed, pw);
7911 pw.print(" (");
7912 pw.print((timeUsed*100)/realtimeSince);
7913 pw.println("%)");
7914 }
7915 if (r.lastCpuTime != 0) {
7916 long timeUsed = r.curCpuTime - r.lastCpuTime;
7917 pw.print(prefix);
7918 pw.print(" ");
7919 pw.print("run cpu over ");
7920 TimeUtils.formatDuration(uptimeSince, pw);
7921 pw.print(" used ");
7922 TimeUtils.formatDuration(timeUsed, pw);
7923 pw.print(" (");
7924 pw.print((timeUsed*100)/uptimeSince);
7925 pw.println("%)");
7926 }
7927 }
7928 }
7929 }
7930 }
7931
Dianne Hackborn472ad872010-04-07 17:31:48 -07007932 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07007934 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 long uptime = SystemClock.uptimeMillis();
7936 long realtime = SystemClock.elapsedRealtime();
7937
7938 if (isCheckinRequest) {
7939 // short checkin version
7940 pw.println(uptime + "," + realtime);
7941 pw.flush();
7942 } else {
7943 pw.println("Applications Memory Usage (kB):");
7944 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
7945 }
7946 for (int i = list.size() - 1 ; i >= 0 ; i--) {
7947 ProcessRecord r = (ProcessRecord)list.get(i);
7948 if (r.thread != null) {
7949 if (!isCheckinRequest) {
7950 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
7951 pw.flush();
7952 }
7953 try {
7954 r.thread.asBinder().dump(fd, args);
7955 } catch (RemoteException e) {
7956 if (!isCheckinRequest) {
7957 pw.println("Got RemoteException!");
7958 pw.flush();
7959 }
7960 }
7961 }
7962 }
7963 }
7964
7965 /**
7966 * Searches array of arguments for the specified string
7967 * @param args array of argument strings
7968 * @param value value to search for
7969 * @return true if the value is contained in the array
7970 */
7971 private static boolean scanArgs(String[] args, String value) {
7972 if (args != null) {
7973 for (String arg : args) {
7974 if (value.equals(arg)) {
7975 return true;
7976 }
7977 }
7978 }
7979 return false;
7980 }
7981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007982 private final void killServicesLocked(ProcessRecord app,
7983 boolean allowRestart) {
7984 // Report disconnected services.
7985 if (false) {
7986 // XXX we are letting the client link to the service for
7987 // death notifications.
7988 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007989 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007990 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007991 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007992 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007993 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007994 = r.connections.values().iterator();
7995 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007996 ArrayList<ConnectionRecord> cl = jt.next();
7997 for (int i=0; i<cl.size(); i++) {
7998 ConnectionRecord c = cl.get(i);
7999 if (c.binding.client != app) {
8000 try {
8001 //c.conn.connected(r.className, null);
8002 } catch (Exception e) {
8003 // todo: this should be asynchronous!
8004 Slog.w(TAG, "Exception thrown disconnected servce "
8005 + r.shortName
8006 + " from app " + app.processName, e);
8007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008008 }
8009 }
8010 }
8011 }
8012 }
8013 }
8014 }
8015
8016 // Clean up any connections this application has to other services.
8017 if (app.connections.size() > 0) {
8018 Iterator<ConnectionRecord> it = app.connections.iterator();
8019 while (it.hasNext()) {
8020 ConnectionRecord r = it.next();
8021 removeConnectionLocked(r, app, null);
8022 }
8023 }
8024 app.connections.clear();
8025
8026 if (app.services.size() != 0) {
8027 // Any services running in the application need to be placed
8028 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008029 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008030 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008031 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 synchronized (sr.stats.getBatteryStats()) {
8033 sr.stats.stopLaunchedLocked();
8034 }
8035 sr.app = null;
8036 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008037 if (mStoppingServices.remove(sr)) {
8038 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8039 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008040
8041 boolean hasClients = sr.bindings.size() > 0;
8042 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008043 Iterator<IntentBindRecord> bindings
8044 = sr.bindings.values().iterator();
8045 while (bindings.hasNext()) {
8046 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008047 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 + ": shouldUnbind=" + b.hasBound);
8049 b.binder = null;
8050 b.requested = b.received = b.hasBound = false;
8051 }
8052 }
8053
8054 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008055 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008056 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008057 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008058 sr.crashCount, sr.shortName, app.pid);
8059 bringDownServiceLocked(sr, true);
8060 } else if (!allowRestart) {
8061 bringDownServiceLocked(sr, true);
8062 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008063 boolean canceled = scheduleServiceRestartLocked(sr, true);
8064
8065 // Should the service remain running? Note that in the
8066 // extreme case of so many attempts to deliver a command
8067 // that it failed, that we also will stop it here.
8068 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8069 if (sr.pendingStarts.size() == 0) {
8070 sr.startRequested = false;
8071 if (!hasClients) {
8072 // Whoops, no reason to restart!
8073 bringDownServiceLocked(sr, true);
8074 }
8075 }
8076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 }
8078 }
8079
8080 if (!allowRestart) {
8081 app.services.clear();
8082 }
8083 }
8084
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008085 // Make sure we have no more records on the stopping list.
8086 int i = mStoppingServices.size();
8087 while (i > 0) {
8088 i--;
8089 ServiceRecord sr = mStoppingServices.get(i);
8090 if (sr.app == app) {
8091 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008092 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008093 }
8094 }
8095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008096 app.executingServices.clear();
8097 }
8098
8099 private final void removeDyingProviderLocked(ProcessRecord proc,
8100 ContentProviderRecord cpr) {
8101 synchronized (cpr) {
8102 cpr.launchingApp = null;
8103 cpr.notifyAll();
8104 }
8105
8106 mProvidersByClass.remove(cpr.info.name);
8107 String names[] = cpr.info.authority.split(";");
8108 for (int j = 0; j < names.length; j++) {
8109 mProvidersByName.remove(names[j]);
8110 }
8111
8112 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8113 while (cit.hasNext()) {
8114 ProcessRecord capp = cit.next();
8115 if (!capp.persistent && capp.thread != null
8116 && capp.pid != 0
8117 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008118 Slog.i(TAG, "Kill " + capp.processName
8119 + " (pid " + capp.pid + "): provider " + cpr.info.name
8120 + " in dying process " + proc.processName);
8121 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8122 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 Process.killProcess(capp.pid);
8124 }
8125 }
8126
8127 mLaunchingProviders.remove(cpr);
8128 }
8129
8130 /**
8131 * Main code for cleaning up a process when it has gone away. This is
8132 * called both as a result of the process dying, or directly when stopping
8133 * a process when running in single process mode.
8134 */
8135 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8136 boolean restarting, int index) {
8137 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008138 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 }
8140
Dianne Hackborn36124872009-10-08 16:22:03 -07008141 mProcessesToGc.remove(app);
8142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 // Dismiss any open dialogs.
8144 if (app.crashDialog != null) {
8145 app.crashDialog.dismiss();
8146 app.crashDialog = null;
8147 }
8148 if (app.anrDialog != null) {
8149 app.anrDialog.dismiss();
8150 app.anrDialog = null;
8151 }
8152 if (app.waitDialog != null) {
8153 app.waitDialog.dismiss();
8154 app.waitDialog = null;
8155 }
8156
8157 app.crashing = false;
8158 app.notResponding = false;
8159
8160 app.resetPackageList();
8161 app.thread = null;
8162 app.forcingToForeground = null;
8163 app.foregroundServices = false;
8164
8165 killServicesLocked(app, true);
8166
8167 boolean restart = false;
8168
8169 int NL = mLaunchingProviders.size();
8170
8171 // Remove published content providers.
8172 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008173 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008175 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008176 cpr.provider = null;
8177 cpr.app = null;
8178
8179 // See if someone is waiting for this provider... in which
8180 // case we don't remove it, but just let it restart.
8181 int i = 0;
8182 if (!app.bad) {
8183 for (; i<NL; i++) {
8184 if (mLaunchingProviders.get(i) == cpr) {
8185 restart = true;
8186 break;
8187 }
8188 }
8189 } else {
8190 i = NL;
8191 }
8192
8193 if (i >= NL) {
8194 removeDyingProviderLocked(app, cpr);
8195 NL = mLaunchingProviders.size();
8196 }
8197 }
8198 app.pubProviders.clear();
8199 }
8200
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008201 // Take care of any launching providers waiting for this process.
8202 if (checkAppInLaunchingProvidersLocked(app, false)) {
8203 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008206 // Unregister from connected content providers.
8207 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008208 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008209 while (it.hasNext()) {
8210 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8211 cpr.clients.remove(app);
8212 }
8213 app.conProviders.clear();
8214 }
8215
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008216 // At this point there may be remaining entries in mLaunchingProviders
8217 // where we were the only one waiting, so they are no longer of use.
8218 // Look for these and clean up if found.
8219 // XXX Commented out for now. Trying to figure out a way to reproduce
8220 // the actual situation to identify what is actually going on.
8221 if (false) {
8222 for (int i=0; i<NL; i++) {
8223 ContentProviderRecord cpr = (ContentProviderRecord)
8224 mLaunchingProviders.get(i);
8225 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8226 synchronized (cpr) {
8227 cpr.launchingApp = null;
8228 cpr.notifyAll();
8229 }
8230 }
8231 }
8232 }
8233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008234 skipCurrentReceiverLocked(app);
8235
8236 // Unregister any receivers.
8237 if (app.receivers.size() > 0) {
8238 Iterator<ReceiverList> it = app.receivers.iterator();
8239 while (it.hasNext()) {
8240 removeReceiverLocked(it.next());
8241 }
8242 app.receivers.clear();
8243 }
8244
Christopher Tate181fafa2009-05-14 11:12:14 -07008245 // If the app is undergoing backup, tell the backup manager about it
8246 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008247 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008248 try {
8249 IBackupManager bm = IBackupManager.Stub.asInterface(
8250 ServiceManager.getService(Context.BACKUP_SERVICE));
8251 bm.agentDisconnected(app.info.packageName);
8252 } catch (RemoteException e) {
8253 // can't happen; backup manager is local
8254 }
8255 }
8256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008257 // If the caller is restarting this app, then leave it in its
8258 // current lists and let the caller take care of it.
8259 if (restarting) {
8260 return;
8261 }
8262
8263 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008264 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008265 "Removing non-persistent process during cleanup: " + app);
8266 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008267 if (mHeavyWeightProcess == app) {
8268 mHeavyWeightProcess = null;
8269 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271 } else if (!app.removed) {
8272 // This app is persistent, so we need to keep its record around.
8273 // If it is not already on the pending app list, add it there
8274 // and start a new process for it.
8275 app.thread = null;
8276 app.forcingToForeground = null;
8277 app.foregroundServices = false;
8278 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8279 mPersistentStartingProcesses.add(app);
8280 restart = true;
8281 }
8282 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008283 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8284 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008285 mProcessesOnHold.remove(app);
8286
The Android Open Source Project4df24232009-03-05 14:34:35 -08008287 if (app == mHomeProcess) {
8288 mHomeProcess = null;
8289 }
8290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008291 if (restart) {
8292 // We have components that still need to be running in the
8293 // process, so re-launch it.
8294 mProcessNames.put(app.processName, app.info.uid, app);
8295 startProcessLocked(app, "restart", app.processName);
8296 } else if (app.pid > 0 && app.pid != MY_PID) {
8297 // Goodbye!
8298 synchronized (mPidsSelfLocked) {
8299 mPidsSelfLocked.remove(app.pid);
8300 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8301 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008302 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 }
8304 }
8305
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008306 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8307 // Look through the content providers we are waiting to have launched,
8308 // and if any run in this process then either schedule a restart of
8309 // the process or kill the client waiting for it if this process has
8310 // gone bad.
8311 int NL = mLaunchingProviders.size();
8312 boolean restart = false;
8313 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008314 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008315 if (cpr.launchingApp == app) {
8316 if (!alwaysBad && !app.bad) {
8317 restart = true;
8318 } else {
8319 removeDyingProviderLocked(app, cpr);
8320 NL = mLaunchingProviders.size();
8321 }
8322 }
8323 }
8324 return restart;
8325 }
8326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008327 // =========================================================
8328 // SERVICES
8329 // =========================================================
8330
8331 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8332 ActivityManager.RunningServiceInfo info =
8333 new ActivityManager.RunningServiceInfo();
8334 info.service = r.name;
8335 if (r.app != null) {
8336 info.pid = r.app.pid;
8337 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008338 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 info.process = r.processName;
8340 info.foreground = r.isForeground;
8341 info.activeSince = r.createTime;
8342 info.started = r.startRequested;
8343 info.clientCount = r.connections.size();
8344 info.crashCount = r.crashCount;
8345 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008346 if (r.isForeground) {
8347 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8348 }
8349 if (r.startRequested) {
8350 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8351 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008352 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008353 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8354 }
8355 if (r.app != null && r.app.persistent) {
8356 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8357 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008358
8359 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8360 for (int i=0; i<connl.size(); i++) {
8361 ConnectionRecord conn = connl.get(i);
8362 if (conn.clientLabel != 0) {
8363 info.clientPackage = conn.binding.client.info.packageName;
8364 info.clientLabel = conn.clientLabel;
8365 return info;
8366 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008367 }
8368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008369 return info;
8370 }
8371
8372 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8373 int flags) {
8374 synchronized (this) {
8375 ArrayList<ActivityManager.RunningServiceInfo> res
8376 = new ArrayList<ActivityManager.RunningServiceInfo>();
8377
8378 if (mServices.size() > 0) {
8379 Iterator<ServiceRecord> it = mServices.values().iterator();
8380 while (it.hasNext() && res.size() < maxNum) {
8381 res.add(makeRunningServiceInfoLocked(it.next()));
8382 }
8383 }
8384
8385 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8386 ServiceRecord r = mRestartingServices.get(i);
8387 ActivityManager.RunningServiceInfo info =
8388 makeRunningServiceInfoLocked(r);
8389 info.restarting = r.nextRestartTime;
8390 res.add(info);
8391 }
8392
8393 return res;
8394 }
8395 }
8396
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008397 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8398 synchronized (this) {
8399 ServiceRecord r = mServices.get(name);
8400 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008401 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8402 for (int i=0; i<conn.size(); i++) {
8403 if (conn.get(i).clientIntent != null) {
8404 return conn.get(i).clientIntent;
8405 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008406 }
8407 }
8408 }
8409 }
8410 return null;
8411 }
8412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008413 private final ServiceRecord findServiceLocked(ComponentName name,
8414 IBinder token) {
8415 ServiceRecord r = mServices.get(name);
8416 return r == token ? r : null;
8417 }
8418
8419 private final class ServiceLookupResult {
8420 final ServiceRecord record;
8421 final String permission;
8422
8423 ServiceLookupResult(ServiceRecord _record, String _permission) {
8424 record = _record;
8425 permission = _permission;
8426 }
8427 };
8428
8429 private ServiceLookupResult findServiceLocked(Intent service,
8430 String resolvedType) {
8431 ServiceRecord r = null;
8432 if (service.getComponent() != null) {
8433 r = mServices.get(service.getComponent());
8434 }
8435 if (r == null) {
8436 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8437 r = mServicesByIntent.get(filter);
8438 }
8439
8440 if (r == null) {
8441 try {
8442 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008443 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008444 service, resolvedType, 0);
8445 ServiceInfo sInfo =
8446 rInfo != null ? rInfo.serviceInfo : null;
8447 if (sInfo == null) {
8448 return null;
8449 }
8450
8451 ComponentName name = new ComponentName(
8452 sInfo.applicationInfo.packageName, sInfo.name);
8453 r = mServices.get(name);
8454 } catch (RemoteException ex) {
8455 // pm is in same process, this will never happen.
8456 }
8457 }
8458 if (r != null) {
8459 int callingPid = Binder.getCallingPid();
8460 int callingUid = Binder.getCallingUid();
8461 if (checkComponentPermission(r.permission,
8462 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8463 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008464 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008465 + " from pid=" + callingPid
8466 + ", uid=" + callingUid
8467 + " requires " + r.permission);
8468 return new ServiceLookupResult(null, r.permission);
8469 }
8470 return new ServiceLookupResult(r, null);
8471 }
8472 return null;
8473 }
8474
8475 private class ServiceRestarter implements Runnable {
8476 private ServiceRecord mService;
8477
8478 void setService(ServiceRecord service) {
8479 mService = service;
8480 }
8481
8482 public void run() {
8483 synchronized(ActivityManagerService.this) {
8484 performServiceRestartLocked(mService);
8485 }
8486 }
8487 }
8488
8489 private ServiceLookupResult retrieveServiceLocked(Intent service,
8490 String resolvedType, int callingPid, int callingUid) {
8491 ServiceRecord r = null;
8492 if (service.getComponent() != null) {
8493 r = mServices.get(service.getComponent());
8494 }
8495 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8496 r = mServicesByIntent.get(filter);
8497 if (r == null) {
8498 try {
8499 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008500 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008501 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 ServiceInfo sInfo =
8503 rInfo != null ? rInfo.serviceInfo : null;
8504 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008505 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008506 ": not found");
8507 return null;
8508 }
8509
8510 ComponentName name = new ComponentName(
8511 sInfo.applicationInfo.packageName, sInfo.name);
8512 r = mServices.get(name);
8513 if (r == null) {
8514 filter = new Intent.FilterComparison(service.cloneFilter());
8515 ServiceRestarter res = new ServiceRestarter();
8516 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8517 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8518 synchronized (stats) {
8519 ss = stats.getServiceStatsLocked(
8520 sInfo.applicationInfo.uid, sInfo.packageName,
8521 sInfo.name);
8522 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008523 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008524 res.setService(r);
8525 mServices.put(name, r);
8526 mServicesByIntent.put(filter, r);
8527
8528 // Make sure this component isn't in the pending list.
8529 int N = mPendingServices.size();
8530 for (int i=0; i<N; i++) {
8531 ServiceRecord pr = mPendingServices.get(i);
8532 if (pr.name.equals(name)) {
8533 mPendingServices.remove(i);
8534 i--;
8535 N--;
8536 }
8537 }
8538 }
8539 } catch (RemoteException ex) {
8540 // pm is in same process, this will never happen.
8541 }
8542 }
8543 if (r != null) {
8544 if (checkComponentPermission(r.permission,
8545 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8546 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008547 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 + " from pid=" + Binder.getCallingPid()
8549 + ", uid=" + Binder.getCallingUid()
8550 + " requires " + r.permission);
8551 return new ServiceLookupResult(null, r.permission);
8552 }
8553 return new ServiceLookupResult(r, null);
8554 }
8555 return null;
8556 }
8557
Dianne Hackborn287952c2010-09-22 22:34:31 -07008558 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8559 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8560 + why + " of " + r + " in app " + r.app);
8561 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8562 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008563 long now = SystemClock.uptimeMillis();
8564 if (r.executeNesting == 0 && r.app != null) {
8565 if (r.app.executingServices.size() == 0) {
8566 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8567 msg.obj = r.app;
8568 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8569 }
8570 r.app.executingServices.add(r);
8571 }
8572 r.executeNesting++;
8573 r.executingStart = now;
8574 }
8575
8576 private final void sendServiceArgsLocked(ServiceRecord r,
8577 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008578 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008579 if (N == 0) {
8580 return;
8581 }
8582
Dianne Hackborn39792d22010-08-19 18:01:52 -07008583 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008584 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008585 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008586 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8587 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008588 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008589 // If somehow we got a dummy start at the front, then
8590 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008591 continue;
8592 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008593 si.deliveredTime = SystemClock.uptimeMillis();
8594 r.deliveredStarts.add(si);
8595 si.deliveryCount++;
8596 if (si.targetPermissionUid >= 0) {
8597 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008598 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008599 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008600 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008601 if (!oomAdjusted) {
8602 oomAdjusted = true;
8603 updateOomAdjLocked(r.app);
8604 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008605 int flags = 0;
8606 if (si.deliveryCount > 0) {
8607 flags |= Service.START_FLAG_RETRY;
8608 }
8609 if (si.doneExecutingCount > 0) {
8610 flags |= Service.START_FLAG_REDELIVERY;
8611 }
8612 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008613 } catch (RemoteException e) {
8614 // Remote process gone... we'll let the normal cleanup take
8615 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008616 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008617 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008618 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008619 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008620 break;
8621 }
8622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008623 }
8624
8625 private final boolean requestServiceBindingLocked(ServiceRecord r,
8626 IntentBindRecord i, boolean rebind) {
8627 if (r.app == null || r.app.thread == null) {
8628 // If service is not currently running, can't yet bind.
8629 return false;
8630 }
8631 if ((!i.requested || rebind) && i.apps.size() > 0) {
8632 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008633 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008634 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8635 if (!rebind) {
8636 i.requested = true;
8637 }
8638 i.hasBound = true;
8639 i.doRebind = false;
8640 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008641 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 return false;
8643 }
8644 }
8645 return true;
8646 }
8647
8648 private final void requestServiceBindingsLocked(ServiceRecord r) {
8649 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8650 while (bindings.hasNext()) {
8651 IntentBindRecord i = bindings.next();
8652 if (!requestServiceBindingLocked(r, i, false)) {
8653 break;
8654 }
8655 }
8656 }
8657
8658 private final void realStartServiceLocked(ServiceRecord r,
8659 ProcessRecord app) throws RemoteException {
8660 if (app.thread == null) {
8661 throw new RemoteException();
8662 }
8663
8664 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008665 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008666
8667 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008668 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008669 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008670
8671 boolean created = false;
8672 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008673 mStringBuilder.setLength(0);
8674 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008675 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008676 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008677 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008678 synchronized (r.stats.getBatteryStats()) {
8679 r.stats.startLaunchedLocked();
8680 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008681 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008682 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008683 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008684 created = true;
8685 } finally {
8686 if (!created) {
8687 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008688 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 }
8690 }
8691
8692 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008693
8694 // If the service is in the started state, and there are no
8695 // pending arguments, then fake up one so its onStartCommand() will
8696 // be called.
8697 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8698 r.lastStartId++;
8699 if (r.lastStartId < 1) {
8700 r.lastStartId = 1;
8701 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008702 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008703 }
8704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008705 sendServiceArgsLocked(r, true);
8706 }
8707
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008708 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8709 boolean allowCancel) {
8710 boolean canceled = false;
8711
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008712 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008713 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008714 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008715
8716 // Any delivered but not yet finished starts should be put back
8717 // on the pending list.
8718 final int N = r.deliveredStarts.size();
8719 if (N > 0) {
8720 for (int i=N-1; i>=0; i--) {
8721 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008722 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008723 if (si.intent == null) {
8724 // We'll generate this again if needed.
8725 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8726 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8727 r.pendingStarts.add(0, si);
8728 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8729 dur *= 2;
8730 if (minDuration < dur) minDuration = dur;
8731 if (resetTime < dur) resetTime = dur;
8732 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008733 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008734 + r.name);
8735 canceled = true;
8736 }
8737 }
8738 r.deliveredStarts.clear();
8739 }
8740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008741 r.totalRestartCount++;
8742 if (r.restartDelay == 0) {
8743 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008744 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 } else {
8746 // If it has been a "reasonably long time" since the service
8747 // was started, then reset our restart duration back to
8748 // the beginning, so we don't infinitely increase the duration
8749 // on a service that just occasionally gets killed (which is
8750 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008751 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008752 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008753 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008754 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008755 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008756 if (r.restartDelay < minDuration) {
8757 r.restartDelay = minDuration;
8758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759 }
8760 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008761
8762 r.nextRestartTime = now + r.restartDelay;
8763
8764 // Make sure that we don't end up restarting a bunch of services
8765 // all at the same time.
8766 boolean repeat;
8767 do {
8768 repeat = false;
8769 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8770 ServiceRecord r2 = mRestartingServices.get(i);
8771 if (r2 != r && r.nextRestartTime
8772 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8773 && r.nextRestartTime
8774 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8775 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8776 r.restartDelay = r.nextRestartTime - now;
8777 repeat = true;
8778 break;
8779 }
8780 }
8781 } while (repeat);
8782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008783 if (!mRestartingServices.contains(r)) {
8784 mRestartingServices.add(r);
8785 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008786
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008787 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008789 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008790 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008791 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008792 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008793 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008794 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008795 r.shortName, r.restartDelay);
8796
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008797 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008798 }
8799
8800 final void performServiceRestartLocked(ServiceRecord r) {
8801 if (!mRestartingServices.contains(r)) {
8802 return;
8803 }
8804 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8805 }
8806
8807 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8808 if (r.restartDelay == 0) {
8809 return false;
8810 }
8811 r.resetRestartCounter();
8812 mRestartingServices.remove(r);
8813 mHandler.removeCallbacks(r.restarter);
8814 return true;
8815 }
8816
8817 private final boolean bringUpServiceLocked(ServiceRecord r,
8818 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008819 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008820 //r.dump(" ");
8821
Dianne Hackborn36124872009-10-08 16:22:03 -07008822 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008823 sendServiceArgsLocked(r, false);
8824 return true;
8825 }
8826
8827 if (!whileRestarting && r.restartDelay > 0) {
8828 // If waiting for a restart, then do nothing.
8829 return true;
8830 }
8831
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008832 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008833
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008834 // We are now bringing the service up, so no longer in the
8835 // restarting state.
8836 mRestartingServices.remove(r);
8837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 final String appName = r.processName;
8839 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8840 if (app != null && app.thread != null) {
8841 try {
8842 realStartServiceLocked(r, app);
8843 return true;
8844 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008845 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008846 }
8847
8848 // If a dead object exception was thrown -- fall through to
8849 // restart the application.
8850 }
8851
Dianne Hackborn36124872009-10-08 16:22:03 -07008852 // Not running -- get it started, and enqueue this service record
8853 // to be executed when the app comes up.
8854 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8855 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008856 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008857 + r.appInfo.packageName + "/"
8858 + r.appInfo.uid + " for service "
8859 + r.intent.getIntent() + ": process is bad");
8860 bringDownServiceLocked(r, true);
8861 return false;
8862 }
8863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008864 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008865 mPendingServices.add(r);
8866 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008868 return true;
8869 }
8870
8871 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008872 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008873 //r.dump(" ");
8874
8875 // Does it still need to run?
8876 if (!force && r.startRequested) {
8877 return;
8878 }
8879 if (r.connections.size() > 0) {
8880 if (!force) {
8881 // XXX should probably keep a count of the number of auto-create
8882 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008883 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008884 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008885 ArrayList<ConnectionRecord> cr = it.next();
8886 for (int i=0; i<cr.size(); i++) {
8887 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8888 return;
8889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 }
8891 }
8892 }
8893
8894 // Report to all of the connections that the service is no longer
8895 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008896 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008897 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008898 ArrayList<ConnectionRecord> c = it.next();
8899 for (int i=0; i<c.size(); i++) {
8900 try {
8901 c.get(i).conn.connected(r.name, null);
8902 } catch (Exception e) {
8903 Slog.w(TAG, "Failure disconnecting service " + r.name +
8904 " to connection " + c.get(i).conn.asBinder() +
8905 " (in " + c.get(i).binding.client.processName + ")", e);
8906 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008907 }
8908 }
8909 }
8910
8911 // Tell the service that it has been unbound.
8912 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
8913 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
8914 while (it.hasNext()) {
8915 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008916 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008917 + ": hasBound=" + ibr.hasBound);
8918 if (r.app != null && r.app.thread != null && ibr.hasBound) {
8919 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008920 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008921 updateOomAdjLocked(r.app);
8922 ibr.hasBound = false;
8923 r.app.thread.scheduleUnbindService(r,
8924 ibr.intent.getIntent());
8925 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008926 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008927 + r.shortName, e);
8928 serviceDoneExecutingLocked(r, true);
8929 }
8930 }
8931 }
8932 }
8933
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008934 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008935 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008936 System.identityHashCode(r), r.shortName,
8937 (r.app != null) ? r.app.pid : -1);
8938
8939 mServices.remove(r.name);
8940 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008941 r.totalRestartCount = 0;
8942 unscheduleServiceRestartLocked(r);
8943
8944 // Also make sure it is not on the pending list.
8945 int N = mPendingServices.size();
8946 for (int i=0; i<N; i++) {
8947 if (mPendingServices.get(i) == r) {
8948 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008949 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 i--;
8951 N--;
8952 }
8953 }
8954
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008955 r.cancelNotification();
8956 r.isForeground = false;
8957 r.foregroundId = 0;
8958 r.foregroundNoti = null;
8959
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008960 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07008961 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008962 r.pendingStarts.clear();
8963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008964 if (r.app != null) {
8965 synchronized (r.stats.getBatteryStats()) {
8966 r.stats.stopLaunchedLocked();
8967 }
8968 r.app.services.remove(r);
8969 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008971 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008972 mStoppingServices.add(r);
8973 updateOomAdjLocked(r.app);
8974 r.app.thread.scheduleStopService(r);
8975 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008976 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008977 + r.shortName, e);
8978 serviceDoneExecutingLocked(r, true);
8979 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008980 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008981 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008982 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008983 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984 }
8985 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008986 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008987 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008988 }
8989 }
8990
8991 ComponentName startServiceLocked(IApplicationThread caller,
8992 Intent service, String resolvedType,
8993 int callingPid, int callingUid) {
8994 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008995 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 + " type=" + resolvedType + " args=" + service.getExtras());
8997
8998 if (caller != null) {
8999 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9000 if (callerApp == null) {
9001 throw new SecurityException(
9002 "Unable to find app for caller " + caller
9003 + " (pid=" + Binder.getCallingPid()
9004 + ") when starting service " + service);
9005 }
9006 }
9007
9008 ServiceLookupResult res =
9009 retrieveServiceLocked(service, resolvedType,
9010 callingPid, callingUid);
9011 if (res == null) {
9012 return null;
9013 }
9014 if (res.record == null) {
9015 return new ComponentName("!", res.permission != null
9016 ? res.permission : "private to package");
9017 }
9018 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009019 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9020 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009021 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009022 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009023 }
9024 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009025 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009026 r.lastStartId++;
9027 if (r.lastStartId < 1) {
9028 r.lastStartId = 1;
9029 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009030 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9031 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009032 r.lastActivity = SystemClock.uptimeMillis();
9033 synchronized (r.stats.getBatteryStats()) {
9034 r.stats.startRunningLocked();
9035 }
9036 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9037 return new ComponentName("!", "Service process is bad");
9038 }
9039 return r.name;
9040 }
9041 }
9042
9043 public ComponentName startService(IApplicationThread caller, Intent service,
9044 String resolvedType) {
9045 // Refuse possible leaked file descriptors
9046 if (service != null && service.hasFileDescriptors() == true) {
9047 throw new IllegalArgumentException("File descriptors passed in Intent");
9048 }
9049
9050 synchronized(this) {
9051 final int callingPid = Binder.getCallingPid();
9052 final int callingUid = Binder.getCallingUid();
9053 final long origId = Binder.clearCallingIdentity();
9054 ComponentName res = startServiceLocked(caller, service,
9055 resolvedType, callingPid, callingUid);
9056 Binder.restoreCallingIdentity(origId);
9057 return res;
9058 }
9059 }
9060
9061 ComponentName startServiceInPackage(int uid,
9062 Intent service, String resolvedType) {
9063 synchronized(this) {
9064 final long origId = Binder.clearCallingIdentity();
9065 ComponentName res = startServiceLocked(null, service,
9066 resolvedType, -1, uid);
9067 Binder.restoreCallingIdentity(origId);
9068 return res;
9069 }
9070 }
9071
9072 public int stopService(IApplicationThread caller, Intent service,
9073 String resolvedType) {
9074 // Refuse possible leaked file descriptors
9075 if (service != null && service.hasFileDescriptors() == true) {
9076 throw new IllegalArgumentException("File descriptors passed in Intent");
9077 }
9078
9079 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009080 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 + " type=" + resolvedType);
9082
9083 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9084 if (caller != null && callerApp == null) {
9085 throw new SecurityException(
9086 "Unable to find app for caller " + caller
9087 + " (pid=" + Binder.getCallingPid()
9088 + ") when stopping service " + service);
9089 }
9090
9091 // If this service is active, make sure it is stopped.
9092 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9093 if (r != null) {
9094 if (r.record != null) {
9095 synchronized (r.record.stats.getBatteryStats()) {
9096 r.record.stats.stopRunningLocked();
9097 }
9098 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009099 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009100 final long origId = Binder.clearCallingIdentity();
9101 bringDownServiceLocked(r.record, false);
9102 Binder.restoreCallingIdentity(origId);
9103 return 1;
9104 }
9105 return -1;
9106 }
9107 }
9108
9109 return 0;
9110 }
9111
9112 public IBinder peekService(Intent service, String resolvedType) {
9113 // Refuse possible leaked file descriptors
9114 if (service != null && service.hasFileDescriptors() == true) {
9115 throw new IllegalArgumentException("File descriptors passed in Intent");
9116 }
9117
9118 IBinder ret = null;
9119
9120 synchronized(this) {
9121 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9122
9123 if (r != null) {
9124 // r.record is null if findServiceLocked() failed the caller permission check
9125 if (r.record == null) {
9126 throw new SecurityException(
9127 "Permission Denial: Accessing service " + r.record.name
9128 + " from pid=" + Binder.getCallingPid()
9129 + ", uid=" + Binder.getCallingUid()
9130 + " requires " + r.permission);
9131 }
9132 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9133 if (ib != null) {
9134 ret = ib.binder;
9135 }
9136 }
9137 }
9138
9139 return ret;
9140 }
9141
9142 public boolean stopServiceToken(ComponentName className, IBinder token,
9143 int startId) {
9144 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009145 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009146 + " " + token + " startId=" + startId);
9147 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009148 if (r != null) {
9149 if (startId >= 0) {
9150 // Asked to only stop if done with all work. Note that
9151 // to avoid leaks, we will take this as dropping all
9152 // start items up to and including this one.
9153 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9154 if (si != null) {
9155 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009156 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9157 cur.removeUriPermissionsLocked();
9158 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009159 break;
9160 }
9161 }
9162 }
9163
9164 if (r.lastStartId != startId) {
9165 return false;
9166 }
9167
9168 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009169 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009170 + " is last, but have " + r.deliveredStarts.size()
9171 + " remaining args");
9172 }
9173 }
9174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009175 synchronized (r.stats.getBatteryStats()) {
9176 r.stats.stopRunningLocked();
9177 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009178 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 }
9180 final long origId = Binder.clearCallingIdentity();
9181 bringDownServiceLocked(r, false);
9182 Binder.restoreCallingIdentity(origId);
9183 return true;
9184 }
9185 }
9186 return false;
9187 }
9188
9189 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009190 int id, Notification notification, boolean removeNotification) {
9191 final long origId = Binder.clearCallingIdentity();
9192 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009193 synchronized(this) {
9194 ServiceRecord r = findServiceLocked(className, token);
9195 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009196 if (id != 0) {
9197 if (notification == null) {
9198 throw new IllegalArgumentException("null notification");
9199 }
9200 if (r.foregroundId != id) {
9201 r.cancelNotification();
9202 r.foregroundId = id;
9203 }
9204 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9205 r.foregroundNoti = notification;
9206 r.isForeground = true;
9207 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009208 if (r.app != null) {
9209 updateServiceForegroundLocked(r.app, true);
9210 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009211 } else {
9212 if (r.isForeground) {
9213 r.isForeground = false;
9214 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009215 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009216 updateServiceForegroundLocked(r.app, true);
9217 }
9218 }
9219 if (removeNotification) {
9220 r.cancelNotification();
9221 r.foregroundId = 0;
9222 r.foregroundNoti = null;
9223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009224 }
9225 }
9226 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009227 } finally {
9228 Binder.restoreCallingIdentity(origId);
9229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009230 }
9231
9232 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9233 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009234 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009235 if (sr.isForeground) {
9236 anyForeground = true;
9237 break;
9238 }
9239 }
9240 if (anyForeground != proc.foregroundServices) {
9241 proc.foregroundServices = anyForeground;
9242 if (oomAdj) {
9243 updateOomAdjLocked();
9244 }
9245 }
9246 }
9247
9248 public int bindService(IApplicationThread caller, IBinder token,
9249 Intent service, String resolvedType,
9250 IServiceConnection connection, int flags) {
9251 // Refuse possible leaked file descriptors
9252 if (service != null && service.hasFileDescriptors() == true) {
9253 throw new IllegalArgumentException("File descriptors passed in Intent");
9254 }
9255
9256 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009257 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009258 + " type=" + resolvedType + " conn=" + connection.asBinder()
9259 + " flags=0x" + Integer.toHexString(flags));
9260 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9261 if (callerApp == null) {
9262 throw new SecurityException(
9263 "Unable to find app for caller " + caller
9264 + " (pid=" + Binder.getCallingPid()
9265 + ") when binding service " + service);
9266 }
9267
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009268 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009269 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009270 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009272 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 return 0;
9274 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009275 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009276 }
9277
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009278 int clientLabel = 0;
9279 PendingIntent clientIntent = null;
9280
9281 if (callerApp.info.uid == Process.SYSTEM_UID) {
9282 // Hacky kind of thing -- allow system stuff to tell us
9283 // what they are, so we can report this elsewhere for
9284 // others to know why certain services are running.
9285 try {
9286 clientIntent = (PendingIntent)service.getParcelableExtra(
9287 Intent.EXTRA_CLIENT_INTENT);
9288 } catch (RuntimeException e) {
9289 }
9290 if (clientIntent != null) {
9291 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9292 if (clientLabel != 0) {
9293 // There are no useful extras in the intent, trash them.
9294 // System code calling with this stuff just needs to know
9295 // this will happen.
9296 service = service.cloneFilter();
9297 }
9298 }
9299 }
9300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009301 ServiceLookupResult res =
9302 retrieveServiceLocked(service, resolvedType,
9303 Binder.getCallingPid(), Binder.getCallingUid());
9304 if (res == null) {
9305 return 0;
9306 }
9307 if (res.record == null) {
9308 return -1;
9309 }
9310 ServiceRecord s = res.record;
9311
9312 final long origId = Binder.clearCallingIdentity();
9313
9314 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009315 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009316 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009317 }
9318
9319 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9320 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009321 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009322
9323 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009324 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9325 if (clist == null) {
9326 clist = new ArrayList<ConnectionRecord>();
9327 s.connections.put(binder, clist);
9328 }
9329 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 b.connections.add(c);
9331 if (activity != null) {
9332 if (activity.connections == null) {
9333 activity.connections = new HashSet<ConnectionRecord>();
9334 }
9335 activity.connections.add(c);
9336 }
9337 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009338 clist = mServiceConnections.get(binder);
9339 if (clist == null) {
9340 clist = new ArrayList<ConnectionRecord>();
9341 mServiceConnections.put(binder, clist);
9342 }
9343 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009344
9345 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9346 s.lastActivity = SystemClock.uptimeMillis();
9347 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9348 return 0;
9349 }
9350 }
9351
9352 if (s.app != null) {
9353 // This could have made the service more important.
9354 updateOomAdjLocked(s.app);
9355 }
9356
Joe Onorato8a9b2202010-02-26 18:56:32 -08009357 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009358 + ": received=" + b.intent.received
9359 + " apps=" + b.intent.apps.size()
9360 + " doRebind=" + b.intent.doRebind);
9361
9362 if (s.app != null && b.intent.received) {
9363 // Service is already running, so we can immediately
9364 // publish the connection.
9365 try {
9366 c.conn.connected(s.name, b.intent.binder);
9367 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009368 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009369 + " to connection " + c.conn.asBinder()
9370 + " (in " + c.binding.client.processName + ")", e);
9371 }
9372
9373 // If this is the first app connected back to this binding,
9374 // and the service had previously asked to be told when
9375 // rebound, then do so.
9376 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9377 requestServiceBindingLocked(s, b.intent, true);
9378 }
9379 } else if (!b.intent.requested) {
9380 requestServiceBindingLocked(s, b.intent, false);
9381 }
9382
9383 Binder.restoreCallingIdentity(origId);
9384 }
9385
9386 return 1;
9387 }
9388
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009389 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009390 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009391 IBinder binder = c.conn.asBinder();
9392 AppBindRecord b = c.binding;
9393 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009394 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9395 if (clist != null) {
9396 clist.remove(c);
9397 if (clist.size() == 0) {
9398 s.connections.remove(binder);
9399 }
9400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009401 b.connections.remove(c);
9402 if (c.activity != null && c.activity != skipAct) {
9403 if (c.activity.connections != null) {
9404 c.activity.connections.remove(c);
9405 }
9406 }
9407 if (b.client != skipApp) {
9408 b.client.connections.remove(c);
9409 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009410 clist = mServiceConnections.get(binder);
9411 if (clist != null) {
9412 clist.remove(c);
9413 if (clist.size() == 0) {
9414 mServiceConnections.remove(binder);
9415 }
9416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009417
9418 if (b.connections.size() == 0) {
9419 b.intent.apps.remove(b.client);
9420 }
9421
Joe Onorato8a9b2202010-02-26 18:56:32 -08009422 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009423 + ": shouldUnbind=" + b.intent.hasBound);
9424 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9425 && b.intent.hasBound) {
9426 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009427 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009428 updateOomAdjLocked(s.app);
9429 b.intent.hasBound = false;
9430 // Assume the client doesn't want to know about a rebind;
9431 // we will deal with that later if it asks for one.
9432 b.intent.doRebind = false;
9433 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9434 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009435 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009436 serviceDoneExecutingLocked(s, true);
9437 }
9438 }
9439
9440 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9441 bringDownServiceLocked(s, false);
9442 }
9443 }
9444
9445 public boolean unbindService(IServiceConnection connection) {
9446 synchronized (this) {
9447 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009448 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009449 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9450 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009451 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 + connection.asBinder());
9453 return false;
9454 }
9455
9456 final long origId = Binder.clearCallingIdentity();
9457
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009458 while (clist.size() > 0) {
9459 ConnectionRecord r = clist.get(0);
9460 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009462 if (r.binding.service.app != null) {
9463 // This could have made the service less important.
9464 updateOomAdjLocked(r.binding.service.app);
9465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009466 }
9467
9468 Binder.restoreCallingIdentity(origId);
9469 }
9470
9471 return true;
9472 }
9473
9474 public void publishService(IBinder token, Intent intent, IBinder service) {
9475 // Refuse possible leaked file descriptors
9476 if (intent != null && intent.hasFileDescriptors() == true) {
9477 throw new IllegalArgumentException("File descriptors passed in Intent");
9478 }
9479
9480 synchronized(this) {
9481 if (!(token instanceof ServiceRecord)) {
9482 throw new IllegalArgumentException("Invalid service token");
9483 }
9484 ServiceRecord r = (ServiceRecord)token;
9485
9486 final long origId = Binder.clearCallingIdentity();
9487
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009488 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009489 + " " + intent + ": " + service);
9490 if (r != null) {
9491 Intent.FilterComparison filter
9492 = new Intent.FilterComparison(intent);
9493 IntentBindRecord b = r.bindings.get(filter);
9494 if (b != null && !b.received) {
9495 b.binder = service;
9496 b.requested = true;
9497 b.received = true;
9498 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009499 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009500 = r.connections.values().iterator();
9501 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009502 ArrayList<ConnectionRecord> clist = it.next();
9503 for (int i=0; i<clist.size(); i++) {
9504 ConnectionRecord c = clist.get(i);
9505 if (!filter.equals(c.binding.intent.intent)) {
9506 if (DEBUG_SERVICE) Slog.v(
9507 TAG, "Not publishing to: " + c);
9508 if (DEBUG_SERVICE) Slog.v(
9509 TAG, "Bound intent: " + c.binding.intent.intent);
9510 if (DEBUG_SERVICE) Slog.v(
9511 TAG, "Published intent: " + intent);
9512 continue;
9513 }
9514 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9515 try {
9516 c.conn.connected(r.name, service);
9517 } catch (Exception e) {
9518 Slog.w(TAG, "Failure sending service " + r.name +
9519 " to connection " + c.conn.asBinder() +
9520 " (in " + c.binding.client.processName + ")", e);
9521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009522 }
9523 }
9524 }
9525 }
9526
9527 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9528
9529 Binder.restoreCallingIdentity(origId);
9530 }
9531 }
9532 }
9533
9534 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9535 // Refuse possible leaked file descriptors
9536 if (intent != null && intent.hasFileDescriptors() == true) {
9537 throw new IllegalArgumentException("File descriptors passed in Intent");
9538 }
9539
9540 synchronized(this) {
9541 if (!(token instanceof ServiceRecord)) {
9542 throw new IllegalArgumentException("Invalid service token");
9543 }
9544 ServiceRecord r = (ServiceRecord)token;
9545
9546 final long origId = Binder.clearCallingIdentity();
9547
9548 if (r != null) {
9549 Intent.FilterComparison filter
9550 = new Intent.FilterComparison(intent);
9551 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009552 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009553 + " at " + b + ": apps="
9554 + (b != null ? b.apps.size() : 0));
9555 if (b != null) {
9556 if (b.apps.size() > 0) {
9557 // Applications have already bound since the last
9558 // unbind, so just rebind right here.
9559 requestServiceBindingLocked(r, b, true);
9560 } else {
9561 // Note to tell the service the next time there is
9562 // a new client.
9563 b.doRebind = true;
9564 }
9565 }
9566
9567 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9568
9569 Binder.restoreCallingIdentity(origId);
9570 }
9571 }
9572 }
9573
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009574 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009575 synchronized(this) {
9576 if (!(token instanceof ServiceRecord)) {
9577 throw new IllegalArgumentException("Invalid service token");
9578 }
9579 ServiceRecord r = (ServiceRecord)token;
9580 boolean inStopping = mStoppingServices.contains(token);
9581 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009582 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009583 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009584 + " with incorrect token: given " + token
9585 + ", expected " + r);
9586 return;
9587 }
9588
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009589 if (type == 1) {
9590 // This is a call from a service start... take care of
9591 // book-keeping.
9592 r.callStart = true;
9593 switch (res) {
9594 case Service.START_STICKY_COMPATIBILITY:
9595 case Service.START_STICKY: {
9596 // We are done with the associated start arguments.
9597 r.findDeliveredStart(startId, true);
9598 // Don't stop if killed.
9599 r.stopIfKilled = false;
9600 break;
9601 }
9602 case Service.START_NOT_STICKY: {
9603 // We are done with the associated start arguments.
9604 r.findDeliveredStart(startId, true);
9605 if (r.lastStartId == startId) {
9606 // There is no more work, and this service
9607 // doesn't want to hang around if killed.
9608 r.stopIfKilled = true;
9609 }
9610 break;
9611 }
9612 case Service.START_REDELIVER_INTENT: {
9613 // We'll keep this item until they explicitly
9614 // call stop for it, but keep track of the fact
9615 // that it was delivered.
9616 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9617 if (si != null) {
9618 si.deliveryCount = 0;
9619 si.doneExecutingCount++;
9620 // Don't stop if killed.
9621 r.stopIfKilled = true;
9622 }
9623 break;
9624 }
9625 default:
9626 throw new IllegalArgumentException(
9627 "Unknown service start result: " + res);
9628 }
9629 if (res == Service.START_STICKY_COMPATIBILITY) {
9630 r.callStart = false;
9631 }
9632 }
9633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634 final long origId = Binder.clearCallingIdentity();
9635 serviceDoneExecutingLocked(r, inStopping);
9636 Binder.restoreCallingIdentity(origId);
9637 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009638 Slog.w(TAG, "Done executing unknown service from pid "
9639 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009640 }
9641 }
9642 }
9643
9644 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009645 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9646 + ": nesting=" + r.executeNesting
9647 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009648 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009649 r.executeNesting--;
9650 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009651 if (DEBUG_SERVICE) Slog.v(TAG,
9652 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009653 r.app.executingServices.remove(r);
9654 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009655 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9656 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009657 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9658 }
9659 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009660 if (DEBUG_SERVICE) Slog.v(TAG,
9661 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009662 mStoppingServices.remove(r);
9663 }
9664 updateOomAdjLocked(r.app);
9665 }
9666 }
9667
9668 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009669 String anrMessage = null;
9670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 synchronized(this) {
9672 if (proc.executingServices.size() == 0 || proc.thread == null) {
9673 return;
9674 }
9675 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9676 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9677 ServiceRecord timeout = null;
9678 long nextTime = 0;
9679 while (it.hasNext()) {
9680 ServiceRecord sr = it.next();
9681 if (sr.executingStart < maxTime) {
9682 timeout = sr;
9683 break;
9684 }
9685 if (sr.executingStart > nextTime) {
9686 nextTime = sr.executingStart;
9687 }
9688 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009689 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009690 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009691 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009692 } else {
9693 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9694 msg.obj = proc;
9695 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9696 }
9697 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009698
9699 if (anrMessage != null) {
9700 appNotResponding(proc, null, null, anrMessage);
9701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 }
9703
9704 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009705 // BACKUP AND RESTORE
9706 // =========================================================
9707
9708 // Cause the target app to be launched if necessary and its backup agent
9709 // instantiated. The backup agent will invoke backupAgentCreated() on the
9710 // activity manager to announce its creation.
9711 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009712 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009713 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9714
9715 synchronized(this) {
9716 // !!! TODO: currently no check here that we're already bound
9717 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9718 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9719 synchronized (stats) {
9720 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9721 }
9722
9723 BackupRecord r = new BackupRecord(ss, app, backupMode);
9724 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9725 // startProcessLocked() returns existing proc's record if it's already running
9726 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009727 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009728 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009729 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009730 return false;
9731 }
9732
9733 r.app = proc;
9734 mBackupTarget = r;
9735 mBackupAppName = app.packageName;
9736
Christopher Tate6fa95972009-06-05 18:43:55 -07009737 // Try not to kill the process during backup
9738 updateOomAdjLocked(proc);
9739
Christopher Tate181fafa2009-05-14 11:12:14 -07009740 // If the process is already attached, schedule the creation of the backup agent now.
9741 // If it is not yet live, this will be done when it attaches to the framework.
9742 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009743 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009744 try {
9745 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9746 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009747 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009748 }
9749 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009750 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009751 }
9752 // Invariants: at this point, the target app process exists and the application
9753 // is either already running or in the process of coming up. mBackupTarget and
9754 // mBackupAppName describe the app, so that when it binds back to the AM we
9755 // know that it's scheduled for a backup-agent operation.
9756 }
9757
9758 return true;
9759 }
9760
9761 // A backup agent has just come up
9762 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009763 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009764 + " = " + agent);
9765
9766 synchronized(this) {
9767 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009768 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009769 return;
9770 }
Dianne Hackborn06740692010-09-22 22:46:21 -07009771 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009772
Dianne Hackborn06740692010-09-22 22:46:21 -07009773 long oldIdent = Binder.clearCallingIdentity();
9774 try {
9775 IBackupManager bm = IBackupManager.Stub.asInterface(
9776 ServiceManager.getService(Context.BACKUP_SERVICE));
9777 bm.agentConnected(agentPackageName, agent);
9778 } catch (RemoteException e) {
9779 // can't happen; the backup manager service is local
9780 } catch (Exception e) {
9781 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
9782 e.printStackTrace();
9783 } finally {
9784 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009785 }
9786 }
9787
9788 // done with this agent
9789 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009790 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009791 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009792 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009793 return;
9794 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009795
9796 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009797 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009798 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009799 return;
9800 }
9801
Christopher Tate181fafa2009-05-14 11:12:14 -07009802 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009803 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009804 return;
9805 }
9806
Christopher Tate6fa95972009-06-05 18:43:55 -07009807 ProcessRecord proc = mBackupTarget.app;
9808 mBackupTarget = null;
9809 mBackupAppName = null;
9810
9811 // Not backing this app up any more; reset its OOM adjustment
9812 updateOomAdjLocked(proc);
9813
Christopher Tatec7b31e32009-06-10 15:49:30 -07009814 // If the app crashed during backup, 'thread' will be null here
9815 if (proc.thread != null) {
9816 try {
9817 proc.thread.scheduleDestroyBackupAgent(appInfo);
9818 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009819 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009820 e.printStackTrace();
9821 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009822 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009823 }
9824 }
9825 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009826 // BROADCASTS
9827 // =========================================================
9828
Josh Bartel7f208742010-02-25 11:01:44 -06009829 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 List cur) {
9831 final ContentResolver resolver = mContext.getContentResolver();
9832 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9833 if (list == null) {
9834 return cur;
9835 }
9836 int N = list.size();
9837 for (int i=0; i<N; i++) {
9838 Intent intent = list.get(i);
9839 if (filter.match(resolver, intent, true, TAG) >= 0) {
9840 if (cur == null) {
9841 cur = new ArrayList<Intent>();
9842 }
9843 cur.add(intent);
9844 }
9845 }
9846 return cur;
9847 }
9848
9849 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009850 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009851 + mBroadcastsScheduled);
9852
9853 if (mBroadcastsScheduled) {
9854 return;
9855 }
9856 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9857 mBroadcastsScheduled = true;
9858 }
9859
9860 public Intent registerReceiver(IApplicationThread caller,
9861 IIntentReceiver receiver, IntentFilter filter, String permission) {
9862 synchronized(this) {
9863 ProcessRecord callerApp = null;
9864 if (caller != null) {
9865 callerApp = getRecordForAppLocked(caller);
9866 if (callerApp == null) {
9867 throw new SecurityException(
9868 "Unable to find app for caller " + caller
9869 + " (pid=" + Binder.getCallingPid()
9870 + ") when registering receiver " + receiver);
9871 }
9872 }
9873
9874 List allSticky = null;
9875
9876 // Look for any matching sticky broadcasts...
9877 Iterator actions = filter.actionsIterator();
9878 if (actions != null) {
9879 while (actions.hasNext()) {
9880 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009881 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009882 }
9883 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009884 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009885 }
9886
9887 // The first sticky in the list is returned directly back to
9888 // the client.
9889 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9890
Joe Onorato8a9b2202010-02-26 18:56:32 -08009891 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 + ": " + sticky);
9893
9894 if (receiver == null) {
9895 return sticky;
9896 }
9897
9898 ReceiverList rl
9899 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9900 if (rl == null) {
9901 rl = new ReceiverList(this, callerApp,
9902 Binder.getCallingPid(),
9903 Binder.getCallingUid(), receiver);
9904 if (rl.app != null) {
9905 rl.app.receivers.add(rl);
9906 } else {
9907 try {
9908 receiver.asBinder().linkToDeath(rl, 0);
9909 } catch (RemoteException e) {
9910 return sticky;
9911 }
9912 rl.linkedToDeath = true;
9913 }
9914 mRegisteredReceivers.put(receiver.asBinder(), rl);
9915 }
9916 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
9917 rl.add(bf);
9918 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009919 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009920 }
9921 mReceiverResolver.addFilter(bf);
9922
9923 // Enqueue broadcasts for all existing stickies that match
9924 // this filter.
9925 if (allSticky != null) {
9926 ArrayList receivers = new ArrayList();
9927 receivers.add(bf);
9928
9929 int N = allSticky.size();
9930 for (int i=0; i<N; i++) {
9931 Intent intent = (Intent)allSticky.get(i);
9932 BroadcastRecord r = new BroadcastRecord(intent, null,
9933 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -08009934 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009935 if (mParallelBroadcasts.size() == 0) {
9936 scheduleBroadcastsLocked();
9937 }
9938 mParallelBroadcasts.add(r);
9939 }
9940 }
9941
9942 return sticky;
9943 }
9944 }
9945
9946 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009947 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009948
9949 boolean doNext = false;
9950
9951 synchronized(this) {
9952 ReceiverList rl
9953 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9954 if (rl != null) {
9955 if (rl.curBroadcast != null) {
9956 BroadcastRecord r = rl.curBroadcast;
9957 doNext = finishReceiverLocked(
9958 receiver.asBinder(), r.resultCode, r.resultData,
9959 r.resultExtras, r.resultAbort, true);
9960 }
9961
9962 if (rl.app != null) {
9963 rl.app.receivers.remove(rl);
9964 }
9965 removeReceiverLocked(rl);
9966 if (rl.linkedToDeath) {
9967 rl.linkedToDeath = false;
9968 rl.receiver.asBinder().unlinkToDeath(rl, 0);
9969 }
9970 }
9971 }
9972
9973 if (!doNext) {
9974 return;
9975 }
9976
9977 final long origId = Binder.clearCallingIdentity();
9978 processNextBroadcast(false);
9979 trimApplications();
9980 Binder.restoreCallingIdentity(origId);
9981 }
9982
9983 void removeReceiverLocked(ReceiverList rl) {
9984 mRegisteredReceivers.remove(rl.receiver.asBinder());
9985 int N = rl.size();
9986 for (int i=0; i<N; i++) {
9987 mReceiverResolver.removeFilter(rl.get(i));
9988 }
9989 }
9990
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07009991 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
9992 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
9993 ProcessRecord r = mLruProcesses.get(i);
9994 if (r.thread != null) {
9995 try {
9996 r.thread.dispatchPackageBroadcast(cmd, packages);
9997 } catch (RemoteException ex) {
9998 }
9999 }
10000 }
10001 }
10002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010003 private final int broadcastIntentLocked(ProcessRecord callerApp,
10004 String callerPackage, Intent intent, String resolvedType,
10005 IIntentReceiver resultTo, int resultCode, String resultData,
10006 Bundle map, String requiredPermission,
10007 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10008 intent = new Intent(intent);
10009
Joe Onorato8a9b2202010-02-26 18:56:32 -080010010 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010011 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10012 + " ordered=" + ordered);
10013 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010014 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010015 }
10016
10017 // Handle special intents: if this broadcast is from the package
10018 // manager about a package being removed, we need to remove all of
10019 // its activities from the history stack.
10020 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10021 intent.getAction());
10022 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10023 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010024 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025 || uidRemoved) {
10026 if (checkComponentPermission(
10027 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10028 callingPid, callingUid, -1)
10029 == PackageManager.PERMISSION_GRANTED) {
10030 if (uidRemoved) {
10031 final Bundle intentExtras = intent.getExtras();
10032 final int uid = intentExtras != null
10033 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10034 if (uid >= 0) {
10035 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10036 synchronized (bs) {
10037 bs.removeUidStatsLocked(uid);
10038 }
10039 }
10040 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010041 // If resources are unvailble just force stop all
10042 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010043 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010044 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10045 if (list != null && (list.length > 0)) {
10046 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010047 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010048 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010049 sendPackageBroadcastLocked(
10050 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010051 }
10052 } else {
10053 Uri data = intent.getData();
10054 String ssp;
10055 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10056 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10057 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010058 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010059 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010060 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10061 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10062 new String[] {ssp});
10063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 }
10065 }
10066 }
10067 } else {
10068 String msg = "Permission Denial: " + intent.getAction()
10069 + " broadcast from " + callerPackage + " (pid=" + callingPid
10070 + ", uid=" + callingUid + ")"
10071 + " requires "
10072 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010073 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010074 throw new SecurityException(msg);
10075 }
10076 }
10077
10078 /*
10079 * If this is the time zone changed action, queue up a message that will reset the timezone
10080 * of all currently running processes. This message will get queued up before the broadcast
10081 * happens.
10082 */
10083 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10084 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10085 }
10086
Dianne Hackborn854060af2009-07-09 18:14:31 -070010087 /*
10088 * Prevent non-system code (defined here to be non-persistent
10089 * processes) from sending protected broadcasts.
10090 */
10091 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10092 || callingUid == Process.SHELL_UID || callingUid == 0) {
10093 // Always okay.
10094 } else if (callerApp == null || !callerApp.persistent) {
10095 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010096 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010097 intent.getAction())) {
10098 String msg = "Permission Denial: not allowed to send broadcast "
10099 + intent.getAction() + " from pid="
10100 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010101 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010102 throw new SecurityException(msg);
10103 }
10104 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010105 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010106 return BROADCAST_SUCCESS;
10107 }
10108 }
10109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010110 // Add to the sticky list if requested.
10111 if (sticky) {
10112 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10113 callingPid, callingUid)
10114 != PackageManager.PERMISSION_GRANTED) {
10115 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10116 + callingPid + ", uid=" + callingUid
10117 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010118 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010119 throw new SecurityException(msg);
10120 }
10121 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010122 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010123 + " and enforce permission " + requiredPermission);
10124 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10125 }
10126 if (intent.getComponent() != null) {
10127 throw new SecurityException(
10128 "Sticky broadcasts can't target a specific component");
10129 }
10130 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10131 if (list == null) {
10132 list = new ArrayList<Intent>();
10133 mStickyBroadcasts.put(intent.getAction(), list);
10134 }
10135 int N = list.size();
10136 int i;
10137 for (i=0; i<N; i++) {
10138 if (intent.filterEquals(list.get(i))) {
10139 // This sticky already exists, replace it.
10140 list.set(i, new Intent(intent));
10141 break;
10142 }
10143 }
10144 if (i >= N) {
10145 list.add(new Intent(intent));
10146 }
10147 }
10148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010149 // Figure out who all will receive this broadcast.
10150 List receivers = null;
10151 List<BroadcastFilter> registeredReceivers = null;
10152 try {
10153 if (intent.getComponent() != null) {
10154 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010155 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010156 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010157 if (ai != null) {
10158 receivers = new ArrayList();
10159 ResolveInfo ri = new ResolveInfo();
10160 ri.activityInfo = ai;
10161 receivers.add(ri);
10162 }
10163 } else {
10164 // Need to resolve the intent to interested receivers...
10165 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10166 == 0) {
10167 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010168 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010169 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010170 }
Mihai Preda074edef2009-05-18 17:13:31 +020010171 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010172 }
10173 } catch (RemoteException ex) {
10174 // pm is in same process, this will never happen.
10175 }
10176
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010177 final boolean replacePending =
10178 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10179
Joe Onorato8a9b2202010-02-26 18:56:32 -080010180 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010181 + " replacePending=" + replacePending);
10182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010183 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10184 if (!ordered && NR > 0) {
10185 // If we are not serializing this broadcast, then send the
10186 // registered receivers separately so they don't wait for the
10187 // components to be launched.
10188 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10189 callerPackage, callingPid, callingUid, requiredPermission,
10190 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010191 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010192 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010193 TAG, "Enqueueing parallel broadcast " + r
10194 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010195 boolean replaced = false;
10196 if (replacePending) {
10197 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10198 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010199 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010200 "***** DROPPING PARALLEL: " + intent);
10201 mParallelBroadcasts.set(i, r);
10202 replaced = true;
10203 break;
10204 }
10205 }
10206 }
10207 if (!replaced) {
10208 mParallelBroadcasts.add(r);
10209 scheduleBroadcastsLocked();
10210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010211 registeredReceivers = null;
10212 NR = 0;
10213 }
10214
10215 // Merge into one list.
10216 int ir = 0;
10217 if (receivers != null) {
10218 // A special case for PACKAGE_ADDED: do not allow the package
10219 // being added to see this broadcast. This prevents them from
10220 // using this as a back door to get run as soon as they are
10221 // installed. Maybe in the future we want to have a special install
10222 // broadcast or such for apps, but we'd like to deliberately make
10223 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010224 String skipPackages[] = null;
10225 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10226 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10227 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10228 Uri data = intent.getData();
10229 if (data != null) {
10230 String pkgName = data.getSchemeSpecificPart();
10231 if (pkgName != null) {
10232 skipPackages = new String[] { pkgName };
10233 }
10234 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010235 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010236 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010237 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010238 if (skipPackages != null && (skipPackages.length > 0)) {
10239 for (String skipPackage : skipPackages) {
10240 if (skipPackage != null) {
10241 int NT = receivers.size();
10242 for (int it=0; it<NT; it++) {
10243 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10244 if (curt.activityInfo.packageName.equals(skipPackage)) {
10245 receivers.remove(it);
10246 it--;
10247 NT--;
10248 }
10249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010250 }
10251 }
10252 }
10253
10254 int NT = receivers != null ? receivers.size() : 0;
10255 int it = 0;
10256 ResolveInfo curt = null;
10257 BroadcastFilter curr = null;
10258 while (it < NT && ir < NR) {
10259 if (curt == null) {
10260 curt = (ResolveInfo)receivers.get(it);
10261 }
10262 if (curr == null) {
10263 curr = registeredReceivers.get(ir);
10264 }
10265 if (curr.getPriority() >= curt.priority) {
10266 // Insert this broadcast record into the final list.
10267 receivers.add(it, curr);
10268 ir++;
10269 curr = null;
10270 it++;
10271 NT++;
10272 } else {
10273 // Skip to the next ResolveInfo in the final list.
10274 it++;
10275 curt = null;
10276 }
10277 }
10278 }
10279 while (ir < NR) {
10280 if (receivers == null) {
10281 receivers = new ArrayList();
10282 }
10283 receivers.add(registeredReceivers.get(ir));
10284 ir++;
10285 }
10286
10287 if ((receivers != null && receivers.size() > 0)
10288 || resultTo != null) {
10289 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10290 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010291 receivers, resultTo, resultCode, resultData, map, ordered,
10292 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010293 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010294 TAG, "Enqueueing ordered broadcast " + r
10295 + ": prev had " + mOrderedBroadcasts.size());
10296 if (DEBUG_BROADCAST) {
10297 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010298 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010300 boolean replaced = false;
10301 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010302 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010303 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010304 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010305 "***** DROPPING ORDERED: " + intent);
10306 mOrderedBroadcasts.set(i, r);
10307 replaced = true;
10308 break;
10309 }
10310 }
10311 }
10312 if (!replaced) {
10313 mOrderedBroadcasts.add(r);
10314 scheduleBroadcastsLocked();
10315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010316 }
10317
10318 return BROADCAST_SUCCESS;
10319 }
10320
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010321 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010322 // Refuse possible leaked file descriptors
10323 if (intent != null && intent.hasFileDescriptors() == true) {
10324 throw new IllegalArgumentException("File descriptors passed in Intent");
10325 }
10326
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010327 int flags = intent.getFlags();
10328
10329 if (!mProcessesReady) {
10330 // if the caller really truly claims to know what they're doing, go
10331 // ahead and allow the broadcast without launching any receivers
10332 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10333 intent = new Intent(intent);
10334 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10335 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10336 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10337 + " before boot completion");
10338 throw new IllegalStateException("Cannot broadcast before boot completed");
10339 }
10340 }
10341
10342 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10343 throw new IllegalArgumentException(
10344 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10345 }
10346
10347 return intent;
10348 }
10349
10350 public final int broadcastIntent(IApplicationThread caller,
10351 Intent intent, String resolvedType, IIntentReceiver resultTo,
10352 int resultCode, String resultData, Bundle map,
10353 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010355 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10358 final int callingPid = Binder.getCallingPid();
10359 final int callingUid = Binder.getCallingUid();
10360 final long origId = Binder.clearCallingIdentity();
10361 int res = broadcastIntentLocked(callerApp,
10362 callerApp != null ? callerApp.info.packageName : null,
10363 intent, resolvedType, resultTo,
10364 resultCode, resultData, map, requiredPermission, serialized,
10365 sticky, callingPid, callingUid);
10366 Binder.restoreCallingIdentity(origId);
10367 return res;
10368 }
10369 }
10370
10371 int broadcastIntentInPackage(String packageName, int uid,
10372 Intent intent, String resolvedType, IIntentReceiver resultTo,
10373 int resultCode, String resultData, Bundle map,
10374 String requiredPermission, boolean serialized, boolean sticky) {
10375 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010376 intent = verifyBroadcastLocked(intent);
10377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 final long origId = Binder.clearCallingIdentity();
10379 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10380 resultTo, resultCode, resultData, map, requiredPermission,
10381 serialized, sticky, -1, uid);
10382 Binder.restoreCallingIdentity(origId);
10383 return res;
10384 }
10385 }
10386
10387 public final void unbroadcastIntent(IApplicationThread caller,
10388 Intent intent) {
10389 // Refuse possible leaked file descriptors
10390 if (intent != null && intent.hasFileDescriptors() == true) {
10391 throw new IllegalArgumentException("File descriptors passed in Intent");
10392 }
10393
10394 synchronized(this) {
10395 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10396 != PackageManager.PERMISSION_GRANTED) {
10397 String msg = "Permission Denial: unbroadcastIntent() from pid="
10398 + Binder.getCallingPid()
10399 + ", uid=" + Binder.getCallingUid()
10400 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010401 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 throw new SecurityException(msg);
10403 }
10404 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10405 if (list != null) {
10406 int N = list.size();
10407 int i;
10408 for (i=0; i<N; i++) {
10409 if (intent.filterEquals(list.get(i))) {
10410 list.remove(i);
10411 break;
10412 }
10413 }
10414 }
10415 }
10416 }
10417
10418 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10419 String resultData, Bundle resultExtras, boolean resultAbort,
10420 boolean explicit) {
10421 if (mOrderedBroadcasts.size() == 0) {
10422 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010423 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010424 }
10425 return false;
10426 }
10427 BroadcastRecord r = mOrderedBroadcasts.get(0);
10428 if (r.receiver == null) {
10429 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010430 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010431 }
10432 return false;
10433 }
10434 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010435 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010436 return false;
10437 }
10438 int state = r.state;
10439 r.state = r.IDLE;
10440 if (state == r.IDLE) {
10441 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010442 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 }
10444 }
10445 r.receiver = null;
10446 r.intent.setComponent(null);
10447 if (r.curApp != null) {
10448 r.curApp.curReceiver = null;
10449 }
10450 if (r.curFilter != null) {
10451 r.curFilter.receiverList.curBroadcast = null;
10452 }
10453 r.curFilter = null;
10454 r.curApp = null;
10455 r.curComponent = null;
10456 r.curReceiver = null;
10457 mPendingBroadcast = null;
10458
10459 r.resultCode = resultCode;
10460 r.resultData = resultData;
10461 r.resultExtras = resultExtras;
10462 r.resultAbort = resultAbort;
10463
10464 // We will process the next receiver right now if this is finishing
10465 // an app receiver (which is always asynchronous) or after we have
10466 // come back from calling a receiver.
10467 return state == BroadcastRecord.APP_RECEIVE
10468 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10469 }
10470
10471 public void finishReceiver(IBinder who, int resultCode, String resultData,
10472 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010473 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474
10475 // Refuse possible leaked file descriptors
10476 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10477 throw new IllegalArgumentException("File descriptors passed in Bundle");
10478 }
10479
10480 boolean doNext;
10481
10482 final long origId = Binder.clearCallingIdentity();
10483
10484 synchronized(this) {
10485 doNext = finishReceiverLocked(
10486 who, resultCode, resultData, resultExtras, resultAbort, true);
10487 }
10488
10489 if (doNext) {
10490 processNextBroadcast(false);
10491 }
10492 trimApplications();
10493
10494 Binder.restoreCallingIdentity(origId);
10495 }
10496
10497 private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
10498 if (r.nextReceiver > 0) {
10499 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10500 if (curReceiver instanceof BroadcastFilter) {
10501 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010502 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010503 System.identityHashCode(r),
10504 r.intent.getAction(),
10505 r.nextReceiver - 1,
10506 System.identityHashCode(bf));
10507 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010508 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010509 System.identityHashCode(r),
10510 r.intent.getAction(),
10511 r.nextReceiver - 1,
10512 ((ResolveInfo)curReceiver).toString());
10513 }
10514 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010515 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010516 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010517 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518 System.identityHashCode(r),
10519 r.intent.getAction(),
10520 r.nextReceiver,
10521 "NONE");
10522 }
10523 }
10524
10525 private final void broadcastTimeout() {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010526 ProcessRecord app = null;
10527 String anrMessage = null;
10528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010529 synchronized (this) {
10530 if (mOrderedBroadcasts.size() == 0) {
10531 return;
10532 }
10533 long now = SystemClock.uptimeMillis();
10534 BroadcastRecord r = mOrderedBroadcasts.get(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010535 if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010536 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010537 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010538 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010540 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010541 return;
10542 }
10543
Joe Onorato8a9b2202010-02-26 18:56:32 -080010544 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010545 r.receiverTime = now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 r.anrCount++;
10547
10548 // Current receiver has passed its expiration date.
10549 if (r.nextReceiver <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010550 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010551 return;
10552 }
10553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010554 Object curReceiver = r.receivers.get(r.nextReceiver-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010555 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010556 logBroadcastReceiverDiscard(r);
10557 if (curReceiver instanceof BroadcastFilter) {
10558 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10559 if (bf.receiverList.pid != 0
10560 && bf.receiverList.pid != MY_PID) {
10561 synchronized (this.mPidsSelfLocked) {
10562 app = this.mPidsSelfLocked.get(
10563 bf.receiverList.pid);
10564 }
10565 }
10566 } else {
10567 app = r.curApp;
10568 }
10569
10570 if (app != null) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010571 anrMessage = "Broadcast of " + r.intent.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010572 }
10573
10574 if (mPendingBroadcast == r) {
10575 mPendingBroadcast = null;
10576 }
10577
10578 // Move on to the next receiver.
10579 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10580 r.resultExtras, r.resultAbort, true);
10581 scheduleBroadcastsLocked();
10582 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010583
10584 if (anrMessage != null) {
10585 appNotResponding(app, null, null, anrMessage);
10586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010587 }
10588
10589 private final void processCurBroadcastLocked(BroadcastRecord r,
10590 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010591 if (DEBUG_BROADCAST) Slog.v(TAG,
10592 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010593 if (app.thread == null) {
10594 throw new RemoteException();
10595 }
10596 r.receiver = app.thread.asBinder();
10597 r.curApp = app;
10598 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010599 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010600
10601 // Tell the application to launch this receiver.
10602 r.intent.setComponent(r.curComponent);
10603
10604 boolean started = false;
10605 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010606 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010607 "Delivering to component " + r.curComponent
10608 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010609 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010610 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10611 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010612 if (DEBUG_BROADCAST) Slog.v(TAG,
10613 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 started = true;
10615 } finally {
10616 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010617 if (DEBUG_BROADCAST) Slog.v(TAG,
10618 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010619 r.receiver = null;
10620 r.curApp = null;
10621 app.curReceiver = null;
10622 }
10623 }
10624
10625 }
10626
10627 static void performReceive(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010628 Intent intent, int resultCode, String data, Bundle extras,
10629 boolean ordered, boolean sticky) throws RemoteException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010630 if (app != null && app.thread != null) {
10631 // If we have an app thread, do the call through that so it is
10632 // correctly ordered with other one-way calls.
10633 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010634 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010636 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010637 }
10638 }
10639
10640 private final void deliverToRegisteredReceiver(BroadcastRecord r,
10641 BroadcastFilter filter, boolean ordered) {
10642 boolean skip = false;
10643 if (filter.requiredPermission != null) {
10644 int perm = checkComponentPermission(filter.requiredPermission,
10645 r.callingPid, r.callingUid, -1);
10646 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010647 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648 + r.intent.toString()
10649 + " from " + r.callerPackage + " (pid="
10650 + r.callingPid + ", uid=" + r.callingUid + ")"
10651 + " requires " + filter.requiredPermission
10652 + " due to registered receiver " + filter);
10653 skip = true;
10654 }
10655 }
10656 if (r.requiredPermission != null) {
10657 int perm = checkComponentPermission(r.requiredPermission,
10658 filter.receiverList.pid, filter.receiverList.uid, -1);
10659 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010660 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010661 + r.intent.toString()
10662 + " to " + filter.receiverList.app
10663 + " (pid=" + filter.receiverList.pid
10664 + ", uid=" + filter.receiverList.uid + ")"
10665 + " requires " + r.requiredPermission
10666 + " due to sender " + r.callerPackage
10667 + " (uid " + r.callingUid + ")");
10668 skip = true;
10669 }
10670 }
10671
10672 if (!skip) {
10673 // If this is not being sent as an ordered broadcast, then we
10674 // don't want to touch the fields that keep track of the current
10675 // state of ordered broadcasts.
10676 if (ordered) {
10677 r.receiver = filter.receiverList.receiver.asBinder();
10678 r.curFilter = filter;
10679 filter.receiverList.curBroadcast = r;
10680 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010681 if (filter.receiverList.app != null) {
10682 // Bump hosting application to no longer be in background
10683 // scheduling class. Note that we can't do that if there
10684 // isn't an app... but we can only be in that case for
10685 // things that directly call the IActivityManager API, which
10686 // are already core system stuff so don't matter for this.
10687 r.curApp = filter.receiverList.app;
10688 filter.receiverList.app.curReceiver = r;
10689 updateOomAdjLocked();
10690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 }
10692 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010693 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010694 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010695 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010696 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010697 }
10698 performReceive(filter.receiverList.app, filter.receiverList.receiver,
10699 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010700 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010701 if (ordered) {
10702 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10703 }
10704 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010705 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010706 if (ordered) {
10707 r.receiver = null;
10708 r.curFilter = null;
10709 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010710 if (filter.receiverList.app != null) {
10711 filter.receiverList.app.curReceiver = null;
10712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010713 }
10714 }
10715 }
10716 }
10717
Dianne Hackborn12527f92009-11-11 17:39:50 -080010718 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10719 if (r.callingUid < 0) {
10720 // This was from a registerReceiver() call; ignore it.
10721 return;
10722 }
10723 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10724 MAX_BROADCAST_HISTORY-1);
10725 r.finishTime = SystemClock.uptimeMillis();
10726 mBroadcastHistory[0] = r;
10727 }
10728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010729 private final void processNextBroadcast(boolean fromMsg) {
10730 synchronized(this) {
10731 BroadcastRecord r;
10732
Joe Onorato8a9b2202010-02-26 18:56:32 -080010733 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010734 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010735 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010736
10737 updateCpuStats();
10738
10739 if (fromMsg) {
10740 mBroadcastsScheduled = false;
10741 }
10742
10743 // First, deliver any non-serialized broadcasts right away.
10744 while (mParallelBroadcasts.size() > 0) {
10745 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010746 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010747 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010748 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010749 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010750 for (int i=0; i<N; i++) {
10751 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010752 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010753 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010754 + target + ": " + r);
10755 deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
10756 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010757 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010758 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010759 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010760 }
10761
10762 // Now take care of the next serialized one...
10763
10764 // If we are waiting for a process to come up to handle the next
10765 // broadcast, then do nothing at this point. Just in case, we
10766 // check that the process we're waiting for still exists.
10767 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010768 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010769 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010770 + mPendingBroadcast.curApp);
10771 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772
10773 boolean isDead;
10774 synchronized (mPidsSelfLocked) {
10775 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10776 }
10777 if (!isDead) {
10778 // It's still alive, so keep waiting
10779 return;
10780 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010781 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010783 mPendingBroadcast.state = BroadcastRecord.IDLE;
10784 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785 mPendingBroadcast = null;
10786 }
10787 }
10788
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010789 boolean looped = false;
10790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010791 do {
10792 if (mOrderedBroadcasts.size() == 0) {
10793 // No more broadcasts pending, so all done!
10794 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010795 if (looped) {
10796 // If we had finished the last ordered broadcast, then
10797 // make sure all processes have correct oom and sched
10798 // adjustments.
10799 updateOomAdjLocked();
10800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 return;
10802 }
10803 r = mOrderedBroadcasts.get(0);
10804 boolean forceReceive = false;
10805
10806 // Ensure that even if something goes awry with the timeout
10807 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010808 // and continue to make progress.
10809 //
10810 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
10811 // receivers don't get executed with with timeouts. They're intended for
10812 // one time heavy lifting after system upgrades and can take
10813 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010814 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010815 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010816 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 if ((numReceivers > 0) &&
10818 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010819 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010820 + " now=" + now
10821 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010822 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010823 + " intent=" + r.intent
10824 + " numReceivers=" + numReceivers
10825 + " nextReceiver=" + r.nextReceiver
10826 + " state=" + r.state);
10827 broadcastTimeout(); // forcibly finish this broadcast
10828 forceReceive = true;
10829 r.state = BroadcastRecord.IDLE;
10830 }
10831 }
10832
10833 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010834 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010835 "processNextBroadcast() called when not idle (state="
10836 + r.state + ")");
10837 return;
10838 }
10839
10840 if (r.receivers == null || r.nextReceiver >= numReceivers
10841 || r.resultAbort || forceReceive) {
10842 // No more receivers for this broadcast! Send the final
10843 // result if requested...
10844 if (r.resultTo != null) {
10845 try {
10846 if (DEBUG_BROADCAST) {
10847 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010848 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010849 + " seq=" + seq + " app=" + r.callerApp);
10850 }
10851 performReceive(r.callerApp, r.resultTo,
10852 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010853 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010854 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010855 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010856 }
10857 }
10858
Joe Onorato8a9b2202010-02-26 18:56:32 -080010859 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010860 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10861
Joe Onorato8a9b2202010-02-26 18:56:32 -080010862 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010863 + r);
10864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010865 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010866 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010867 mOrderedBroadcasts.remove(0);
10868 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010869 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010870 continue;
10871 }
10872 } while (r == null);
10873
10874 // Get the next receiver...
10875 int recIdx = r.nextReceiver++;
10876
10877 // Keep track of when this receiver started, and make sure there
10878 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080010879 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010880 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080010881 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882
Joe Onorato8a9b2202010-02-26 18:56:32 -080010883 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010884 + r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010885 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010886 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at "
Dianne Hackborn12527f92009-11-11 17:39:50 -080010887 + (r.receiverTime + BROADCAST_TIMEOUT));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010888 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010889 mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010890 }
10891
10892 Object nextReceiver = r.receivers.get(recIdx);
10893 if (nextReceiver instanceof BroadcastFilter) {
10894 // Simple case: this is a registered receiver who gets
10895 // a direct call.
10896 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010897 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010898 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010899 + filter + ": " + r);
10900 deliverToRegisteredReceiver(r, filter, r.ordered);
10901 if (r.receiver == null || !r.ordered) {
10902 // The receiver has already finished, so schedule to
10903 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010904 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
10905 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 r.state = BroadcastRecord.IDLE;
10907 scheduleBroadcastsLocked();
10908 }
10909 return;
10910 }
10911
10912 // Hard case: need to instantiate the receiver, possibly
10913 // starting its application process to host it.
10914
10915 ResolveInfo info =
10916 (ResolveInfo)nextReceiver;
10917
10918 boolean skip = false;
10919 int perm = checkComponentPermission(info.activityInfo.permission,
10920 r.callingPid, r.callingUid,
10921 info.activityInfo.exported
10922 ? -1 : info.activityInfo.applicationInfo.uid);
10923 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010924 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010925 + r.intent.toString()
10926 + " from " + r.callerPackage + " (pid=" + r.callingPid
10927 + ", uid=" + r.callingUid + ")"
10928 + " requires " + info.activityInfo.permission
10929 + " due to receiver " + info.activityInfo.packageName
10930 + "/" + info.activityInfo.name);
10931 skip = true;
10932 }
10933 if (r.callingUid != Process.SYSTEM_UID &&
10934 r.requiredPermission != null) {
10935 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010936 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010937 checkPermission(r.requiredPermission,
10938 info.activityInfo.applicationInfo.packageName);
10939 } catch (RemoteException e) {
10940 perm = PackageManager.PERMISSION_DENIED;
10941 }
10942 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010943 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010944 + r.intent + " to "
10945 + info.activityInfo.applicationInfo.packageName
10946 + " requires " + r.requiredPermission
10947 + " due to sender " + r.callerPackage
10948 + " (uid " + r.callingUid + ")");
10949 skip = true;
10950 }
10951 }
10952 if (r.curApp != null && r.curApp.crashing) {
10953 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010954 if (DEBUG_BROADCAST) Slog.v(TAG,
10955 "Skipping deliver ordered " + r + " to " + r.curApp
10956 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 skip = true;
10958 }
10959
10960 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010961 if (DEBUG_BROADCAST) Slog.v(TAG,
10962 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 r.receiver = null;
10964 r.curFilter = null;
10965 r.state = BroadcastRecord.IDLE;
10966 scheduleBroadcastsLocked();
10967 return;
10968 }
10969
10970 r.state = BroadcastRecord.APP_RECEIVE;
10971 String targetProcess = info.activityInfo.processName;
10972 r.curComponent = new ComponentName(
10973 info.activityInfo.applicationInfo.packageName,
10974 info.activityInfo.name);
10975 r.curReceiver = info.activityInfo;
10976
10977 // Is this receiver's application already running?
10978 ProcessRecord app = getProcessRecordLocked(targetProcess,
10979 info.activityInfo.applicationInfo.uid);
10980 if (app != null && app.thread != null) {
10981 try {
10982 processCurBroadcastLocked(r, app);
10983 return;
10984 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010985 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986 + r.curComponent, e);
10987 }
10988
10989 // If a dead object exception was thrown -- fall through to
10990 // restart the application.
10991 }
10992
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010993 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010994 if (DEBUG_BROADCAST) Slog.v(TAG,
10995 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 if ((r.curApp=startProcessLocked(targetProcess,
10997 info.activityInfo.applicationInfo, true,
10998 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010999 "broadcast", r.curComponent,
11000 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11001 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011002 // Ah, this recipient is unavailable. Finish it if necessary,
11003 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011004 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011005 + info.activityInfo.applicationInfo.packageName + "/"
11006 + info.activityInfo.applicationInfo.uid + " for broadcast "
11007 + r.intent + ": process is bad");
11008 logBroadcastReceiverDiscard(r);
11009 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11010 r.resultExtras, r.resultAbort, true);
11011 scheduleBroadcastsLocked();
11012 r.state = BroadcastRecord.IDLE;
11013 return;
11014 }
11015
11016 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011017 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 }
11019 }
11020
11021 // =========================================================
11022 // INSTRUMENTATION
11023 // =========================================================
11024
11025 public boolean startInstrumentation(ComponentName className,
11026 String profileFile, int flags, Bundle arguments,
11027 IInstrumentationWatcher watcher) {
11028 // Refuse possible leaked file descriptors
11029 if (arguments != null && arguments.hasFileDescriptors()) {
11030 throw new IllegalArgumentException("File descriptors passed in Bundle");
11031 }
11032
11033 synchronized(this) {
11034 InstrumentationInfo ii = null;
11035 ApplicationInfo ai = null;
11036 try {
11037 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011038 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011039 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011040 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011041 } catch (PackageManager.NameNotFoundException e) {
11042 }
11043 if (ii == null) {
11044 reportStartInstrumentationFailure(watcher, className,
11045 "Unable to find instrumentation info for: " + className);
11046 return false;
11047 }
11048 if (ai == null) {
11049 reportStartInstrumentationFailure(watcher, className,
11050 "Unable to find instrumentation target package: " + ii.targetPackage);
11051 return false;
11052 }
11053
11054 int match = mContext.getPackageManager().checkSignatures(
11055 ii.targetPackage, ii.packageName);
11056 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11057 String msg = "Permission Denial: starting instrumentation "
11058 + className + " from pid="
11059 + Binder.getCallingPid()
11060 + ", uid=" + Binder.getCallingPid()
11061 + " not allowed because package " + ii.packageName
11062 + " does not have a signature matching the target "
11063 + ii.targetPackage;
11064 reportStartInstrumentationFailure(watcher, className, msg);
11065 throw new SecurityException(msg);
11066 }
11067
11068 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011069 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 ProcessRecord app = addAppLocked(ai);
11071 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011072 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011073 app.instrumentationProfileFile = profileFile;
11074 app.instrumentationArguments = arguments;
11075 app.instrumentationWatcher = watcher;
11076 app.instrumentationResultClass = className;
11077 Binder.restoreCallingIdentity(origId);
11078 }
11079
11080 return true;
11081 }
11082
11083 /**
11084 * Report errors that occur while attempting to start Instrumentation. Always writes the
11085 * error to the logs, but if somebody is watching, send the report there too. This enables
11086 * the "am" command to report errors with more information.
11087 *
11088 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11089 * @param cn The component name of the instrumentation.
11090 * @param report The error report.
11091 */
11092 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11093 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011094 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011095 try {
11096 if (watcher != null) {
11097 Bundle results = new Bundle();
11098 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11099 results.putString("Error", report);
11100 watcher.instrumentationStatus(cn, -1, results);
11101 }
11102 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011103 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 }
11105 }
11106
11107 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11108 if (app.instrumentationWatcher != null) {
11109 try {
11110 // NOTE: IInstrumentationWatcher *must* be oneway here
11111 app.instrumentationWatcher.instrumentationFinished(
11112 app.instrumentationClass,
11113 resultCode,
11114 results);
11115 } catch (RemoteException e) {
11116 }
11117 }
11118 app.instrumentationWatcher = null;
11119 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011120 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011121 app.instrumentationProfileFile = null;
11122 app.instrumentationArguments = null;
11123
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011124 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011125 }
11126
11127 public void finishInstrumentation(IApplicationThread target,
11128 int resultCode, Bundle results) {
11129 // Refuse possible leaked file descriptors
11130 if (results != null && results.hasFileDescriptors()) {
11131 throw new IllegalArgumentException("File descriptors passed in Intent");
11132 }
11133
11134 synchronized(this) {
11135 ProcessRecord app = getRecordForAppLocked(target);
11136 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011137 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011138 return;
11139 }
11140 final long origId = Binder.clearCallingIdentity();
11141 finishInstrumentationLocked(app, resultCode, results);
11142 Binder.restoreCallingIdentity(origId);
11143 }
11144 }
11145
11146 // =========================================================
11147 // CONFIGURATION
11148 // =========================================================
11149
11150 public ConfigurationInfo getDeviceConfigurationInfo() {
11151 ConfigurationInfo config = new ConfigurationInfo();
11152 synchronized (this) {
11153 config.reqTouchScreen = mConfiguration.touchscreen;
11154 config.reqKeyboardType = mConfiguration.keyboard;
11155 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011156 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11157 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011158 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11159 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011160 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11161 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011162 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11163 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011164 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 }
11166 return config;
11167 }
11168
11169 public Configuration getConfiguration() {
11170 Configuration ci;
11171 synchronized(this) {
11172 ci = new Configuration(mConfiguration);
11173 }
11174 return ci;
11175 }
11176
11177 public void updateConfiguration(Configuration values) {
11178 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11179 "updateConfiguration()");
11180
11181 synchronized(this) {
11182 if (values == null && mWindowManager != null) {
11183 // sentinel: fetch the current configuration from the window manager
11184 values = mWindowManager.computeNewConfiguration();
11185 }
11186
11187 final long origId = Binder.clearCallingIdentity();
11188 updateConfigurationLocked(values, null);
11189 Binder.restoreCallingIdentity(origId);
11190 }
11191 }
11192
11193 /**
11194 * Do either or both things: (1) change the current configuration, and (2)
11195 * make sure the given activity is running with the (now) current
11196 * configuration. Returns true if the activity has been left running, or
11197 * false if <var>starting</var> is being destroyed to match the new
11198 * configuration.
11199 */
11200 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011201 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 int changes = 0;
11203
11204 boolean kept = true;
11205
11206 if (values != null) {
11207 Configuration newConfig = new Configuration(mConfiguration);
11208 changes = newConfig.updateFrom(values);
11209 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011210 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011211 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 }
11213
Doug Zongker2bec3d42009-12-04 12:52:44 -080011214 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011215
11216 if (values.locale != null) {
11217 saveLocaleLocked(values.locale,
11218 !values.locale.equals(mConfiguration.locale),
11219 values.userSetLocale);
11220 }
11221
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011222 mConfigurationSeq++;
11223 if (mConfigurationSeq <= 0) {
11224 mConfigurationSeq = 1;
11225 }
11226 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011228 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011229
11230 AttributeCache ac = AttributeCache.instance();
11231 if (ac != null) {
11232 ac.updateConfiguration(mConfiguration);
11233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011234
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011235 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11236 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11237 msg.obj = new Configuration(mConfiguration);
11238 mHandler.sendMessage(msg);
11239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011241 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11242 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011243 try {
11244 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011245 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011246 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247 app.thread.scheduleConfigurationChanged(mConfiguration);
11248 }
11249 } catch (Exception e) {
11250 }
11251 }
11252 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011253 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11254 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011255 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11256 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011257 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11258 broadcastIntentLocked(null, null,
11259 new Intent(Intent.ACTION_LOCALE_CHANGED),
11260 null, null, 0, null, null,
11261 null, false, false, MY_PID, Process.SYSTEM_UID);
11262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 }
11264 }
11265
11266 if (changes != 0 && starting == null) {
11267 // If the configuration changed, and the caller is not already
11268 // in the process of starting an activity, then find the top
11269 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011270 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011271 }
11272
11273 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011274 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011275 if (kept) {
11276 // If this didn't result in the starting activity being
11277 // destroyed, then we need to make sure at this point that all
11278 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011279 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011280 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011281 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 }
11283 }
11284
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011285 if (values != null && mWindowManager != null) {
11286 mWindowManager.setNewConfiguration(mConfiguration);
11287 }
11288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 return kept;
11290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291
11292 /**
11293 * Save the locale. You must be inside a synchronized (this) block.
11294 */
11295 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11296 if(isDiff) {
11297 SystemProperties.set("user.language", l.getLanguage());
11298 SystemProperties.set("user.region", l.getCountry());
11299 }
11300
11301 if(isPersist) {
11302 SystemProperties.set("persist.sys.language", l.getLanguage());
11303 SystemProperties.set("persist.sys.country", l.getCountry());
11304 SystemProperties.set("persist.sys.localevar", l.getVariant());
11305 }
11306 }
11307
11308 // =========================================================
11309 // LIFETIME MANAGEMENT
11310 // =========================================================
11311
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011312 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11313 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011314 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011315 // This adjustment has already been computed. If we are calling
11316 // from the top, we may have already computed our adjustment with
11317 // an earlier hidden adjustment that isn't really for us... if
11318 // so, use the new hidden adjustment.
11319 if (!recursed && app.hidden) {
11320 app.curAdj = hiddenAdj;
11321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011322 return app.curAdj;
11323 }
11324
11325 if (app.thread == null) {
11326 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011327 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011328 return (app.curAdj=EMPTY_APP_ADJ);
11329 }
11330
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011331 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11332 // The max adjustment doesn't allow this app to be anything
11333 // below foreground, so it is not worth doing work for it.
11334 app.adjType = "fixed";
11335 app.adjSeq = mAdjSeq;
11336 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011337 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011338 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11339 return (app.curAdj=app.maxAdj);
11340 }
11341
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011342 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011343 app.adjSource = null;
11344 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011345 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011346 app.empty = false;
11347 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011348
The Android Open Source Project4df24232009-03-05 14:34:35 -080011349 // Determine the importance of the process, starting with most
11350 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011351 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011352 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011353 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011354 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011355 // The last app on the list is the foreground app.
11356 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011357 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011358 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011359 } else if (app.instrumentationClass != null) {
11360 // Don't want to kill running instrumentation.
11361 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011362 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011363 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011364 } else if (app.persistentActivities > 0) {
11365 // Special persistent activities... shouldn't be used these days.
11366 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011367 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011368 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 } else if (app.curReceiver != null ||
11370 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11371 // An app that is currently receiving a broadcast also
11372 // counts as being in the foreground.
11373 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011374 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011375 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011376 } else if (app.executingServices.size() > 0) {
11377 // An app that is currently executing a service callback also
11378 // counts as being in the foreground.
11379 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011380 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011381 app.adjType = "exec-service";
11382 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011383 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011384 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011385 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011386 app.adjType = "foreground-service";
11387 } else if (app.forcingToForeground != null) {
11388 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011389 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011390 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011391 app.adjType = "force-foreground";
11392 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011393 } else if (app == mHeavyWeightProcess) {
11394 // We don't want to kill the current heavy-weight process.
11395 adj = HEAVY_WEIGHT_APP_ADJ;
11396 schedGroup = Process.THREAD_GROUP_DEFAULT;
11397 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011398 } else if (app == mHomeProcess) {
11399 // This process is hosting what we currently consider to be the
11400 // home app, so we don't want to let it go into the background.
11401 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011402 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011403 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404 } else if ((N=app.activities.size()) != 0) {
11405 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011406 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011407 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011408 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011409 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011410 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011411 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011412 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011413 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011414 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011415 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011416 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011417 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 break;
11419 }
11420 }
11421 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011422 // A very not-needed process. If this is lower in the lru list,
11423 // we will push it in to the empty bucket.
11424 app.hidden = true;
11425 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011426 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011427 adj = hiddenAdj;
11428 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011429 }
11430
Joe Onorato8a9b2202010-02-26 18:56:32 -080011431 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011432
The Android Open Source Project4df24232009-03-05 14:34:35 -080011433 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011434 // there are applications dependent on our services or providers, but
11435 // this gives us a baseline and makes sure we don't get into an
11436 // infinite recursion.
11437 app.adjSeq = mAdjSeq;
11438 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011439
Christopher Tate6fa95972009-06-05 18:43:55 -070011440 if (mBackupTarget != null && app == mBackupTarget.app) {
11441 // If possible we want to avoid killing apps while they're being backed up
11442 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011443 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011444 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011445 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011446 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011447 }
11448 }
11449
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011450 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11451 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 final long now = SystemClock.uptimeMillis();
11453 // This process is more important if the top activity is
11454 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011455 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011457 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011458 if (s.startRequested) {
11459 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11460 // This service has seen some activity within
11461 // recent memory, so we will keep its process ahead
11462 // of the background processes.
11463 if (adj > SECONDARY_SERVER_ADJ) {
11464 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011465 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011466 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011467 }
11468 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011469 // If we have let the service slide into the background
11470 // state, still have some text describing what it is doing
11471 // even though the service no longer has an impact.
11472 if (adj > SECONDARY_SERVER_ADJ) {
11473 app.adjType = "started-bg-services";
11474 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011475 // Don't kill this process because it is doing work; it
11476 // has said it is doing work.
11477 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011478 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011479 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11480 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011481 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011482 = s.connections.values().iterator();
11483 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011484 ArrayList<ConnectionRecord> clist = kt.next();
11485 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11486 // XXX should compute this based on the max of
11487 // all connected clients.
11488 ConnectionRecord cr = clist.get(i);
11489 if (cr.binding.client == app) {
11490 // Binding to ourself is not interesting.
11491 continue;
11492 }
11493 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11494 ProcessRecord client = cr.binding.client;
11495 int myHiddenAdj = hiddenAdj;
11496 if (myHiddenAdj > client.hiddenAdj) {
11497 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11498 myHiddenAdj = client.hiddenAdj;
11499 } else {
11500 myHiddenAdj = VISIBLE_APP_ADJ;
11501 }
11502 }
11503 int clientAdj = computeOomAdjLocked(
11504 client, myHiddenAdj, TOP_APP, true);
11505 if (adj > clientAdj) {
11506 adj = clientAdj >= VISIBLE_APP_ADJ
11507 ? clientAdj : VISIBLE_APP_ADJ;
11508 if (!client.hidden) {
11509 app.hidden = false;
11510 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011511 if (client.keeping) {
11512 app.keeping = true;
11513 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011514 app.adjType = "service";
11515 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11516 .REASON_SERVICE_IN_USE;
11517 app.adjSource = cr.binding.client;
11518 app.adjTarget = s.name;
11519 }
11520 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11521 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11522 schedGroup = Process.THREAD_GROUP_DEFAULT;
11523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011524 }
11525 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011526 ActivityRecord a = cr.activity;
11527 //if (a != null) {
11528 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11529 //}
11530 if (a != null && adj > FOREGROUND_APP_ADJ &&
11531 (a.state == ActivityState.RESUMED
11532 || a.state == ActivityState.PAUSING)) {
11533 adj = FOREGROUND_APP_ADJ;
11534 schedGroup = Process.THREAD_GROUP_DEFAULT;
11535 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011536 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011537 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11538 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011539 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011540 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011542 }
11543 }
11544 }
11545 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011546
Dianne Hackborn287952c2010-09-22 22:34:31 -070011547 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011548 // would like to avoid killing it unless it would prevent the current
11549 // application from running. By default we put the process in
11550 // with the rest of the background processes; as we scan through
11551 // its services we may bump it up from there.
11552 if (adj > hiddenAdj) {
11553 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011554 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011555 app.adjType = "bg-services";
11556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011557 }
11558
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011559 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11560 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011561 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011562 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11563 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011564 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011565 if (cpr.clients.size() != 0) {
11566 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11567 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11568 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011569 if (client == app) {
11570 // Being our own client is not interesting.
11571 continue;
11572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011573 int myHiddenAdj = hiddenAdj;
11574 if (myHiddenAdj > client.hiddenAdj) {
11575 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11576 myHiddenAdj = client.hiddenAdj;
11577 } else {
11578 myHiddenAdj = FOREGROUND_APP_ADJ;
11579 }
11580 }
11581 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011582 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011583 if (adj > clientAdj) {
11584 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011585 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011586 if (!client.hidden) {
11587 app.hidden = false;
11588 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011589 if (client.keeping) {
11590 app.keeping = true;
11591 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011592 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011593 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11594 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011595 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011596 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011597 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011598 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11599 schedGroup = Process.THREAD_GROUP_DEFAULT;
11600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011601 }
11602 }
11603 // If the provider has external (non-framework) process
11604 // dependencies, ensure that its adjustment is at least
11605 // FOREGROUND_APP_ADJ.
11606 if (cpr.externals != 0) {
11607 if (adj > FOREGROUND_APP_ADJ) {
11608 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011609 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011610 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011611 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011612 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011613 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 }
11615 }
11616 }
11617 }
11618
11619 app.curRawAdj = adj;
11620
Joe Onorato8a9b2202010-02-26 18:56:32 -080011621 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011622 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11623 if (adj > app.maxAdj) {
11624 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011625 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011626 schedGroup = Process.THREAD_GROUP_DEFAULT;
11627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011629 if (adj < HIDDEN_APP_MIN_ADJ) {
11630 app.keeping = true;
11631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632
11633 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011634 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 return adj;
11637 }
11638
11639 /**
11640 * Ask a given process to GC right now.
11641 */
11642 final void performAppGcLocked(ProcessRecord app) {
11643 try {
11644 app.lastRequestedGc = SystemClock.uptimeMillis();
11645 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011646 if (app.reportLowMemory) {
11647 app.reportLowMemory = false;
11648 app.thread.scheduleLowMemory();
11649 } else {
11650 app.thread.processInBackground();
11651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011652 }
11653 } catch (Exception e) {
11654 // whatever.
11655 }
11656 }
11657
11658 /**
11659 * Returns true if things are idle enough to perform GCs.
11660 */
Josh Bartel7f208742010-02-25 11:01:44 -060011661 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011662 return mParallelBroadcasts.size() == 0
11663 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011664 && (mSleeping || (mMainStack.mResumedActivity != null &&
11665 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 }
11667
11668 /**
11669 * Perform GCs on all processes that are waiting for it, but only
11670 * if things are idle.
11671 */
11672 final void performAppGcsLocked() {
11673 final int N = mProcessesToGc.size();
11674 if (N <= 0) {
11675 return;
11676 }
Josh Bartel7f208742010-02-25 11:01:44 -060011677 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011678 while (mProcessesToGc.size() > 0) {
11679 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011680 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011681 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11682 <= SystemClock.uptimeMillis()) {
11683 // To avoid spamming the system, we will GC processes one
11684 // at a time, waiting a few seconds between each.
11685 performAppGcLocked(proc);
11686 scheduleAppGcsLocked();
11687 return;
11688 } else {
11689 // It hasn't been long enough since we last GCed this
11690 // process... put it in the list to wait for its time.
11691 addProcessToGcListLocked(proc);
11692 break;
11693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011694 }
11695 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011696
11697 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011698 }
11699 }
11700
11701 /**
11702 * If all looks good, perform GCs on all processes waiting for them.
11703 */
11704 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011705 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 performAppGcsLocked();
11707 return;
11708 }
11709 // Still not idle, wait some more.
11710 scheduleAppGcsLocked();
11711 }
11712
11713 /**
11714 * Schedule the execution of all pending app GCs.
11715 */
11716 final void scheduleAppGcsLocked() {
11717 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011718
11719 if (mProcessesToGc.size() > 0) {
11720 // Schedule a GC for the time to the next process.
11721 ProcessRecord proc = mProcessesToGc.get(0);
11722 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11723
11724 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11725 long now = SystemClock.uptimeMillis();
11726 if (when < (now+GC_TIMEOUT)) {
11727 when = now + GC_TIMEOUT;
11728 }
11729 mHandler.sendMessageAtTime(msg, when);
11730 }
11731 }
11732
11733 /**
11734 * Add a process to the array of processes waiting to be GCed. Keeps the
11735 * list in sorted order by the last GC time. The process can't already be
11736 * on the list.
11737 */
11738 final void addProcessToGcListLocked(ProcessRecord proc) {
11739 boolean added = false;
11740 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11741 if (mProcessesToGc.get(i).lastRequestedGc <
11742 proc.lastRequestedGc) {
11743 added = true;
11744 mProcessesToGc.add(i+1, proc);
11745 break;
11746 }
11747 }
11748 if (!added) {
11749 mProcessesToGc.add(0, proc);
11750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011751 }
11752
11753 /**
11754 * Set up to ask a process to GC itself. This will either do it
11755 * immediately, or put it on the list of processes to gc the next
11756 * time things are idle.
11757 */
11758 final void scheduleAppGcLocked(ProcessRecord app) {
11759 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011760 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 return;
11762 }
11763 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011764 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011765 scheduleAppGcsLocked();
11766 }
11767 }
11768
Dianne Hackborn287952c2010-09-22 22:34:31 -070011769 final void checkExcessivePowerUsageLocked(boolean doKills) {
11770 updateCpuStatsNow();
11771
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011772 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011773 boolean doWakeKills = doKills;
11774 boolean doCpuKills = doKills;
11775 if (mLastPowerCheckRealtime == 0) {
11776 doWakeKills = false;
11777 }
11778 if (mLastPowerCheckUptime == 0) {
11779 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011780 }
11781 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011782 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011783 }
11784 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011785 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
11786 final long curUptime = SystemClock.uptimeMillis();
11787 final long uptimeSince = curUptime - mLastPowerCheckUptime;
11788 mLastPowerCheckRealtime = curRealtime;
11789 mLastPowerCheckUptime = curUptime;
11790 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
11791 doWakeKills = false;
11792 }
11793 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
11794 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011795 }
11796 int i = mLruProcesses.size();
11797 while (i > 0) {
11798 i--;
11799 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011800 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011801 long wtime;
11802 synchronized (stats) {
11803 wtime = stats.getProcessWakeTime(app.info.uid,
11804 app.pid, curRealtime);
11805 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011806 long wtimeUsed = wtime - app.lastWakeTime;
11807 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
11808 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011809 StringBuilder sb = new StringBuilder(128);
11810 sb.append("Wake for ");
11811 app.toShortString(sb);
11812 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011813 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011814 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011815 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011816 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011817 sb.append((wtimeUsed*100)/realtimeSince);
11818 sb.append("%)");
11819 Slog.i(TAG, sb.toString());
11820 sb.setLength(0);
11821 sb.append("CPU for ");
11822 app.toShortString(sb);
11823 sb.append(": over ");
11824 TimeUtils.formatDuration(uptimeSince, sb);
11825 sb.append(" used ");
11826 TimeUtils.formatDuration(cputimeUsed, sb);
11827 sb.append(" (");
11828 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011829 sb.append("%)");
11830 Slog.i(TAG, sb.toString());
11831 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011832 // If a process has held a wake lock for more
11833 // than 50% of the time during this period,
11834 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070011835 if (doWakeKills && realtimeSince > 0
11836 && ((wtimeUsed*100)/realtimeSince) >= 50) {
11837 synchronized (stats) {
11838 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
11839 realtimeSince, wtimeUsed);
11840 }
11841 Slog.w(TAG, "Excessive wake lock in " + app.processName
11842 + " (pid " + app.pid + "): held " + wtimeUsed
11843 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011844 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11845 app.processName, app.setAdj, "excessive wake lock");
11846 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011847 } else if (doCpuKills && uptimeSince > 0
11848 && ((cputimeUsed*100)/uptimeSince) >= 50) {
11849 synchronized (stats) {
11850 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
11851 uptimeSince, cputimeUsed);
11852 }
11853 Slog.w(TAG, "Excessive CPU in " + app.processName
11854 + " (pid " + app.pid + "): used " + cputimeUsed
11855 + " during " + uptimeSince);
11856 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11857 app.processName, app.setAdj, "excessive cpu");
11858 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011859 } else {
11860 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011861 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011862 }
11863 }
11864 }
11865 }
11866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011867 private final boolean updateOomAdjLocked(
11868 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
11869 app.hiddenAdj = hiddenAdj;
11870
11871 if (app.thread == null) {
11872 return true;
11873 }
11874
Dianne Hackborn287952c2010-09-22 22:34:31 -070011875 final boolean wasKeeping = app.keeping;
11876
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011877 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011878
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011879 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011880 if (app.curRawAdj != app.setRawAdj) {
11881 if (app.curRawAdj > FOREGROUND_APP_ADJ
11882 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
11883 // If this app is transitioning from foreground to
11884 // non-foreground, have it do a gc.
11885 scheduleAppGcLocked(app);
11886 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
11887 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
11888 // Likewise do a gc when an app is moving in to the
11889 // background (such as a service stopping).
11890 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011891 }
11892
11893 if (wasKeeping && !app.keeping) {
11894 // This app is no longer something we want to keep. Note
11895 // its current wake lock time to later know to kill it if
11896 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011897 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11898 synchronized (stats) {
11899 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
11900 app.pid, SystemClock.elapsedRealtime());
11901 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011902 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011905 app.setRawAdj = app.curRawAdj;
11906 }
11907 if (adj != app.setAdj) {
11908 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011909 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 TAG, "Set app " + app.processName +
11911 " oom adj to " + adj);
11912 app.setAdj = adj;
11913 } else {
11914 return false;
11915 }
11916 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011917 if (app.setSchedGroup != app.curSchedGroup) {
11918 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011919 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011920 "Setting process group of " + app.processName
11921 + " to " + app.curSchedGroup);
11922 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070011923 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011924 try {
11925 Process.setProcessGroup(app.pid, app.curSchedGroup);
11926 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011927 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011928 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070011929 e.printStackTrace();
11930 } finally {
11931 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011932 }
11933 }
11934 if (false) {
11935 if (app.thread != null) {
11936 try {
11937 app.thread.setSchedulingGroup(app.curSchedGroup);
11938 } catch (RemoteException e) {
11939 }
11940 }
11941 }
11942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011943 }
11944
11945 return true;
11946 }
11947
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011948 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011949 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011950 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011951 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011952 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011953 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 }
11955 }
11956 return resumedActivity;
11957 }
11958
11959 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011960 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011961 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11962 int curAdj = app.curAdj;
11963 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11964 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11965
11966 mAdjSeq++;
11967
11968 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
11969 if (res) {
11970 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
11971 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
11972 if (nowHidden != wasHidden) {
11973 // Changed to/from hidden state, so apps after it in the LRU
11974 // list may also be changed.
11975 updateOomAdjLocked();
11976 }
11977 }
11978 return res;
11979 }
11980
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011981 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011982 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011983 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011984 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
11985
11986 if (false) {
11987 RuntimeException e = new RuntimeException();
11988 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011989 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011990 }
11991
11992 mAdjSeq++;
11993
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011994 // Let's determine how many processes we have running vs.
11995 // how many slots we have for background processes; we may want
11996 // to put multiple processes in a slot of there are enough of
11997 // them.
11998 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
11999 int factor = (mLruProcesses.size()-4)/numSlots;
12000 if (factor < 1) factor = 1;
12001 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012002 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012004 // First try updating the OOM adjustment for each of the
12005 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012006 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012007 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12008 while (i > 0) {
12009 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012010 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012011 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012013 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012014 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012015 step++;
12016 if (step >= factor) {
12017 step = 0;
12018 curHiddenAdj++;
12019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012021 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012022 if (!app.killedBackground) {
12023 numHidden++;
12024 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012025 Slog.i(TAG, "No longer want " + app.processName
12026 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012027 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12028 app.processName, app.setAdj, "too many background");
12029 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012030 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012031 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012032 }
12033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012034 } else {
12035 didOomAdj = false;
12036 }
12037 }
12038
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012039 // If we return false, we will fall back on killing processes to
12040 // have a fixed limit. Do this if a limit has been requested; else
12041 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012042 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12043 }
12044
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012045 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012046 synchronized (this) {
12047 int i;
12048
12049 // First remove any unused application processes whose package
12050 // has been removed.
12051 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12052 final ProcessRecord app = mRemovedProcesses.get(i);
12053 if (app.activities.size() == 0
12054 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012055 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012056 TAG, "Exiting empty application process "
12057 + app.processName + " ("
12058 + (app.thread != null ? app.thread.asBinder() : null)
12059 + ")\n");
12060 if (app.pid > 0 && app.pid != MY_PID) {
12061 Process.killProcess(app.pid);
12062 } else {
12063 try {
12064 app.thread.scheduleExit();
12065 } catch (Exception e) {
12066 // Ignore exceptions.
12067 }
12068 }
12069 cleanUpApplicationRecordLocked(app, false, -1);
12070 mRemovedProcesses.remove(i);
12071
12072 if (app.persistent) {
12073 if (app.persistent) {
12074 addAppLocked(app.info);
12075 }
12076 }
12077 }
12078 }
12079
12080 // Now try updating the OOM adjustment for each of the
12081 // application processes based on their current state.
12082 // If the setOomAdj() API is not supported, then go with our
12083 // back-up plan...
12084 if (!updateOomAdjLocked()) {
12085
12086 // Count how many processes are running services.
12087 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012088 for (i=mLruProcesses.size()-1; i>=0; i--) {
12089 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012090
12091 if (app.persistent || app.services.size() != 0
12092 || app.curReceiver != null
12093 || app.persistentActivities > 0) {
12094 // Don't count processes holding services against our
12095 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012096 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012097 TAG, "Not trimming app " + app + " with services: "
12098 + app.services);
12099 numServiceProcs++;
12100 }
12101 }
12102
12103 int curMaxProcs = mProcessLimit;
12104 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12105 if (mAlwaysFinishActivities) {
12106 curMaxProcs = 1;
12107 }
12108 curMaxProcs += numServiceProcs;
12109
12110 // Quit as many processes as we can to get down to the desired
12111 // process count. First remove any processes that no longer
12112 // have activites running in them.
12113 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012114 i<mLruProcesses.size()
12115 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012116 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012117 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012118 // Quit an application only if it is not currently
12119 // running any activities.
12120 if (!app.persistent && app.activities.size() == 0
12121 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012122 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012123 TAG, "Exiting empty application process "
12124 + app.processName + " ("
12125 + (app.thread != null ? app.thread.asBinder() : null)
12126 + ")\n");
12127 if (app.pid > 0 && app.pid != MY_PID) {
12128 Process.killProcess(app.pid);
12129 } else {
12130 try {
12131 app.thread.scheduleExit();
12132 } catch (Exception e) {
12133 // Ignore exceptions.
12134 }
12135 }
12136 // todo: For now we assume the application is not buggy
12137 // or evil, and will quit as a result of our request.
12138 // Eventually we need to drive this off of the death
12139 // notification, and kill the process if it takes too long.
12140 cleanUpApplicationRecordLocked(app, false, i);
12141 i--;
12142 }
12143 }
12144
12145 // If we still have too many processes, now from the least
12146 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012147 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012148 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012149 " of " + curMaxProcs + " processes");
12150 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012151 i<mLruProcesses.size()
12152 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012154 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012155 // Quit the application only if we have a state saved for
12156 // all of its activities.
12157 boolean canQuit = !app.persistent && app.curReceiver == null
12158 && app.services.size() == 0
12159 && app.persistentActivities == 0;
12160 int NUMA = app.activities.size();
12161 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012162 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012163 TAG, "Looking to quit " + app.processName);
12164 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012165 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012166 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012167 TAG, " " + r.intent.getComponent().flattenToShortString()
12168 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12169 canQuit = (r.haveState || !r.stateNotNeeded)
12170 && !r.visible && r.stopped;
12171 }
12172 if (canQuit) {
12173 // Finish all of the activities, and then the app itself.
12174 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012175 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012177 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178 }
12179 r.resultTo = null;
12180 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012181 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012182 + app.processName + " ("
12183 + (app.thread != null ? app.thread.asBinder() : null)
12184 + ")\n");
12185 if (app.pid > 0 && app.pid != MY_PID) {
12186 Process.killProcess(app.pid);
12187 } else {
12188 try {
12189 app.thread.scheduleExit();
12190 } catch (Exception e) {
12191 // Ignore exceptions.
12192 }
12193 }
12194 // todo: For now we assume the application is not buggy
12195 // or evil, and will quit as a result of our request.
12196 // Eventually we need to drive this off of the death
12197 // notification, and kill the process if it takes too long.
12198 cleanUpApplicationRecordLocked(app, false, i);
12199 i--;
12200 //dump();
12201 }
12202 }
12203
12204 }
12205
12206 int curMaxActivities = MAX_ACTIVITIES;
12207 if (mAlwaysFinishActivities) {
12208 curMaxActivities = 1;
12209 }
12210
12211 // Finally, if there are too many activities now running, try to
12212 // finish as many as we can to get back down to the limit.
12213 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012214 i<mMainStack.mLRUActivities.size()
12215 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012216 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012217 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012218 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012219
12220 // We can finish this one if we have its icicle saved and
12221 // it is not persistent.
12222 if ((r.haveState || !r.stateNotNeeded) && !r.visible
12223 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012224 final int origSize = mMainStack.mLRUActivities.size();
12225 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226
12227 // This will remove it from the LRU list, so keep
12228 // our index at the same value. Note that this check to
12229 // see if the size changes is just paranoia -- if
12230 // something unexpected happens, we don't want to end up
12231 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012232 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233 i--;
12234 }
12235 }
12236 }
12237 }
12238 }
12239
12240 /** This method sends the specified signal to each of the persistent apps */
12241 public void signalPersistentProcesses(int sig) throws RemoteException {
12242 if (sig != Process.SIGNAL_USR1) {
12243 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12244 }
12245
12246 synchronized (this) {
12247 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12248 != PackageManager.PERMISSION_GRANTED) {
12249 throw new SecurityException("Requires permission "
12250 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12251 }
12252
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012253 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12254 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012255 if (r.thread != null && r.persistent) {
12256 Process.sendSignal(r.pid, sig);
12257 }
12258 }
12259 }
12260 }
12261
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012262 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012263 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012264
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012265 try {
12266 synchronized (this) {
12267 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12268 // its own permission.
12269 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12270 != PackageManager.PERMISSION_GRANTED) {
12271 throw new SecurityException("Requires permission "
12272 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012273 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012274
12275 if (start && fd == null) {
12276 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012277 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012278
12279 ProcessRecord proc = null;
12280 try {
12281 int pid = Integer.parseInt(process);
12282 synchronized (mPidsSelfLocked) {
12283 proc = mPidsSelfLocked.get(pid);
12284 }
12285 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012286 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012287
12288 if (proc == null) {
12289 HashMap<String, SparseArray<ProcessRecord>> all
12290 = mProcessNames.getMap();
12291 SparseArray<ProcessRecord> procs = all.get(process);
12292 if (procs != null && procs.size() > 0) {
12293 proc = procs.valueAt(0);
12294 }
12295 }
12296
12297 if (proc == null || proc.thread == null) {
12298 throw new IllegalArgumentException("Unknown process: " + process);
12299 }
12300
12301 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12302 if (isSecure) {
12303 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12304 throw new SecurityException("Process not debuggable: " + proc);
12305 }
12306 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012307
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012308 proc.thread.profilerControl(start, path, fd);
12309 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012310 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012311 }
12312 } catch (RemoteException e) {
12313 throw new IllegalStateException("Process disappeared");
12314 } finally {
12315 if (fd != null) {
12316 try {
12317 fd.close();
12318 } catch (IOException e) {
12319 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012320 }
12321 }
12322 }
12323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012324 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12325 public void monitor() {
12326 synchronized (this) { }
12327 }
12328}