blob: 34753e7c7c1e96a36e269edfc08397cbe343b3bc [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 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700568 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
569 */
570 private boolean mPendingBroadcastTimeoutMessage;
571
572 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 * Intent broadcast that we have tried to start, but are
574 * waiting for its application's process to be created. We only
575 * need one (instead of a list) because we always process broadcasts
576 * one at a time, so no others can be started while waiting for this
577 * one.
578 */
579 BroadcastRecord mPendingBroadcast = null;
580
581 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700582 * The receiver index that is pending, to restart the broadcast if needed.
583 */
584 int mPendingBroadcastRecvIndex;
585
586 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 * Keeps track of all IIntentReceivers that have been registered for
588 * broadcasts. Hash keys are the receiver IBinder, hash value is
589 * a ReceiverList.
590 */
591 final HashMap mRegisteredReceivers = new HashMap();
592
593 /**
594 * Resolver for broadcast intents to registered receivers.
595 * Holds BroadcastFilter (subclass of IntentFilter).
596 */
597 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
598 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
599 @Override
600 protected boolean allowFilterResult(
601 BroadcastFilter filter, List<BroadcastFilter> dest) {
602 IBinder target = filter.receiverList.receiver.asBinder();
603 for (int i=dest.size()-1; i>=0; i--) {
604 if (dest.get(i).receiverList.receiver.asBinder() == target) {
605 return false;
606 }
607 }
608 return true;
609 }
610 };
611
612 /**
613 * State of all active sticky broadcasts. Keys are the action of the
614 * sticky Intent, values are an ArrayList of all broadcasted intents with
615 * that action (which should usually be one).
616 */
617 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
618 new HashMap<String, ArrayList<Intent>>();
619
620 /**
621 * All currently running services.
622 */
623 final HashMap<ComponentName, ServiceRecord> mServices =
624 new HashMap<ComponentName, ServiceRecord>();
625
626 /**
627 * All currently running services indexed by the Intent used to start them.
628 */
629 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
630 new HashMap<Intent.FilterComparison, ServiceRecord>();
631
632 /**
633 * All currently bound service connections. Keys are the IBinder of
634 * the client's IServiceConnection.
635 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700636 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
637 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638
639 /**
640 * List of services that we have been asked to start,
641 * but haven't yet been able to. It is used to hold start requests
642 * while waiting for their corresponding application thread to get
643 * going.
644 */
645 final ArrayList<ServiceRecord> mPendingServices
646 = new ArrayList<ServiceRecord>();
647
648 /**
649 * List of services that are scheduled to restart following a crash.
650 */
651 final ArrayList<ServiceRecord> mRestartingServices
652 = new ArrayList<ServiceRecord>();
653
654 /**
655 * List of services that are in the process of being stopped.
656 */
657 final ArrayList<ServiceRecord> mStoppingServices
658 = new ArrayList<ServiceRecord>();
659
660 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700661 * Backup/restore process management
662 */
663 String mBackupAppName = null;
664 BackupRecord mBackupTarget = null;
665
666 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 * List of PendingThumbnailsRecord objects of clients who are still
668 * waiting to receive all of the thumbnails for a task.
669 */
670 final ArrayList mPendingThumbnails = new ArrayList();
671
672 /**
673 * List of HistoryRecord objects that have been finished and must
674 * still report back to a pending thumbnail receiver.
675 */
676 final ArrayList mCancelledThumbnails = new ArrayList();
677
678 /**
679 * All of the currently running global content providers. Keys are a
680 * string containing the provider name and values are a
681 * ContentProviderRecord object containing the data about it. Note
682 * that a single provider may be published under multiple names, so
683 * there may be multiple entries here for a single one in mProvidersByClass.
684 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700685 final HashMap<String, ContentProviderRecord> mProvidersByName
686 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687
688 /**
689 * All of the currently running global content providers. Keys are a
690 * string containing the provider's implementation class and values are a
691 * ContentProviderRecord object containing the data about it.
692 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700693 final HashMap<String, ContentProviderRecord> mProvidersByClass
694 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695
696 /**
697 * List of content providers who have clients waiting for them. The
698 * application is currently being launched and the provider will be
699 * removed from this list once it is published.
700 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700701 final ArrayList<ContentProviderRecord> mLaunchingProviders
702 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703
704 /**
705 * Global set of specific Uri permissions that have been granted.
706 */
707 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
708 = new SparseArray<HashMap<Uri, UriPermission>>();
709
710 /**
711 * Thread-local storage used to carry caller permissions over through
712 * indirect content-provider access.
713 * @see #ActivityManagerService.openContentUri()
714 */
715 private class Identity {
716 public int pid;
717 public int uid;
718
719 Identity(int _pid, int _uid) {
720 pid = _pid;
721 uid = _uid;
722 }
723 }
724 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
725
726 /**
727 * All information we have collected about the runtime performance of
728 * any user id that can impact battery performance.
729 */
730 final BatteryStatsService mBatteryStatsService;
731
732 /**
733 * information about component usage
734 */
735 final UsageStatsService mUsageStatsService;
736
737 /**
738 * Current configuration information. HistoryRecord objects are given
739 * a reference to this object to indicate which configuration they are
740 * currently running in, so this object must be kept immutable.
741 */
742 Configuration mConfiguration = new Configuration();
743
744 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800745 * Current sequencing integer of the configuration, for skipping old
746 * configurations.
747 */
748 int mConfigurationSeq = 0;
749
750 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700751 * Hardware-reported OpenGLES version.
752 */
753 final int GL_ES_VERSION;
754
755 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 * List of initialization arguments to pass to all processes when binding applications to them.
757 * For example, references to the commonly used services.
758 */
759 HashMap<String, IBinder> mAppBindArgs;
760
761 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700762 * Temporary to avoid allocations. Protected by main lock.
763 */
764 final StringBuilder mStringBuilder = new StringBuilder(256);
765
766 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 * Used to control how we initialize the service.
768 */
769 boolean mStartRunning = false;
770 ComponentName mTopComponent;
771 String mTopAction;
772 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700773 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 boolean mSystemReady = false;
775 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700776 boolean mWaitingUpdate = false;
777 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700778 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700779 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780
781 Context mContext;
782
783 int mFactoryTest;
784
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700785 boolean mCheckedForSetup;
786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700788 * The time at which we will allow normal application switches again,
789 * after a call to {@link #stopAppSwitches()}.
790 */
791 long mAppSwitchesAllowedTime;
792
793 /**
794 * This is set to true after the first switch after mAppSwitchesAllowedTime
795 * is set; any switches after that will clear the time.
796 */
797 boolean mDidAppSwitch;
798
799 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700800 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700801 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700802 long mLastPowerCheckRealtime;
803
804 /**
805 * Last time (in uptime) at which we checked for power usage.
806 */
807 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700808
809 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 * Set while we are wanting to sleep, to prevent any
811 * activities from being started/resumed.
812 */
813 boolean mSleeping = false;
814
815 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700816 * Set if we are shutting down the system, similar to sleeping.
817 */
818 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819
820 /**
821 * Task identifier that activities are currently being started
822 * in. Incremented each time a new task is created.
823 * todo: Replace this with a TokenSpace class that generates non-repeating
824 * integers that won't wrap.
825 */
826 int mCurTask = 1;
827
828 /**
829 * Current sequence id for oom_adj computation traversal.
830 */
831 int mAdjSeq = 0;
832
833 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700834 * Current sequence id for process LRU updating.
835 */
836 int mLruSeq = 0;
837
838 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
840 * is set, indicating the user wants processes started in such a way
841 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
842 * running in each process (thus no pre-initialized process, etc).
843 */
844 boolean mSimpleProcessManagement = false;
845
846 /**
847 * System monitoring: number of processes that died since the last
848 * N procs were started.
849 */
850 int[] mProcDeaths = new int[20];
851
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700852 /**
853 * This is set if we had to do a delayed dexopt of an app before launching
854 * it, to increasing the ANR timeouts in that case.
855 */
856 boolean mDidDexOpt;
857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 String mDebugApp = null;
859 boolean mWaitForDebugger = false;
860 boolean mDebugTransient = false;
861 String mOrigDebugApp = null;
862 boolean mOrigWaitForDebugger = false;
863 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700864 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700866 final RemoteCallbackList<IActivityWatcher> mWatchers
867 = new RemoteCallbackList<IActivityWatcher>();
868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 /**
870 * Callback of last caller to {@link #requestPss}.
871 */
872 Runnable mRequestPssCallback;
873
874 /**
875 * Remaining processes for which we are waiting results from the last
876 * call to {@link #requestPss}.
877 */
878 final ArrayList<ProcessRecord> mRequestPssList
879 = new ArrayList<ProcessRecord>();
880
881 /**
882 * Runtime statistics collection thread. This object's lock is used to
883 * protect all related state.
884 */
885 final Thread mProcessStatsThread;
886
887 /**
888 * Used to collect process stats when showing not responding dialog.
889 * Protected by mProcessStatsThread.
890 */
891 final ProcessStats mProcessStats = new ProcessStats(
892 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700893 final AtomicLong mLastCpuTime = new AtomicLong(0);
894 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896 long mLastWriteTime = 0;
897
898 /**
899 * Set to true after the system has finished booting.
900 */
901 boolean mBooted = false;
902
903 int mProcessLimit = 0;
904
905 WindowManagerService mWindowManager;
906
907 static ActivityManagerService mSelf;
908 static ActivityThread mSystemThread;
909
910 private final class AppDeathRecipient implements IBinder.DeathRecipient {
911 final ProcessRecord mApp;
912 final int mPid;
913 final IApplicationThread mAppThread;
914
915 AppDeathRecipient(ProcessRecord app, int pid,
916 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800917 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 TAG, "New death recipient " + this
919 + " for thread " + thread.asBinder());
920 mApp = app;
921 mPid = pid;
922 mAppThread = thread;
923 }
924
925 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800926 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 TAG, "Death received in " + this
928 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 synchronized(ActivityManagerService.this) {
930 appDiedLocked(mApp, mPid, mAppThread);
931 }
932 }
933 }
934
935 static final int SHOW_ERROR_MSG = 1;
936 static final int SHOW_NOT_RESPONDING_MSG = 2;
937 static final int SHOW_FACTORY_ERROR_MSG = 3;
938 static final int UPDATE_CONFIGURATION_MSG = 4;
939 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
940 static final int WAIT_FOR_DEBUGGER_MSG = 6;
941 static final int BROADCAST_INTENT_MSG = 7;
942 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 static final int SERVICE_TIMEOUT_MSG = 12;
944 static final int UPDATE_TIME_ZONE = 13;
945 static final int SHOW_UID_ERROR_MSG = 14;
946 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700948 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700949 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800950 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700951 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
952 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700953 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700954 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955
956 AlertDialog mUidAlert;
957
958 final Handler mHandler = new Handler() {
959 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800960 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 //}
962
963 public void handleMessage(Message msg) {
964 switch (msg.what) {
965 case SHOW_ERROR_MSG: {
966 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 synchronized (ActivityManagerService.this) {
968 ProcessRecord proc = (ProcessRecord)data.get("app");
969 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800970 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 return;
972 }
973 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700974 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800975 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 d.show();
977 proc.crashDialog = d;
978 } else {
979 // The device is asleep, so just pretend that the user
980 // saw a crash dialog and hit "force quit".
981 res.set(0);
982 }
983 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700984
985 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 } break;
987 case SHOW_NOT_RESPONDING_MSG: {
988 synchronized (ActivityManagerService.this) {
989 HashMap data = (HashMap) msg.obj;
990 ProcessRecord proc = (ProcessRecord)data.get("app");
991 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800992 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 return;
994 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800995
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700996 Intent intent = new Intent("android.intent.action.ANR");
997 if (!mProcessesReady) {
998 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
999 }
1000 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001001 null, null, 0, null, null, null,
1002 false, false, MY_PID, Process.SYSTEM_UID);
1003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001005 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 d.show();
1007 proc.anrDialog = d;
1008 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001009
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001010 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001012 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1013 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1014 synchronized (ActivityManagerService.this) {
1015 ProcessRecord proc = (ProcessRecord) data.get("app");
1016 if (proc == null) {
1017 Slog.e(TAG, "App not found when showing strict mode dialog.");
1018 break;
1019 }
1020 if (proc.crashDialog != null) {
1021 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1022 return;
1023 }
1024 AppErrorResult res = (AppErrorResult) data.get("result");
1025 if (!mSleeping && !mShuttingDown) {
1026 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1027 d.show();
1028 proc.crashDialog = d;
1029 } else {
1030 // The device is asleep, so just pretend that the user
1031 // saw a crash dialog and hit "force quit".
1032 res.set(0);
1033 }
1034 }
1035 ensureBootCompleted();
1036 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 case SHOW_FACTORY_ERROR_MSG: {
1038 Dialog d = new FactoryErrorDialog(
1039 mContext, msg.getData().getCharSequence("msg"));
1040 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001041 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 } break;
1043 case UPDATE_CONFIGURATION_MSG: {
1044 final ContentResolver resolver = mContext.getContentResolver();
1045 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1046 } break;
1047 case GC_BACKGROUND_PROCESSES_MSG: {
1048 synchronized (ActivityManagerService.this) {
1049 performAppGcsIfAppropriateLocked();
1050 }
1051 } break;
1052 case WAIT_FOR_DEBUGGER_MSG: {
1053 synchronized (ActivityManagerService.this) {
1054 ProcessRecord app = (ProcessRecord)msg.obj;
1055 if (msg.arg1 != 0) {
1056 if (!app.waitedForDebugger) {
1057 Dialog d = new AppWaitingForDebuggerDialog(
1058 ActivityManagerService.this,
1059 mContext, app);
1060 app.waitDialog = d;
1061 app.waitedForDebugger = true;
1062 d.show();
1063 }
1064 } else {
1065 if (app.waitDialog != null) {
1066 app.waitDialog.dismiss();
1067 app.waitDialog = null;
1068 }
1069 }
1070 }
1071 } break;
1072 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001073 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 TAG, "Received BROADCAST_INTENT_MSG");
1075 processNextBroadcast(true);
1076 } break;
1077 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001078 synchronized (ActivityManagerService.this) {
1079 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001083 if (mDidDexOpt) {
1084 mDidDexOpt = false;
1085 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1086 nmsg.obj = msg.obj;
1087 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1088 return;
1089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 serviceTimeout((ProcessRecord)msg.obj);
1091 } break;
1092 case UPDATE_TIME_ZONE: {
1093 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001094 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1095 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 if (r.thread != null) {
1097 try {
1098 r.thread.updateTimeZone();
1099 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001100 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 }
1102 }
1103 }
1104 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001105 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 case SHOW_UID_ERROR_MSG: {
1107 // XXX This is a temporary dialog, no need to localize.
1108 AlertDialog d = new BaseErrorDialog(mContext);
1109 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1110 d.setCancelable(false);
1111 d.setTitle("System UIDs Inconsistent");
1112 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
1113 d.setButton("I'm Feeling Lucky",
1114 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1115 mUidAlert = d;
1116 d.show();
1117 } break;
1118 case IM_FEELING_LUCKY_MSG: {
1119 if (mUidAlert != null) {
1120 mUidAlert.dismiss();
1121 mUidAlert = null;
1122 }
1123 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001125 if (mDidDexOpt) {
1126 mDidDexOpt = false;
1127 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1128 nmsg.obj = msg.obj;
1129 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1130 return;
1131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 ProcessRecord app = (ProcessRecord)msg.obj;
1133 synchronized (ActivityManagerService.this) {
1134 processStartTimedOutLocked(app);
1135 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001136 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001137 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1138 synchronized (ActivityManagerService.this) {
1139 doPendingActivityLaunchesLocked(true);
1140 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001141 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001142 case KILL_APPLICATION_MSG: {
1143 synchronized (ActivityManagerService.this) {
1144 int uid = msg.arg1;
1145 boolean restart = (msg.arg2 == 1);
1146 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001147 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001148 }
1149 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001150 case FINALIZE_PENDING_INTENT_MSG: {
1151 ((PendingIntentRecord)msg.obj).completeFinalize();
1152 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001153 case POST_HEAVY_NOTIFICATION_MSG: {
1154 INotificationManager inm = NotificationManager.getService();
1155 if (inm == null) {
1156 return;
1157 }
1158
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001159 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001160 ProcessRecord process = root.app;
1161 if (process == null) {
1162 return;
1163 }
1164
1165 try {
1166 Context context = mContext.createPackageContext(process.info.packageName, 0);
1167 String text = mContext.getString(R.string.heavy_weight_notification,
1168 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1169 Notification notification = new Notification();
1170 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1171 notification.when = 0;
1172 notification.flags = Notification.FLAG_ONGOING_EVENT;
1173 notification.tickerText = text;
1174 notification.defaults = 0; // please be quiet
1175 notification.sound = null;
1176 notification.vibrate = null;
1177 notification.setLatestEventInfo(context, text,
1178 mContext.getText(R.string.heavy_weight_notification_detail),
1179 PendingIntent.getActivity(mContext, 0, root.intent,
1180 PendingIntent.FLAG_CANCEL_CURRENT));
1181
1182 try {
1183 int[] outId = new int[1];
1184 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1185 notification, outId);
1186 } catch (RuntimeException e) {
1187 Slog.w(ActivityManagerService.TAG,
1188 "Error showing notification for heavy-weight app", e);
1189 } catch (RemoteException e) {
1190 }
1191 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001192 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001193 }
1194 } break;
1195 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1196 INotificationManager inm = NotificationManager.getService();
1197 if (inm == null) {
1198 return;
1199 }
1200 try {
1201 inm.cancelNotification("android",
1202 R.string.heavy_weight_notification);
1203 } catch (RuntimeException e) {
1204 Slog.w(ActivityManagerService.TAG,
1205 "Error canceling notification for service", e);
1206 } catch (RemoteException e) {
1207 }
1208 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001209 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1210 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001211 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001212 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001213 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1214 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001215 }
1216 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 }
1218 }
1219 };
1220
1221 public static void setSystemProcess() {
1222 try {
1223 ActivityManagerService m = mSelf;
1224
1225 ServiceManager.addService("activity", m);
1226 ServiceManager.addService("meminfo", new MemBinder(m));
1227 if (MONITOR_CPU_USAGE) {
1228 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 ServiceManager.addService("permission", new PermissionController(m));
1231
1232 ApplicationInfo info =
1233 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001234 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001235 mSystemThread.installSystemApplicationInfo(info);
1236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 synchronized (mSelf) {
1238 ProcessRecord app = mSelf.newProcessRecordLocked(
1239 mSystemThread.getApplicationThread(), info,
1240 info.processName);
1241 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001242 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 app.maxAdj = SYSTEM_ADJ;
1244 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1245 synchronized (mSelf.mPidsSelfLocked) {
1246 mSelf.mPidsSelfLocked.put(app.pid, app);
1247 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001248 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 }
1250 } catch (PackageManager.NameNotFoundException e) {
1251 throw new RuntimeException(
1252 "Unable to find android system package", e);
1253 }
1254 }
1255
1256 public void setWindowManager(WindowManagerService wm) {
1257 mWindowManager = wm;
1258 }
1259
1260 public static final Context main(int factoryTest) {
1261 AThread thr = new AThread();
1262 thr.start();
1263
1264 synchronized (thr) {
1265 while (thr.mService == null) {
1266 try {
1267 thr.wait();
1268 } catch (InterruptedException e) {
1269 }
1270 }
1271 }
1272
1273 ActivityManagerService m = thr.mService;
1274 mSelf = m;
1275 ActivityThread at = ActivityThread.systemMain();
1276 mSystemThread = at;
1277 Context context = at.getSystemContext();
1278 m.mContext = context;
1279 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001280 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281
1282 m.mBatteryStatsService.publish(context);
1283 m.mUsageStatsService.publish(context);
1284
1285 synchronized (thr) {
1286 thr.mReady = true;
1287 thr.notifyAll();
1288 }
1289
1290 m.startRunning(null, null, null, null);
1291
1292 return context;
1293 }
1294
1295 public static ActivityManagerService self() {
1296 return mSelf;
1297 }
1298
1299 static class AThread extends Thread {
1300 ActivityManagerService mService;
1301 boolean mReady = false;
1302
1303 public AThread() {
1304 super("ActivityManager");
1305 }
1306
1307 public void run() {
1308 Looper.prepare();
1309
1310 android.os.Process.setThreadPriority(
1311 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001312 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313
1314 ActivityManagerService m = new ActivityManagerService();
1315
1316 synchronized (this) {
1317 mService = m;
1318 notifyAll();
1319 }
1320
1321 synchronized (this) {
1322 while (!mReady) {
1323 try {
1324 wait();
1325 } catch (InterruptedException e) {
1326 }
1327 }
1328 }
1329
1330 Looper.loop();
1331 }
1332 }
1333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 static class MemBinder extends Binder {
1335 ActivityManagerService mActivityManagerService;
1336 MemBinder(ActivityManagerService activityManagerService) {
1337 mActivityManagerService = activityManagerService;
1338 }
1339
1340 @Override
1341 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1342 ActivityManagerService service = mActivityManagerService;
1343 ArrayList<ProcessRecord> procs;
1344 synchronized (mActivityManagerService) {
1345 if (args != null && args.length > 0
1346 && args[0].charAt(0) != '-') {
1347 procs = new ArrayList<ProcessRecord>();
1348 int pid = -1;
1349 try {
1350 pid = Integer.parseInt(args[0]);
1351 } catch (NumberFormatException e) {
1352
1353 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001354 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1355 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 if (proc.pid == pid) {
1357 procs.add(proc);
1358 } else if (proc.processName.equals(args[0])) {
1359 procs.add(proc);
1360 }
1361 }
1362 if (procs.size() <= 0) {
1363 pw.println("No process found for: " + args[0]);
1364 return;
1365 }
1366 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001367 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 }
1369 }
1370 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1371 }
1372 }
1373
1374 static class CpuBinder extends Binder {
1375 ActivityManagerService mActivityManagerService;
1376 CpuBinder(ActivityManagerService activityManagerService) {
1377 mActivityManagerService = activityManagerService;
1378 }
1379
1380 @Override
1381 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1382 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001383 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1384 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1385 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386 }
1387 }
1388 }
1389
1390 private ActivityManagerService() {
1391 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1392 if (v != null && Integer.getInteger(v) != 0) {
1393 mSimpleProcessManagement = true;
1394 }
1395 v = System.getenv("ANDROID_DEBUG_APP");
1396 if (v != null) {
1397 mSimpleProcessManagement = true;
1398 }
1399
Joe Onorato8a9b2202010-02-26 18:56:32 -08001400 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 File dataDir = Environment.getDataDirectory();
1403 File systemDir = new File(dataDir, "system");
1404 systemDir.mkdirs();
1405 mBatteryStatsService = new BatteryStatsService(new File(
1406 systemDir, "batterystats.bin").toString());
1407 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001408 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001409 mOnBattery = DEBUG_POWER ? true
1410 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001411 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001413 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001414 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415
Jack Palevichb90d28c2009-07-22 15:35:24 -07001416 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1417 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1418
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001419 mConfiguration.setToDefaults();
1420 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 mProcessStats.init();
1422
1423 // Add ourself to the Watchdog monitors.
1424 Watchdog.getInstance().addMonitor(this);
1425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 mProcessStatsThread = new Thread("ProcessStats") {
1427 public void run() {
1428 while (true) {
1429 try {
1430 try {
1431 synchronized(this) {
1432 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001433 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001435 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 // + ", write delay=" + nextWriteDelay);
1437 if (nextWriteDelay < nextCpuDelay) {
1438 nextCpuDelay = nextWriteDelay;
1439 }
1440 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001441 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 this.wait(nextCpuDelay);
1443 }
1444 }
1445 } catch (InterruptedException e) {
1446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 updateCpuStatsNow();
1448 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001449 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 }
1451 }
1452 }
1453 };
1454 mProcessStatsThread.start();
1455 }
1456
1457 @Override
1458 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1459 throws RemoteException {
1460 try {
1461 return super.onTransact(code, data, reply, flags);
1462 } catch (RuntimeException e) {
1463 // The activity manager only throws security exceptions, so let's
1464 // log all others.
1465 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001466 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 }
1468 throw e;
1469 }
1470 }
1471
1472 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001473 final long now = SystemClock.uptimeMillis();
1474 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1475 return;
1476 }
1477 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1478 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 mProcessStatsThread.notify();
1480 }
1481 }
1482 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 void updateCpuStatsNow() {
1485 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001486 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 final long now = SystemClock.uptimeMillis();
1488 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001491 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1492 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 haveNewCpuStats = true;
1494 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001495 //Slog.i(TAG, mProcessStats.printCurrentState());
1496 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 // + mProcessStats.getTotalCpuPercent() + "%");
1498
Joe Onorato8a9b2202010-02-26 18:56:32 -08001499 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 if ("true".equals(SystemProperties.get("events.cpu"))) {
1501 int user = mProcessStats.getLastUserTime();
1502 int system = mProcessStats.getLastSystemTime();
1503 int iowait = mProcessStats.getLastIoWaitTime();
1504 int irq = mProcessStats.getLastIrqTime();
1505 int softIrq = mProcessStats.getLastSoftIrqTime();
1506 int idle = mProcessStats.getLastIdleTime();
1507
1508 int total = user + system + iowait + irq + softIrq + idle;
1509 if (total == 0) total = 1;
1510
Doug Zongker2bec3d42009-12-04 12:52:44 -08001511 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 ((user+system+iowait+irq+softIrq) * 100) / total,
1513 (user * 100) / total,
1514 (system * 100) / total,
1515 (iowait * 100) / total,
1516 (irq * 100) / total,
1517 (softIrq * 100) / total);
1518 }
1519 }
1520
Amith Yamasanie43530a2009-08-21 13:11:37 -07001521 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001522 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001523 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 synchronized(mPidsSelfLocked) {
1525 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001526 if (mOnBattery) {
1527 int perc = bstats.startAddingCpuLocked();
1528 int totalUTime = 0;
1529 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001530 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001532 ProcessStats.Stats st = mProcessStats.getStats(i);
1533 if (!st.working) {
1534 continue;
1535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001537 int otherUTime = (st.rel_utime*perc)/100;
1538 int otherSTime = (st.rel_stime*perc)/100;
1539 totalUTime += otherUTime;
1540 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541 if (pr != null) {
1542 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001543 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1544 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001545 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001546 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001547 } else {
1548 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001549 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001550 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001551 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1552 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001553 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 }
1556 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001557 bstats.finishAddingCpuLocked(perc, totalUTime,
1558 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
1560 }
1561 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1564 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001565 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 }
1567 }
1568 }
1569 }
1570
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001571 @Override
1572 public void batteryNeedsCpuUpdate() {
1573 updateCpuStatsNow();
1574 }
1575
1576 @Override
1577 public void batteryPowerChanged(boolean onBattery) {
1578 // When plugging in, update the CPU stats first before changing
1579 // the plug state.
1580 updateCpuStatsNow();
1581 synchronized (this) {
1582 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001583 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001584 }
1585 }
1586 }
1587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 /**
1589 * Initialize the application bind args. These are passed to each
1590 * process when the bindApplication() IPC is sent to the process. They're
1591 * lazily setup to make sure the services are running when they're asked for.
1592 */
1593 private HashMap<String, IBinder> getCommonServicesLocked() {
1594 if (mAppBindArgs == null) {
1595 mAppBindArgs = new HashMap<String, IBinder>();
1596
1597 // Setup the application init args
1598 mAppBindArgs.put("package", ServiceManager.getService("package"));
1599 mAppBindArgs.put("window", ServiceManager.getService("window"));
1600 mAppBindArgs.put(Context.ALARM_SERVICE,
1601 ServiceManager.getService(Context.ALARM_SERVICE));
1602 }
1603 return mAppBindArgs;
1604 }
1605
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001606 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 if (mFocusedActivity != r) {
1608 mFocusedActivity = r;
1609 mWindowManager.setFocusedApp(r, true);
1610 }
1611 }
1612
Dianne Hackborn906497c2010-05-10 15:57:38 -07001613 private final void updateLruProcessInternalLocked(ProcessRecord app,
1614 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001616 int lrui = mLruProcesses.indexOf(app);
1617 if (lrui >= 0) mLruProcesses.remove(lrui);
1618
1619 int i = mLruProcesses.size()-1;
1620 int skipTop = 0;
1621
Dianne Hackborn906497c2010-05-10 15:57:38 -07001622 app.lruSeq = mLruSeq;
1623
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001624 // compute the new weight for this process.
1625 if (updateActivityTime) {
1626 app.lastActivityTime = SystemClock.uptimeMillis();
1627 }
1628 if (app.activities.size() > 0) {
1629 // If this process has activities, we more strongly want to keep
1630 // it around.
1631 app.lruWeight = app.lastActivityTime;
1632 } else if (app.pubProviders.size() > 0) {
1633 // If this process contains content providers, we want to keep
1634 // it a little more strongly.
1635 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1636 // Also don't let it kick out the first few "real" hidden processes.
1637 skipTop = MIN_HIDDEN_APPS;
1638 } else {
1639 // If this process doesn't have activities, we less strongly
1640 // want to keep it around, and generally want to avoid getting
1641 // in front of any very recently used activities.
1642 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1643 // Also don't let it kick out the first few "real" hidden processes.
1644 skipTop = MIN_HIDDEN_APPS;
1645 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001646
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001647 while (i >= 0) {
1648 ProcessRecord p = mLruProcesses.get(i);
1649 // If this app shouldn't be in front of the first N background
1650 // apps, then skip over that many that are currently hidden.
1651 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1652 skipTop--;
1653 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001654 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001655 mLruProcesses.add(i+1, app);
1656 break;
1657 }
1658 i--;
1659 }
1660 if (i < 0) {
1661 mLruProcesses.add(0, app);
1662 }
1663
Dianne Hackborn906497c2010-05-10 15:57:38 -07001664 // If the app is currently using a content provider or service,
1665 // bump those processes as well.
1666 if (app.connections.size() > 0) {
1667 for (ConnectionRecord cr : app.connections) {
1668 if (cr.binding != null && cr.binding.service != null
1669 && cr.binding.service.app != null
1670 && cr.binding.service.app.lruSeq != mLruSeq) {
1671 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1672 updateActivityTime, i+1);
1673 }
1674 }
1675 }
1676 if (app.conProviders.size() > 0) {
1677 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1678 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1679 updateLruProcessInternalLocked(cpr.app, oomAdj,
1680 updateActivityTime, i+1);
1681 }
1682 }
1683 }
1684
Joe Onorato8a9b2202010-02-26 18:56:32 -08001685 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001686 if (oomAdj) {
1687 updateOomAdjLocked();
1688 }
1689 }
1690
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001691 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001692 boolean oomAdj, boolean updateActivityTime) {
1693 mLruSeq++;
1694 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1695 }
1696
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001697 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 String processName, int uid) {
1699 if (uid == Process.SYSTEM_UID) {
1700 // The system gets to run in any process. If there are multiple
1701 // processes with the same uid, just pick the first (this
1702 // should never happen).
1703 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1704 processName);
1705 return procs != null ? procs.valueAt(0) : null;
1706 }
1707 ProcessRecord proc = mProcessNames.get(processName, uid);
1708 return proc;
1709 }
1710
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001711 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001712 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001713 try {
1714 if (pm.performDexOpt(packageName)) {
1715 mDidDexOpt = true;
1716 }
1717 } catch (RemoteException e) {
1718 }
1719 }
1720
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001721 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 int transit = mWindowManager.getPendingAppTransition();
1723 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1724 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1725 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1726 }
1727
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001728 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001730 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1732 // We don't have to do anything more if:
1733 // (1) There is an existing application record; and
1734 // (2) The caller doesn't think it is dead, OR there is no thread
1735 // object attached to it so we know it couldn't have crashed; and
1736 // (3) There is a pid assigned to it, so it is either starting or
1737 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001738 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 + " app=" + app + " knownToBeDead=" + knownToBeDead
1740 + " thread=" + (app != null ? app.thread : null)
1741 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001742 if (app != null && app.pid > 0) {
1743 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001744 // We already have the app running, or are waiting for it to
1745 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001746 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001747 return app;
1748 } else {
1749 // An application record is attached to a previous process,
1750 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001751 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001752 handleAppDiedLocked(app, true);
1753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 String hostingNameStr = hostingName != null
1757 ? hostingName.flattenToShortString() : null;
1758
1759 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1760 // If we are in the background, then check to see if this process
1761 // is bad. If so, we will just silently fail.
1762 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001763 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1764 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 return null;
1766 }
1767 } else {
1768 // When the user is explicitly starting a process, then clear its
1769 // crash count so that we won't make it bad until they see at
1770 // least one crash dialog again, and make the process good again
1771 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001772 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1773 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 mProcessCrashTimes.remove(info.processName, info.uid);
1775 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001776 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 info.processName);
1778 mBadProcesses.remove(info.processName, info.uid);
1779 if (app != null) {
1780 app.bad = false;
1781 }
1782 }
1783 }
1784
1785 if (app == null) {
1786 app = newProcessRecordLocked(null, info, processName);
1787 mProcessNames.put(processName, info.uid, app);
1788 } else {
1789 // If this is a new package in the process, add the package to the list
1790 app.addPackage(info.packageName);
1791 }
1792
1793 // If the system is not ready yet, then hold off on starting this
1794 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001795 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001796 && !isAllowedWhileBooting(info)
1797 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 if (!mProcessesOnHold.contains(app)) {
1799 mProcessesOnHold.add(app);
1800 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001801 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 return app;
1803 }
1804
1805 startProcessLocked(app, hostingType, hostingNameStr);
1806 return (app.pid != 0) ? app : null;
1807 }
1808
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001809 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1810 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1811 }
1812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001813 private final void startProcessLocked(ProcessRecord app,
1814 String hostingType, String hostingNameStr) {
1815 if (app.pid > 0 && app.pid != MY_PID) {
1816 synchronized (mPidsSelfLocked) {
1817 mPidsSelfLocked.remove(app.pid);
1818 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1819 }
1820 app.pid = 0;
1821 }
1822
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001823 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1824 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 mProcessesOnHold.remove(app);
1826
1827 updateCpuStats();
1828
1829 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1830 mProcDeaths[0] = 0;
1831
1832 try {
1833 int uid = app.info.uid;
1834 int[] gids = null;
1835 try {
1836 gids = mContext.getPackageManager().getPackageGids(
1837 app.info.packageName);
1838 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001839 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 }
1841 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1842 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1843 && mTopComponent != null
1844 && app.processName.equals(mTopComponent.getPackageName())) {
1845 uid = 0;
1846 }
1847 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1848 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1849 uid = 0;
1850 }
1851 }
1852 int debugFlags = 0;
1853 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1854 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1855 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001856 // Run the app in safe mode if its manifest requests so or the
1857 // system is booted in safe mode.
1858 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1859 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001860 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1863 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1864 }
1865 if ("1".equals(SystemProperties.get("debug.assert"))) {
1866 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1867 }
1868 int pid = Process.start("android.app.ActivityThread",
1869 mSimpleProcessManagement ? app.processName : null, uid, uid,
1870 gids, debugFlags, null);
1871 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1872 synchronized (bs) {
1873 if (bs.isOnBattery()) {
1874 app.batteryStats.incStartsLocked();
1875 }
1876 }
1877
Doug Zongker2bec3d42009-12-04 12:52:44 -08001878 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 app.processName, hostingType,
1880 hostingNameStr != null ? hostingNameStr : "");
1881
1882 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001883 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 }
1885
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001886 StringBuilder buf = mStringBuilder;
1887 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 buf.append("Start proc ");
1889 buf.append(app.processName);
1890 buf.append(" for ");
1891 buf.append(hostingType);
1892 if (hostingNameStr != null) {
1893 buf.append(" ");
1894 buf.append(hostingNameStr);
1895 }
1896 buf.append(": pid=");
1897 buf.append(pid);
1898 buf.append(" uid=");
1899 buf.append(uid);
1900 buf.append(" gids={");
1901 if (gids != null) {
1902 for (int gi=0; gi<gids.length; gi++) {
1903 if (gi != 0) buf.append(", ");
1904 buf.append(gids[gi]);
1905
1906 }
1907 }
1908 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001909 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 if (pid == 0 || pid == MY_PID) {
1911 // Processes are being emulated with threads.
1912 app.pid = MY_PID;
1913 app.removed = false;
1914 mStartingProcesses.add(app);
1915 } else if (pid > 0) {
1916 app.pid = pid;
1917 app.removed = false;
1918 synchronized (mPidsSelfLocked) {
1919 this.mPidsSelfLocked.put(pid, app);
1920 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1921 msg.obj = app;
1922 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1923 }
1924 } else {
1925 app.pid = 0;
1926 RuntimeException e = new RuntimeException(
1927 "Failure starting process " + app.processName
1928 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001929 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 }
1931 } catch (RuntimeException e) {
1932 // XXX do better error recovery.
1933 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001934 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 }
1936 }
1937
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001938 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 if (resumed) {
1940 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1941 } else {
1942 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1943 }
1944 }
1945
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001946 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001947 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1948 && mTopAction == null) {
1949 // We are running in factory test mode, but unable to find
1950 // the factory test app, so just sit around displaying the
1951 // error message and don't try to start anything.
1952 return false;
1953 }
1954 Intent intent = new Intent(
1955 mTopAction,
1956 mTopData != null ? Uri.parse(mTopData) : null);
1957 intent.setComponent(mTopComponent);
1958 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1959 intent.addCategory(Intent.CATEGORY_HOME);
1960 }
1961 ActivityInfo aInfo =
1962 intent.resolveActivityInfo(mContext.getPackageManager(),
1963 STOCK_PM_FLAGS);
1964 if (aInfo != null) {
1965 intent.setComponent(new ComponentName(
1966 aInfo.applicationInfo.packageName, aInfo.name));
1967 // Don't do this if the home app is currently being
1968 // instrumented.
1969 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1970 aInfo.applicationInfo.uid);
1971 if (app == null || app.instrumentationClass == null) {
1972 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001973 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001974 null, null, 0, 0, 0, false, false);
1975 }
1976 }
1977
1978
1979 return true;
1980 }
1981
1982 /**
1983 * Starts the "new version setup screen" if appropriate.
1984 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001985 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001986 // Only do this once per boot.
1987 if (mCheckedForSetup) {
1988 return;
1989 }
1990
1991 // We will show this screen if the current one is a different
1992 // version than the last one shown, and we are not running in
1993 // low-level factory test mode.
1994 final ContentResolver resolver = mContext.getContentResolver();
1995 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1996 Settings.Secure.getInt(resolver,
1997 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1998 mCheckedForSetup = true;
1999
2000 // See if we should be showing the platform update setup UI.
2001 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2002 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2003 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2004
2005 // We don't allow third party apps to replace this.
2006 ResolveInfo ri = null;
2007 for (int i=0; ris != null && i<ris.size(); i++) {
2008 if ((ris.get(i).activityInfo.applicationInfo.flags
2009 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2010 ri = ris.get(i);
2011 break;
2012 }
2013 }
2014
2015 if (ri != null) {
2016 String vers = ri.activityInfo.metaData != null
2017 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2018 : null;
2019 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2020 vers = ri.activityInfo.applicationInfo.metaData.getString(
2021 Intent.METADATA_SETUP_VERSION);
2022 }
2023 String lastVers = Settings.Secure.getString(
2024 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2025 if (vers != null && !vers.equals(lastVers)) {
2026 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2027 intent.setComponent(new ComponentName(
2028 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002029 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002030 null, null, 0, 0, 0, false, false);
2031 }
2032 }
2033 }
2034 }
2035
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002036 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002037 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002038
2039 final int identHash = System.identityHashCode(r);
2040 updateUsageStats(r, true);
2041
2042 int i = mWatchers.beginBroadcast();
2043 while (i > 0) {
2044 i--;
2045 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2046 if (w != null) {
2047 try {
2048 w.activityResuming(identHash);
2049 } catch (RemoteException e) {
2050 }
2051 }
2052 }
2053 mWatchers.finishBroadcast();
2054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002056 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002057 final int N = mPendingActivityLaunches.size();
2058 if (N <= 0) {
2059 return;
2060 }
2061 for (int i=0; i<N; i++) {
2062 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002063 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002064 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2065 doResume && i == (N-1));
2066 }
2067 mPendingActivityLaunches.clear();
2068 }
2069
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002070 public final int startActivity(IApplicationThread caller,
2071 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2072 int grantedMode, IBinder resultTo,
2073 String resultWho, int requestCode, boolean onlyIfNeeded,
2074 boolean debug) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002075 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002076 grantedUriPermissions, grantedMode, resultTo, resultWho,
2077 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002078 }
2079
2080 public final WaitResult startActivityAndWait(IApplicationThread caller,
2081 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2082 int grantedMode, IBinder resultTo,
2083 String resultWho, int requestCode, boolean onlyIfNeeded,
2084 boolean debug) {
2085 WaitResult res = new WaitResult();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002086 mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002087 grantedUriPermissions, grantedMode, resultTo, resultWho,
2088 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002089 return res;
2090 }
2091
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002092 public final int startActivityWithConfig(IApplicationThread caller,
2093 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2094 int grantedMode, IBinder resultTo,
2095 String resultWho, int requestCode, boolean onlyIfNeeded,
2096 boolean debug, Configuration config) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002097 return mMainStack.startActivityMayWait(caller, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002098 grantedUriPermissions, grantedMode, resultTo, resultWho,
2099 requestCode, onlyIfNeeded, debug, null, config);
2100 }
2101
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002102 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002103 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002104 IBinder resultTo, String resultWho, int requestCode,
2105 int flagsMask, int flagsValues) {
2106 // Refuse possible leaked file descriptors
2107 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2108 throw new IllegalArgumentException("File descriptors passed in Intent");
2109 }
2110
2111 IIntentSender sender = intent.getTarget();
2112 if (!(sender instanceof PendingIntentRecord)) {
2113 throw new IllegalArgumentException("Bad PendingIntent object");
2114 }
2115
2116 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002117
2118 synchronized (this) {
2119 // If this is coming from the currently resumed activity, it is
2120 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002121 if (mMainStack.mResumedActivity != null
2122 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002123 Binder.getCallingUid()) {
2124 mAppSwitchesAllowedTime = 0;
2125 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002126 }
2127
2128 return pir.sendInner(0, fillInIntent, resolvedType,
2129 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2130 }
2131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 public boolean startNextMatchingActivity(IBinder callingActivity,
2133 Intent intent) {
2134 // Refuse possible leaked file descriptors
2135 if (intent != null && intent.hasFileDescriptors() == true) {
2136 throw new IllegalArgumentException("File descriptors passed in Intent");
2137 }
2138
2139 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002140 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 if (index < 0) {
2142 return false;
2143 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002144 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 if (r.app == null || r.app.thread == null) {
2146 // The caller is not running... d'oh!
2147 return false;
2148 }
2149 intent = new Intent(intent);
2150 // The caller is not allowed to change the data.
2151 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2152 // And we are resetting to find the next component...
2153 intent.setComponent(null);
2154
2155 ActivityInfo aInfo = null;
2156 try {
2157 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002158 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002160 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002161
2162 // Look for the original activity in the list...
2163 final int N = resolves != null ? resolves.size() : 0;
2164 for (int i=0; i<N; i++) {
2165 ResolveInfo rInfo = resolves.get(i);
2166 if (rInfo.activityInfo.packageName.equals(r.packageName)
2167 && rInfo.activityInfo.name.equals(r.info.name)) {
2168 // We found the current one... the next matching is
2169 // after it.
2170 i++;
2171 if (i<N) {
2172 aInfo = resolves.get(i).activityInfo;
2173 }
2174 break;
2175 }
2176 }
2177 } catch (RemoteException e) {
2178 }
2179
2180 if (aInfo == null) {
2181 // Nobody who is next!
2182 return false;
2183 }
2184
2185 intent.setComponent(new ComponentName(
2186 aInfo.applicationInfo.packageName, aInfo.name));
2187 intent.setFlags(intent.getFlags()&~(
2188 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2189 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2190 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2191 Intent.FLAG_ACTIVITY_NEW_TASK));
2192
2193 // Okay now we need to start the new activity, replacing the
2194 // currently running activity. This is a little tricky because
2195 // we want to start the new one as if the current one is finished,
2196 // but not finish the current one first so that there is no flicker.
2197 // And thus...
2198 final boolean wasFinishing = r.finishing;
2199 r.finishing = true;
2200
2201 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002202 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 final String resultWho = r.resultWho;
2204 final int requestCode = r.requestCode;
2205 r.resultTo = null;
2206 if (resultTo != null) {
2207 resultTo.removeResultsLocked(r, resultWho, requestCode);
2208 }
2209
2210 final long origId = Binder.clearCallingIdentity();
2211 // XXX we are not dealing with propagating grantedUriPermissions...
2212 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002213 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002215 requestCode, -1, r.launchedFromUid, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 Binder.restoreCallingIdentity(origId);
2217
2218 r.finishing = wasFinishing;
2219 if (res != START_SUCCESS) {
2220 return false;
2221 }
2222 return true;
2223 }
2224 }
2225
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002226 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 Intent intent, String resolvedType, IBinder resultTo,
2228 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002229
2230 // This is so super not safe, that only the system (or okay root)
2231 // can do it.
2232 final int callingUid = Binder.getCallingUid();
2233 if (callingUid != 0 && callingUid != Process.myUid()) {
2234 throw new SecurityException(
2235 "startActivityInPackage only available to the system");
2236 }
2237
The Android Open Source Project4df24232009-03-05 14:34:35 -08002238 final boolean componentSpecified = intent.getComponent() != null;
2239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002240 // Don't modify the client's object!
2241 intent = new Intent(intent);
2242
2243 // Collect information about the target of the Intent.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 ActivityInfo aInfo;
2245 try {
2246 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002247 AppGlobals.getPackageManager().resolveIntent(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 intent, resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002249 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 aInfo = rInfo != null ? rInfo.activityInfo : null;
2251 } catch (RemoteException e) {
2252 aInfo = null;
2253 }
2254
2255 if (aInfo != null) {
2256 // Store the found target back into the intent, because now that
2257 // we have it we never want to do this again. For example, if the
2258 // user navigates back to this point in the history, we should
2259 // always restart the exact same activity.
2260 intent.setComponent(new ComponentName(
2261 aInfo.applicationInfo.packageName, aInfo.name));
2262 }
2263
2264 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002265 return mMainStack.startActivityLocked(null, intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
The Android Open Source Project4df24232009-03-05 14:34:35 -08002267 onlyIfNeeded, componentSpecified);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 }
2269 }
2270
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002271 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 // Remove any existing entries that are the same kind of task.
2273 int N = mRecentTasks.size();
2274 for (int i=0; i<N; i++) {
2275 TaskRecord tr = mRecentTasks.get(i);
2276 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2277 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2278 mRecentTasks.remove(i);
2279 i--;
2280 N--;
2281 if (task.intent == null) {
2282 // If the new recent task we are adding is not fully
2283 // specified, then replace it with the existing recent task.
2284 task = tr;
2285 }
2286 }
2287 }
2288 if (N >= MAX_RECENT_TASKS) {
2289 mRecentTasks.remove(N-1);
2290 }
2291 mRecentTasks.add(0, task);
2292 }
2293
2294 public void setRequestedOrientation(IBinder token,
2295 int requestedOrientation) {
2296 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002297 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002298 if (index < 0) {
2299 return;
2300 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002301 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302 final long origId = Binder.clearCallingIdentity();
2303 mWindowManager.setAppOrientation(r, requestedOrientation);
2304 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002305 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306 r.mayFreezeScreenLocked(r.app) ? r : null);
2307 if (config != null) {
2308 r.frozenBeforeDestroy = true;
2309 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002310 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 }
2312 }
2313 Binder.restoreCallingIdentity(origId);
2314 }
2315 }
2316
2317 public int getRequestedOrientation(IBinder token) {
2318 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002319 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 if (index < 0) {
2321 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2322 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002323 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 return mWindowManager.getAppOrientation(r);
2325 }
2326 }
2327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 /**
2329 * This is the internal entry point for handling Activity.finish().
2330 *
2331 * @param token The Binder token referencing the Activity we want to finish.
2332 * @param resultCode Result code, if any, from this Activity.
2333 * @param resultData Result data (Intent), if any, from this Activity.
2334 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002335 * @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 -08002336 */
2337 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2338 // Refuse possible leaked file descriptors
2339 if (resultData != null && resultData.hasFileDescriptors() == true) {
2340 throw new IllegalArgumentException("File descriptors passed in Intent");
2341 }
2342
2343 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002344 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002346 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 if (next != null) {
2348 // ask watcher if this is allowed
2349 boolean resumeOK = true;
2350 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002351 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002353 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 }
2355
2356 if (!resumeOK) {
2357 return false;
2358 }
2359 }
2360 }
2361 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002362 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 resultData, "app-request");
2364 Binder.restoreCallingIdentity(origId);
2365 return res;
2366 }
2367 }
2368
Dianne Hackborn860755f2010-06-03 18:47:52 -07002369 public final void finishHeavyWeightApp() {
2370 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2371 != PackageManager.PERMISSION_GRANTED) {
2372 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2373 + Binder.getCallingPid()
2374 + ", uid=" + Binder.getCallingUid()
2375 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2376 Slog.w(TAG, msg);
2377 throw new SecurityException(msg);
2378 }
2379
2380 synchronized(this) {
2381 if (mHeavyWeightProcess == null) {
2382 return;
2383 }
2384
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002385 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002386 mHeavyWeightProcess.activities);
2387 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002388 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002389 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002390 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002391 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002392 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002393 null, "finish-heavy");
2394 }
2395 }
2396 }
2397
2398 mHeavyWeightProcess = null;
2399 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2400 }
2401 }
2402
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002403 public void crashApplication(int uid, int initialPid, String packageName,
2404 String message) {
2405 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2406 != PackageManager.PERMISSION_GRANTED) {
2407 String msg = "Permission Denial: crashApplication() from pid="
2408 + Binder.getCallingPid()
2409 + ", uid=" + Binder.getCallingUid()
2410 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2411 Slog.w(TAG, msg);
2412 throw new SecurityException(msg);
2413 }
2414
2415 synchronized(this) {
2416 ProcessRecord proc = null;
2417
2418 // Figure out which process to kill. We don't trust that initialPid
2419 // still has any relation to current pids, so must scan through the
2420 // list.
2421 synchronized (mPidsSelfLocked) {
2422 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2423 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2424 if (p.info.uid != uid) {
2425 continue;
2426 }
2427 if (p.pid == initialPid) {
2428 proc = p;
2429 break;
2430 }
2431 for (String str : p.pkgList) {
2432 if (str.equals(packageName)) {
2433 proc = p;
2434 }
2435 }
2436 }
2437 }
2438
2439 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002440 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002441 + " initialPid=" + initialPid
2442 + " packageName=" + packageName);
2443 return;
2444 }
2445
2446 if (proc.thread != null) {
2447 long ident = Binder.clearCallingIdentity();
2448 try {
2449 proc.thread.scheduleCrash(message);
2450 } catch (RemoteException e) {
2451 }
2452 Binder.restoreCallingIdentity(ident);
2453 }
2454 }
2455 }
2456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 public final void finishSubActivity(IBinder token, String resultWho,
2458 int requestCode) {
2459 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002460 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002461 if (index < 0) {
2462 return;
2463 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002464 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002465
2466 final long origId = Binder.clearCallingIdentity();
2467
2468 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002469 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2470 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471 if (r.resultTo == self && r.requestCode == requestCode) {
2472 if ((r.resultWho == null && resultWho == null) ||
2473 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002474 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002475 Activity.RESULT_CANCELED, null, "request-sub");
2476 }
2477 }
2478 }
2479
2480 Binder.restoreCallingIdentity(origId);
2481 }
2482 }
2483
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002484 public boolean willActivityBeVisible(IBinder token) {
2485 synchronized(this) {
2486 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002487 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2488 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002489 if (r == token) {
2490 return true;
2491 }
2492 if (r.fullscreen && !r.finishing) {
2493 return false;
2494 }
2495 }
2496 return true;
2497 }
2498 }
2499
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002500 public void overridePendingTransition(IBinder token, String packageName,
2501 int enterAnim, int exitAnim) {
2502 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002503 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002504 if (index < 0) {
2505 return;
2506 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002507 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002508
2509 final long origId = Binder.clearCallingIdentity();
2510
2511 if (self.state == ActivityState.RESUMED
2512 || self.state == ActivityState.PAUSING) {
2513 mWindowManager.overridePendingAppTransition(packageName,
2514 enterAnim, exitAnim);
2515 }
2516
2517 Binder.restoreCallingIdentity(origId);
2518 }
2519 }
2520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002522 * Main function for removing an existing process from the activity manager
2523 * as a result of that process going away. Clears out all connections
2524 * to the process.
2525 */
2526 private final void handleAppDiedLocked(ProcessRecord app,
2527 boolean restarting) {
2528 cleanUpApplicationRecordLocked(app, restarting, -1);
2529 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002530 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002531 }
2532
2533 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002534 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2535 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2536 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002538 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2539 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002540 }
2541
2542 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002543 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544
2545 boolean atTop = true;
2546 boolean hasVisibleActivities = false;
2547
2548 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002549 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002550 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 TAG, "Removing app " + app + " from history with " + i + " entries");
2552 while (i > 0) {
2553 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002554 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002555 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002556 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2557 if (r.app == app) {
2558 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002559 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 TAG, "Removing this entry! frozen=" + r.haveState
2561 + " finishing=" + r.finishing);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002562 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002563
2564 r.inHistory = false;
2565 mWindowManager.removeAppToken(r);
2566 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002567 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002569 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570
2571 } else {
2572 // We have the current state for this activity, so
2573 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002574 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002575 TAG, "Keeping entry, setting app to null");
2576 if (r.visible) {
2577 hasVisibleActivities = true;
2578 }
2579 r.app = null;
2580 r.nowVisible = false;
2581 if (!r.haveState) {
2582 r.icicle = null;
2583 }
2584 }
2585
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002586 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 r.state = ActivityState.STOPPED;
2588 }
2589 atTop = false;
2590 }
2591
2592 app.activities.clear();
2593
2594 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002595 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 + " running instrumentation " + app.instrumentationClass);
2597 Bundle info = new Bundle();
2598 info.putString("shortMsg", "Process crashed.");
2599 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2600 }
2601
2602 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002603 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 // If there was nothing to resume, and we are not already
2605 // restarting this process, but there is a visible activity that
2606 // is hosted by the process... then make sure all visible
2607 // activities are running, taking care of restarting this
2608 // process.
2609 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002610 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002611 }
2612 }
2613 }
2614 }
2615
2616 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2617 IBinder threadBinder = thread.asBinder();
2618
2619 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002620 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2621 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2623 return i;
2624 }
2625 }
2626 return -1;
2627 }
2628
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002629 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 IApplicationThread thread) {
2631 if (thread == null) {
2632 return null;
2633 }
2634
2635 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002636 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 }
2638
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002639 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 IApplicationThread thread) {
2641
2642 mProcDeaths[0]++;
2643
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002644 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2645 synchronized (stats) {
2646 stats.noteProcessDiedLocked(app.info.uid, pid);
2647 }
2648
Magnus Edlund7bb25812010-02-24 15:45:06 +01002649 // Clean up already done if the process has been re-started.
2650 if (app.pid == pid && app.thread != null &&
2651 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002652 if (!app.killedBackground) {
2653 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2654 + ") has died.");
2655 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002656 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002657 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658 TAG, "Dying app: " + app + ", pid: " + pid
2659 + ", thread: " + thread.asBinder());
2660 boolean doLowMem = app.instrumentationClass == null;
2661 handleAppDiedLocked(app, false);
2662
2663 if (doLowMem) {
2664 // If there are no longer any background processes running,
2665 // and the app that died was not running instrumentation,
2666 // then tell everyone we are now low on memory.
2667 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002668 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2669 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002670 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2671 haveBg = true;
2672 break;
2673 }
2674 }
2675
2676 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002677 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002678 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002679 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002680 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2681 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002682 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002683 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2684 // The low memory report is overriding any current
2685 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002686 // heavy/important/visible/foreground processes first.
2687 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002688 rec.lastRequestedGc = 0;
2689 } else {
2690 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002692 rec.reportLowMemory = true;
2693 rec.lastLowMemory = now;
2694 mProcessesToGc.remove(rec);
2695 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 }
2697 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002698 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 }
2700 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002701 } else if (app.pid != pid) {
2702 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002703 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002704 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002705 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002706 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002707 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 + thread.asBinder());
2709 }
2710 }
2711
Dan Egnor42471dd2010-01-07 17:25:22 -08002712 /**
2713 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002714 * @param clearTraces causes the dump file to be erased prior to the new
2715 * traces being written, if true; when false, the new traces will be
2716 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002717 * @param firstPids of dalvik VM processes to dump stack traces for first
2718 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002719 * @return file containing stack traces, or null if no dump file is configured
2720 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002721 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2722 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002723 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2724 if (tracesPath == null || tracesPath.length() == 0) {
2725 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002727
2728 File tracesFile = new File(tracesPath);
2729 try {
2730 File tracesDir = tracesFile.getParentFile();
2731 if (!tracesDir.exists()) tracesFile.mkdirs();
2732 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2733
Christopher Tate6ee412d2010-05-28 12:01:56 -07002734 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002735 tracesFile.createNewFile();
2736 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2737 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002738 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002739 return null;
2740 }
2741
2742 // Use a FileObserver to detect when traces finish writing.
2743 // The order of traces is considered important to maintain for legibility.
2744 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2745 public synchronized void onEvent(int event, String path) { notify(); }
2746 };
2747
2748 try {
2749 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002750
2751 // First collect all of the stacks of the most important pids.
2752 try {
2753 int num = firstPids.size();
2754 for (int i = 0; i < num; i++) {
2755 synchronized (observer) {
2756 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2757 observer.wait(200); // Wait for write-close, give up after 200msec
2758 }
2759 }
2760 } catch (InterruptedException e) {
2761 Log.wtf(TAG, e);
2762 }
2763
2764 // Next measure CPU usage.
2765 if (processStats != null) {
2766 processStats.init();
2767 System.gc();
2768 processStats.update();
2769 try {
2770 synchronized (processStats) {
2771 processStats.wait(500); // measure over 1/2 second.
2772 }
2773 } catch (InterruptedException e) {
2774 }
2775 processStats.update();
2776
2777 // We'll take the stack crawls of just the top apps using CPU.
2778 final int N = processStats.countWorkingStats();
2779 int numProcs = 0;
2780 for (int i=0; i<N && numProcs<5; i++) {
2781 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2782 if (lastPids.indexOfKey(stats.pid) >= 0) {
2783 numProcs++;
2784 try {
2785 synchronized (observer) {
2786 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2787 observer.wait(200); // Wait for write-close, give up after 200msec
2788 }
2789 } catch (InterruptedException e) {
2790 Log.wtf(TAG, e);
2791 }
2792
2793 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002794 }
2795 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002796
2797 return tracesFile;
2798
Dan Egnor42471dd2010-01-07 17:25:22 -08002799 } finally {
2800 observer.stopWatching();
2801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002802 }
2803
Jeff Brown4d94a762010-09-23 11:33:28 -07002804 private final class AppNotResponding implements Runnable {
2805 private final ProcessRecord mApp;
2806 private final String mAnnotation;
2807
2808 public AppNotResponding(ProcessRecord app, String annotation) {
2809 mApp = app;
2810 mAnnotation = annotation;
2811 }
2812
2813 @Override
2814 public void run() {
2815 appNotResponding(mApp, null, null, mAnnotation);
2816 }
2817 }
2818
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002819 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2820 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002821 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2822 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2823
Dianne Hackborn287952c2010-09-22 22:34:31 -07002824 if (mController != null) {
2825 try {
2826 // 0 == continue, -1 = kill process immediately
2827 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2828 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2829 } catch (RemoteException e) {
2830 mController = null;
2831 }
2832 }
2833
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002834 long anrTime = SystemClock.uptimeMillis();
2835 if (MONITOR_CPU_USAGE) {
2836 updateCpuStatsNow();
2837 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002838
2839 synchronized (this) {
2840 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2841 if (mShuttingDown) {
2842 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2843 return;
2844 } else if (app.notResponding) {
2845 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2846 return;
2847 } else if (app.crashing) {
2848 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2849 return;
2850 }
2851
2852 // In case we come through here for the same app before completing
2853 // this one, mark as anring now so we will bail out.
2854 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002855
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002856 // Log the ANR to the event log.
2857 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2858 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002859
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002860 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002861 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002862
2863 int parentPid = app.pid;
2864 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002865 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002866
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002867 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002868
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002869 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2870 ProcessRecord r = mLruProcesses.get(i);
2871 if (r != null && r.thread != null) {
2872 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002873 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2874 if (r.persistent) {
2875 firstPids.add(pid);
2876 } else {
2877 lastPids.put(pid, Boolean.TRUE);
2878 }
2879 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002881 }
2882 }
2883
Dan Egnor42471dd2010-01-07 17:25:22 -08002884 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002885 StringBuilder info = mStringBuilder;
2886 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002887 info.append("ANR in ").append(app.processName);
2888 if (activity != null && activity.shortComponentName != null) {
2889 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002890 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002891 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002893 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002895 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002896 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898
Dianne Hackborn287952c2010-09-22 22:34:31 -07002899 final ProcessStats processStats = new ProcessStats(true);
2900
2901 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2902
Dan Egnor42471dd2010-01-07 17:25:22 -08002903 String cpuInfo = null;
2904 if (MONITOR_CPU_USAGE) {
2905 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002906 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002907 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002908 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002909 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002910 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 }
2912
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002913 info.append(processStats.printCurrentState(anrTime));
2914
Joe Onorato8a9b2202010-02-26 18:56:32 -08002915 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002916 if (tracesFile == null) {
2917 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2918 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2919 }
2920
2921 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2922
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002923 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002925 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2926 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002927 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002928 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2929 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 }
2931 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002932 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 }
2934 }
2935
Dan Egnor42471dd2010-01-07 17:25:22 -08002936 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2937 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2938 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002939
2940 synchronized (this) {
2941 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2942 Process.killProcess(app.pid);
2943 return;
2944 }
2945
2946 // Set the app's notResponding state, and look up the errorReportReceiver
2947 makeAppNotRespondingLocked(app,
2948 activity != null ? activity.shortComponentName : null,
2949 annotation != null ? "ANR " + annotation : "ANR",
2950 info.toString());
2951
2952 // Bring up the infamous App Not Responding dialog
2953 Message msg = Message.obtain();
2954 HashMap map = new HashMap();
2955 msg.what = SHOW_NOT_RESPONDING_MSG;
2956 msg.obj = map;
2957 map.put("app", app);
2958 if (activity != null) {
2959 map.put("activity", activity);
2960 }
2961
2962 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08002963 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 }
2965
Dianne Hackborn0dad3642010-09-09 21:25:35 -07002966 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
2967 if (!mLaunchWarningShown) {
2968 mLaunchWarningShown = true;
2969 mHandler.post(new Runnable() {
2970 @Override
2971 public void run() {
2972 synchronized (ActivityManagerService.this) {
2973 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
2974 d.show();
2975 mHandler.postDelayed(new Runnable() {
2976 @Override
2977 public void run() {
2978 synchronized (ActivityManagerService.this) {
2979 d.dismiss();
2980 mLaunchWarningShown = false;
2981 }
2982 }
2983 }, 4000);
2984 }
2985 }
2986 });
2987 }
2988 }
2989
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002990 final void decPersistentCountLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 app.persistentActivities--;
2992 if (app.persistentActivities > 0) {
2993 // Still more of 'em...
2994 return;
2995 }
2996 if (app.persistent) {
2997 // Ah, but the application itself is persistent. Whatever!
2998 return;
2999 }
3000
3001 // App is no longer persistent... make sure it and the ones
3002 // following it in the LRU list have the correc oom_adj.
3003 updateOomAdjLocked();
3004 }
3005
3006 public void setPersistent(IBinder token, boolean isPersistent) {
3007 if (checkCallingPermission(android.Manifest.permission.PERSISTENT_ACTIVITY)
3008 != PackageManager.PERMISSION_GRANTED) {
3009 String msg = "Permission Denial: setPersistent() from pid="
3010 + Binder.getCallingPid()
3011 + ", uid=" + Binder.getCallingUid()
3012 + " requires " + android.Manifest.permission.PERSISTENT_ACTIVITY;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003013 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003014 throw new SecurityException(msg);
3015 }
3016
3017 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003018 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 if (index < 0) {
3020 return;
3021 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003022 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 ProcessRecord app = r.app;
3024
Joe Onorato8a9b2202010-02-26 18:56:32 -08003025 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 TAG, "Setting persistence " + isPersistent + ": " + r);
3027
3028 if (isPersistent) {
3029 if (r.persistent) {
3030 // Okay okay, I heard you already!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003031 if (localLOGV) Slog.v(TAG, "Already persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003032 return;
3033 }
3034 r.persistent = true;
3035 app.persistentActivities++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003036 if (localLOGV) Slog.v(TAG, "Num persistent now: " + app.persistentActivities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 if (app.persistentActivities > 1) {
3038 // We aren't the first...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003039 if (localLOGV) Slog.v(TAG, "Not the first!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003040 return;
3041 }
3042 if (app.persistent) {
3043 // This would be redundant.
Joe Onorato8a9b2202010-02-26 18:56:32 -08003044 if (localLOGV) Slog.v(TAG, "App is persistent!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 return;
3046 }
3047
3048 // App is now persistent... make sure it and the ones
3049 // following it now have the correct oom_adj.
3050 final long origId = Binder.clearCallingIdentity();
3051 updateOomAdjLocked();
3052 Binder.restoreCallingIdentity(origId);
3053
3054 } else {
3055 if (!r.persistent) {
3056 // Okay okay, I heard you already!
3057 return;
3058 }
3059 r.persistent = false;
3060 final long origId = Binder.clearCallingIdentity();
3061 decPersistentCountLocked(app);
3062 Binder.restoreCallingIdentity(origId);
3063
3064 }
3065 }
3066 }
3067
3068 public boolean clearApplicationUserData(final String packageName,
3069 final IPackageDataObserver observer) {
3070 int uid = Binder.getCallingUid();
3071 int pid = Binder.getCallingPid();
3072 long callingId = Binder.clearCallingIdentity();
3073 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003074 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 int pkgUid = -1;
3076 synchronized(this) {
3077 try {
3078 pkgUid = pm.getPackageUid(packageName);
3079 } catch (RemoteException e) {
3080 }
3081 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003082 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 return false;
3084 }
3085 if (uid == pkgUid || checkComponentPermission(
3086 android.Manifest.permission.CLEAR_APP_USER_DATA,
3087 pid, uid, -1)
3088 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003089 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 } else {
3091 throw new SecurityException(pid+" does not have permission:"+
3092 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3093 "for process:"+packageName);
3094 }
3095 }
3096
3097 try {
3098 //clear application user data
3099 pm.clearApplicationUserData(packageName, observer);
3100 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3101 Uri.fromParts("package", packageName, null));
3102 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003103 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3104 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 } catch (RemoteException e) {
3106 }
3107 } finally {
3108 Binder.restoreCallingIdentity(callingId);
3109 }
3110 return true;
3111 }
3112
Dianne Hackborn03abb812010-01-04 18:43:19 -08003113 public void killBackgroundProcesses(final String packageName) {
3114 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3115 != PackageManager.PERMISSION_GRANTED &&
3116 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3117 != PackageManager.PERMISSION_GRANTED) {
3118 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 + Binder.getCallingPid()
3120 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003121 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003122 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003123 throw new SecurityException(msg);
3124 }
3125
3126 long callingId = Binder.clearCallingIdentity();
3127 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003128 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003129 int pkgUid = -1;
3130 synchronized(this) {
3131 try {
3132 pkgUid = pm.getPackageUid(packageName);
3133 } catch (RemoteException e) {
3134 }
3135 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003136 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 return;
3138 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003139 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003140 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003141 }
3142 } finally {
3143 Binder.restoreCallingIdentity(callingId);
3144 }
3145 }
3146
3147 public void forceStopPackage(final String packageName) {
3148 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3149 != PackageManager.PERMISSION_GRANTED) {
3150 String msg = "Permission Denial: forceStopPackage() from pid="
3151 + Binder.getCallingPid()
3152 + ", uid=" + Binder.getCallingUid()
3153 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003154 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003155 throw new SecurityException(msg);
3156 }
3157
3158 long callingId = Binder.clearCallingIdentity();
3159 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003160 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003161 int pkgUid = -1;
3162 synchronized(this) {
3163 try {
3164 pkgUid = pm.getPackageUid(packageName);
3165 } catch (RemoteException e) {
3166 }
3167 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003168 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003169 return;
3170 }
3171 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003172 }
3173 } finally {
3174 Binder.restoreCallingIdentity(callingId);
3175 }
3176 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003177
3178 /*
3179 * The pkg name and uid have to be specified.
3180 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3181 */
3182 public void killApplicationWithUid(String pkg, int uid) {
3183 if (pkg == null) {
3184 return;
3185 }
3186 // Make sure the uid is valid.
3187 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003188 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003189 return;
3190 }
3191 int callerUid = Binder.getCallingUid();
3192 // Only the system server can kill an application
3193 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003194 // Post an aysnc message to kill the application
3195 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3196 msg.arg1 = uid;
3197 msg.arg2 = 0;
3198 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003199 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003200 } else {
3201 throw new SecurityException(callerUid + " cannot kill pkg: " +
3202 pkg);
3203 }
3204 }
3205
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003206 public void closeSystemDialogs(String reason) {
3207 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003208 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003209 if (reason != null) {
3210 intent.putExtra("reason", reason);
3211 }
3212
3213 final int uid = Binder.getCallingUid();
3214 final long origId = Binder.clearCallingIdentity();
3215 synchronized (this) {
3216 int i = mWatchers.beginBroadcast();
3217 while (i > 0) {
3218 i--;
3219 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3220 if (w != null) {
3221 try {
3222 w.closingSystemDialogs(reason);
3223 } catch (RemoteException e) {
3224 }
3225 }
3226 }
3227 mWatchers.finishBroadcast();
3228
Dianne Hackbornffa42482009-09-23 22:20:11 -07003229 mWindowManager.closeSystemDialogs(reason);
3230
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003231 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3232 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003233 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003234 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003235 Activity.RESULT_CANCELED, null, "close-sys");
3236 }
3237 }
3238
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003239 broadcastIntentLocked(null, null, intent, null,
3240 null, 0, null, null, null, false, false, -1, uid);
3241 }
3242 Binder.restoreCallingIdentity(origId);
3243 }
3244
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003245 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003246 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003247 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3248 for (int i=pids.length-1; i>=0; i--) {
3249 infos[i] = new Debug.MemoryInfo();
3250 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003251 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003252 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003253 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003254
3255 public void killApplicationProcess(String processName, int uid) {
3256 if (processName == null) {
3257 return;
3258 }
3259
3260 int callerUid = Binder.getCallingUid();
3261 // Only the system server can kill an application
3262 if (callerUid == Process.SYSTEM_UID) {
3263 synchronized (this) {
3264 ProcessRecord app = getProcessRecordLocked(processName, uid);
3265 if (app != null) {
3266 try {
3267 app.thread.scheduleSuicide();
3268 } catch (RemoteException e) {
3269 // If the other end already died, then our work here is done.
3270 }
3271 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003272 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003273 + processName + " / " + uid);
3274 }
3275 }
3276 } else {
3277 throw new SecurityException(callerUid + " cannot kill app process: " +
3278 processName);
3279 }
3280 }
3281
Dianne Hackborn03abb812010-01-04 18:43:19 -08003282 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003283 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3285 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003286 if (!mProcessesReady) {
3287 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 intent.putExtra(Intent.EXTRA_UID, uid);
3290 broadcastIntentLocked(null, null, intent,
3291 null, null, 0, null, null, null,
3292 false, false, MY_PID, Process.SYSTEM_UID);
3293 }
3294
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003295 private final boolean killPackageProcessesLocked(String packageName, int uid,
3296 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003297 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298
Dianne Hackborn03abb812010-01-04 18:43:19 -08003299 // Remove all processes this package may have touched: all with the
3300 // same UID (except for the system or root user), and all whose name
3301 // matches the package name.
3302 final String procNamePrefix = packageName + ":";
3303 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3304 final int NA = apps.size();
3305 for (int ia=0; ia<NA; ia++) {
3306 ProcessRecord app = apps.valueAt(ia);
3307 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003308 if (doit) {
3309 procs.add(app);
3310 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003311 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3312 || app.processName.equals(packageName)
3313 || app.processName.startsWith(procNamePrefix)) {
3314 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003315 if (!doit) {
3316 return true;
3317 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003318 app.removed = true;
3319 procs.add(app);
3320 }
3321 }
3322 }
3323 }
3324
3325 int N = procs.size();
3326 for (int i=0; i<N; i++) {
3327 removeProcessLocked(procs.get(i), callerWillRestart);
3328 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003329 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003330 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003331
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003332 private final boolean forceStopPackageLocked(String name, int uid,
3333 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003334 int i, N;
3335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 if (uid < 0) {
3337 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003338 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 } catch (RemoteException e) {
3340 }
3341 }
3342
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003343 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003344 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003345
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003346 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3347 while (badApps.hasNext()) {
3348 SparseArray<Long> ba = badApps.next();
3349 if (ba.get(uid) != null) {
3350 badApps.remove();
3351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 }
3353 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003354
3355 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3356 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003358 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3359 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003360 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003361 if (!doit) {
3362 return true;
3363 }
3364 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003365 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 if (r.app != null) {
3367 r.app.removed = true;
3368 }
3369 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003370 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371 }
3372 }
3373
3374 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3375 for (ServiceRecord service : mServices.values()) {
3376 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003377 if (!doit) {
3378 return true;
3379 }
3380 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003381 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382 if (service.app != null) {
3383 service.app.removed = true;
3384 }
3385 service.app = null;
3386 services.add(service);
3387 }
3388 }
3389
3390 N = services.size();
3391 for (i=0; i<N; i++) {
3392 bringDownServiceLocked(services.get(i), true);
3393 }
3394
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003395 if (doit) {
3396 if (purgeCache) {
3397 AttributeCache ac = AttributeCache.instance();
3398 if (ac != null) {
3399 ac.removePackage(name);
3400 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003401 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003402 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003403 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003404
3405 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 }
3407
3408 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3409 final String name = app.processName;
3410 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003411 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003412 TAG, "Force removing process " + app + " (" + name
3413 + "/" + uid + ")");
3414
3415 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003416 if (mHeavyWeightProcess == app) {
3417 mHeavyWeightProcess = null;
3418 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420 boolean needRestart = false;
3421 if (app.pid > 0 && app.pid != MY_PID) {
3422 int pid = app.pid;
3423 synchronized (mPidsSelfLocked) {
3424 mPidsSelfLocked.remove(pid);
3425 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3426 }
3427 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003428 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 Process.killProcess(pid);
3430
3431 if (app.persistent) {
3432 if (!callerWillRestart) {
3433 addAppLocked(app.info);
3434 } else {
3435 needRestart = true;
3436 }
3437 }
3438 } else {
3439 mRemovedProcesses.add(app);
3440 }
3441
3442 return needRestart;
3443 }
3444
3445 private final void processStartTimedOutLocked(ProcessRecord app) {
3446 final int pid = app.pid;
3447 boolean gone = false;
3448 synchronized (mPidsSelfLocked) {
3449 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3450 if (knownApp != null && knownApp.thread == null) {
3451 mPidsSelfLocked.remove(pid);
3452 gone = true;
3453 }
3454 }
3455
3456 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003457 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003458 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003459 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003461 if (mHeavyWeightProcess == app) {
3462 mHeavyWeightProcess = null;
3463 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3464 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003465 // Take care of any launching providers waiting for this process.
3466 checkAppInLaunchingProvidersLocked(app, true);
3467 // Take care of any services that are waiting for the process.
3468 for (int i=0; i<mPendingServices.size(); i++) {
3469 ServiceRecord sr = mPendingServices.get(i);
3470 if (app.info.uid == sr.appInfo.uid
3471 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003472 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003473 mPendingServices.remove(i);
3474 i--;
3475 bringDownServiceLocked(sr, true);
3476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003478 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003479 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003480 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003481 try {
3482 IBackupManager bm = IBackupManager.Stub.asInterface(
3483 ServiceManager.getService(Context.BACKUP_SERVICE));
3484 bm.agentDisconnected(app.info.packageName);
3485 } catch (RemoteException e) {
3486 // Can't happen; the backup manager is local
3487 }
3488 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003489 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003490 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003491 mPendingBroadcast.state = BroadcastRecord.IDLE;
3492 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003493 mPendingBroadcast = null;
3494 scheduleBroadcastsLocked();
3495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003497 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 }
3499 }
3500
3501 private final boolean attachApplicationLocked(IApplicationThread thread,
3502 int pid) {
3503
3504 // Find the application record that is being attached... either via
3505 // the pid if we are running in multiple processes, or just pull the
3506 // next app record if we are emulating process with anonymous threads.
3507 ProcessRecord app;
3508 if (pid != MY_PID && pid >= 0) {
3509 synchronized (mPidsSelfLocked) {
3510 app = mPidsSelfLocked.get(pid);
3511 }
3512 } else if (mStartingProcesses.size() > 0) {
3513 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003514 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 } else {
3516 app = null;
3517 }
3518
3519 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003520 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003522 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 if (pid > 0 && pid != MY_PID) {
3524 Process.killProcess(pid);
3525 } else {
3526 try {
3527 thread.scheduleExit();
3528 } catch (Exception e) {
3529 // Ignore exceptions.
3530 }
3531 }
3532 return false;
3533 }
3534
3535 // If this application record is still attached to a previous
3536 // process, clean it up now.
3537 if (app.thread != null) {
3538 handleAppDiedLocked(app, true);
3539 }
3540
3541 // Tell the process all about itself.
3542
Joe Onorato8a9b2202010-02-26 18:56:32 -08003543 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003544 TAG, "Binding process pid " + pid + " to record " + app);
3545
3546 String processName = app.processName;
3547 try {
3548 thread.asBinder().linkToDeath(new AppDeathRecipient(
3549 app, pid, thread), 0);
3550 } catch (RemoteException e) {
3551 app.resetPackageList();
3552 startProcessLocked(app, "link fail", processName);
3553 return false;
3554 }
3555
Doug Zongker2bec3d42009-12-04 12:52:44 -08003556 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557
3558 app.thread = thread;
3559 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003560 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3561 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 app.forcingToForeground = null;
3563 app.foregroundServices = false;
3564 app.debugging = false;
3565
3566 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3567
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003568 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003569 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003571 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003572 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003573 }
3574
Joe Onorato8a9b2202010-02-26 18:56:32 -08003575 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003576 TAG, "New app record " + app
3577 + " thread=" + thread.asBinder() + " pid=" + pid);
3578 try {
3579 int testMode = IApplicationThread.DEBUG_OFF;
3580 if (mDebugApp != null && mDebugApp.equals(processName)) {
3581 testMode = mWaitForDebugger
3582 ? IApplicationThread.DEBUG_WAIT
3583 : IApplicationThread.DEBUG_ON;
3584 app.debugging = true;
3585 if (mDebugTransient) {
3586 mDebugApp = mOrigDebugApp;
3587 mWaitForDebugger = mOrigWaitForDebugger;
3588 }
3589 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003590
Christopher Tate181fafa2009-05-14 11:12:14 -07003591 // If the app is being launched for restore or full backup, set it up specially
3592 boolean isRestrictedBackupMode = false;
3593 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3594 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3595 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3596 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003597
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003598 ensurePackageDexOpt(app.instrumentationInfo != null
3599 ? app.instrumentationInfo.packageName
3600 : app.info.packageName);
3601 if (app.instrumentationClass != null) {
3602 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003603 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003604 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003605 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003606 thread.bindApplication(processName, app.instrumentationInfo != null
3607 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 app.instrumentationClass, app.instrumentationProfileFile,
3609 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003610 isRestrictedBackupMode || !normalMode,
3611 mConfiguration, getCommonServicesLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003612 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003613 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003614 } catch (Exception e) {
3615 // todo: Yikes! What should we do? For now we will try to
3616 // start another process, but that could easily get us in
3617 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003618 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619
3620 app.resetPackageList();
3621 startProcessLocked(app, "bind fail", processName);
3622 return false;
3623 }
3624
3625 // Remove this record from the list of starting applications.
3626 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003627 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3628 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 mProcessesOnHold.remove(app);
3630
3631 boolean badApp = false;
3632 boolean didSomething = false;
3633
3634 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003635 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003636 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3638 && processName.equals(hr.processName)) {
3639 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003640 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 didSomething = true;
3642 }
3643 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003644 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003645 + hr.intent.getComponent().flattenToShortString(), e);
3646 badApp = true;
3647 }
3648 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003649 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 }
3651 }
3652
3653 // Find any services that should be running in this process...
3654 if (!badApp && mPendingServices.size() > 0) {
3655 ServiceRecord sr = null;
3656 try {
3657 for (int i=0; i<mPendingServices.size(); i++) {
3658 sr = mPendingServices.get(i);
3659 if (app.info.uid != sr.appInfo.uid
3660 || !processName.equals(sr.processName)) {
3661 continue;
3662 }
3663
3664 mPendingServices.remove(i);
3665 i--;
3666 realStartServiceLocked(sr, app);
3667 didSomething = true;
3668 }
3669 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003670 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 + sr.shortName, e);
3672 badApp = true;
3673 }
3674 }
3675
3676 // Check if the next broadcast receiver is in this process...
3677 BroadcastRecord br = mPendingBroadcast;
3678 if (!badApp && br != null && br.curApp == app) {
3679 try {
3680 mPendingBroadcast = null;
3681 processCurBroadcastLocked(br, app);
3682 didSomething = true;
3683 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003684 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 + br.curComponent.flattenToShortString(), e);
3686 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003687 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3689 br.resultExtras, br.resultAbort, true);
3690 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003691 // We need to reset the state if we fails to start the receiver.
3692 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 }
3694 }
3695
Christopher Tate181fafa2009-05-14 11:12:14 -07003696 // Check whether the next backup agent is in this process...
3697 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003698 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003699 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003700 try {
3701 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3702 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003703 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003704 e.printStackTrace();
3705 }
3706 }
3707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 if (badApp) {
3709 // todo: Also need to kill application to deal with all
3710 // kinds of exceptions.
3711 handleAppDiedLocked(app, false);
3712 return false;
3713 }
3714
3715 if (!didSomething) {
3716 updateOomAdjLocked();
3717 }
3718
3719 return true;
3720 }
3721
3722 public final void attachApplication(IApplicationThread thread) {
3723 synchronized (this) {
3724 int callingPid = Binder.getCallingPid();
3725 final long origId = Binder.clearCallingIdentity();
3726 attachApplicationLocked(thread, callingPid);
3727 Binder.restoreCallingIdentity(origId);
3728 }
3729 }
3730
Dianne Hackborne88846e2009-09-30 21:34:25 -07003731 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003733 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003734 Binder.restoreCallingIdentity(origId);
3735 }
3736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003738 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003739 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 mWindowManager.enableScreenAfterBoot();
3741 }
3742
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003743 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003744 IntentFilter pkgFilter = new IntentFilter();
3745 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3746 pkgFilter.addDataScheme("package");
3747 mContext.registerReceiver(new BroadcastReceiver() {
3748 @Override
3749 public void onReceive(Context context, Intent intent) {
3750 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3751 if (pkgs != null) {
3752 for (String pkg : pkgs) {
3753 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3754 setResultCode(Activity.RESULT_OK);
3755 return;
3756 }
3757 }
3758 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003759 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003760 }, pkgFilter);
3761
3762 synchronized (this) {
3763 // Ensure that any processes we had put on hold are now started
3764 // up.
3765 final int NP = mProcessesOnHold.size();
3766 if (NP > 0) {
3767 ArrayList<ProcessRecord> procs =
3768 new ArrayList<ProcessRecord>(mProcessesOnHold);
3769 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003770 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3771 + procs.get(ip));
3772 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003773 }
3774 }
3775
3776 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003777 // Start looking for apps that are abusing wake locks.
3778 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003779 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003780 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003781 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003782 broadcastIntentLocked(null, null,
3783 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3784 null, null, 0, null, null,
3785 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3786 false, false, MY_PID, Process.SYSTEM_UID);
3787 }
3788 }
3789 }
3790
3791 final void ensureBootCompleted() {
3792 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003793 boolean enableScreen;
3794 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003795 booting = mBooting;
3796 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003797 enableScreen = !mBooted;
3798 mBooted = true;
3799 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003800
3801 if (booting) {
3802 finishBooting();
3803 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003804
3805 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003806 enableScreenAfterBoot();
3807 }
3808 }
3809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 public final void activityPaused(IBinder token, Bundle icicle) {
3811 // Refuse possible leaked file descriptors
3812 if (icicle != null && icicle.hasFileDescriptors()) {
3813 throw new IllegalArgumentException("File descriptors passed in Bundle");
3814 }
3815
3816 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003817 mMainStack.activityPaused(token, icicle, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818 Binder.restoreCallingIdentity(origId);
3819 }
3820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 public final void activityStopped(IBinder token, Bitmap thumbnail,
3822 CharSequence description) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003823 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 TAG, "Activity stopped: token=" + token);
3825
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003826 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827
3828 final long origId = Binder.clearCallingIdentity();
3829
3830 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003831 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003833 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003834 r.thumbnail = thumbnail;
3835 r.description = description;
3836 r.stopped = true;
3837 r.state = ActivityState.STOPPED;
3838 if (!r.finishing) {
3839 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003840 r.stack.destroyActivityLocked(r, true);
3841 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003842 }
3843 }
3844 }
3845 }
3846
3847 if (r != null) {
3848 sendPendingThumbnail(r, null, null, null, false);
3849 }
3850
3851 trimApplications();
3852
3853 Binder.restoreCallingIdentity(origId);
3854 }
3855
3856 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003857 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003858 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 }
3860
3861 public String getCallingPackage(IBinder token) {
3862 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003863 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003864 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 }
3866 }
3867
3868 public ComponentName getCallingActivity(IBinder token) {
3869 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003870 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871 return r != null ? r.intent.getComponent() : null;
3872 }
3873 }
3874
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003875 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003876 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003878 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 if (r != null) {
3880 return r.resultTo;
3881 }
3882 }
3883 return null;
3884 }
3885
3886 public ComponentName getActivityClassForToken(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.intent.getComponent();
3892 }
3893 return null;
3894 }
3895 }
3896
3897 public String getPackageForToken(IBinder token) {
3898 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003899 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003900 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003901 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003902 return r.packageName;
3903 }
3904 return null;
3905 }
3906 }
3907
3908 public IIntentSender getIntentSender(int type,
3909 String packageName, IBinder token, String resultWho,
3910 int requestCode, Intent intent, String resolvedType, int flags) {
3911 // Refuse possible leaked file descriptors
3912 if (intent != null && intent.hasFileDescriptors() == true) {
3913 throw new IllegalArgumentException("File descriptors passed in Intent");
3914 }
3915
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003916 if (type == INTENT_SENDER_BROADCAST) {
3917 if ((intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3918 throw new IllegalArgumentException(
3919 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3920 }
3921 }
3922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003923 synchronized(this) {
3924 int callingUid = Binder.getCallingUid();
3925 try {
3926 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3927 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003928 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 .getPackageUid(packageName);
3930 if (uid != Binder.getCallingUid()) {
3931 String msg = "Permission Denial: getIntentSender() from pid="
3932 + Binder.getCallingPid()
3933 + ", uid=" + Binder.getCallingUid()
3934 + ", (need uid=" + uid + ")"
3935 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003936 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 throw new SecurityException(msg);
3938 }
3939 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003940
3941 return getIntentSenderLocked(type, packageName, callingUid,
3942 token, resultWho, requestCode, intent, resolvedType, flags);
3943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 } catch (RemoteException e) {
3945 throw new SecurityException(e);
3946 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003947 }
3948 }
3949
3950 IIntentSender getIntentSenderLocked(int type,
3951 String packageName, int callingUid, IBinder token, String resultWho,
3952 int requestCode, Intent intent, String resolvedType, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003953 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003954 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003955 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003956 if (index < 0) {
3957 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003959 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003960 if (activity.finishing) {
3961 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003963 }
3964
3965 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3966 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3967 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3968 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3969 |PendingIntent.FLAG_UPDATE_CURRENT);
3970
3971 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3972 type, packageName, activity, resultWho,
3973 requestCode, intent, resolvedType, flags);
3974 WeakReference<PendingIntentRecord> ref;
3975 ref = mIntentSenderRecords.get(key);
3976 PendingIntentRecord rec = ref != null ? ref.get() : null;
3977 if (rec != null) {
3978 if (!cancelCurrent) {
3979 if (updateCurrent) {
3980 rec.key.requestIntent.replaceExtras(intent);
3981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 return rec;
3983 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003984 rec.canceled = true;
3985 mIntentSenderRecords.remove(key);
3986 }
3987 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 return rec;
3989 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003990 rec = new PendingIntentRecord(this, key, callingUid);
3991 mIntentSenderRecords.put(key, rec.ref);
3992 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
3993 if (activity.pendingResults == null) {
3994 activity.pendingResults
3995 = new HashSet<WeakReference<PendingIntentRecord>>();
3996 }
3997 activity.pendingResults.add(rec.ref);
3998 }
3999 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 }
4001
4002 public void cancelIntentSender(IIntentSender sender) {
4003 if (!(sender instanceof PendingIntentRecord)) {
4004 return;
4005 }
4006 synchronized(this) {
4007 PendingIntentRecord rec = (PendingIntentRecord)sender;
4008 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004009 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 .getPackageUid(rec.key.packageName);
4011 if (uid != Binder.getCallingUid()) {
4012 String msg = "Permission Denial: cancelIntentSender() from pid="
4013 + Binder.getCallingPid()
4014 + ", uid=" + Binder.getCallingUid()
4015 + " is not allowed to cancel packges "
4016 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004017 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 throw new SecurityException(msg);
4019 }
4020 } catch (RemoteException e) {
4021 throw new SecurityException(e);
4022 }
4023 cancelIntentSenderLocked(rec, true);
4024 }
4025 }
4026
4027 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4028 rec.canceled = true;
4029 mIntentSenderRecords.remove(rec.key);
4030 if (cleanActivity && rec.key.activity != null) {
4031 rec.key.activity.pendingResults.remove(rec.ref);
4032 }
4033 }
4034
4035 public String getPackageForIntentSender(IIntentSender pendingResult) {
4036 if (!(pendingResult instanceof PendingIntentRecord)) {
4037 return null;
4038 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004039 try {
4040 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4041 return res.key.packageName;
4042 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043 }
4044 return null;
4045 }
4046
4047 public void setProcessLimit(int max) {
4048 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4049 "setProcessLimit()");
4050 mProcessLimit = max;
4051 }
4052
4053 public int getProcessLimit() {
4054 return mProcessLimit;
4055 }
4056
4057 void foregroundTokenDied(ForegroundToken token) {
4058 synchronized (ActivityManagerService.this) {
4059 synchronized (mPidsSelfLocked) {
4060 ForegroundToken cur
4061 = mForegroundProcesses.get(token.pid);
4062 if (cur != token) {
4063 return;
4064 }
4065 mForegroundProcesses.remove(token.pid);
4066 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4067 if (pr == null) {
4068 return;
4069 }
4070 pr.forcingToForeground = null;
4071 pr.foregroundServices = false;
4072 }
4073 updateOomAdjLocked();
4074 }
4075 }
4076
4077 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4078 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4079 "setProcessForeground()");
4080 synchronized(this) {
4081 boolean changed = false;
4082
4083 synchronized (mPidsSelfLocked) {
4084 ProcessRecord pr = mPidsSelfLocked.get(pid);
4085 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004086 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087 return;
4088 }
4089 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4090 if (oldToken != null) {
4091 oldToken.token.unlinkToDeath(oldToken, 0);
4092 mForegroundProcesses.remove(pid);
4093 pr.forcingToForeground = null;
4094 changed = true;
4095 }
4096 if (isForeground && token != null) {
4097 ForegroundToken newToken = new ForegroundToken() {
4098 public void binderDied() {
4099 foregroundTokenDied(this);
4100 }
4101 };
4102 newToken.pid = pid;
4103 newToken.token = token;
4104 try {
4105 token.linkToDeath(newToken, 0);
4106 mForegroundProcesses.put(pid, newToken);
4107 pr.forcingToForeground = token;
4108 changed = true;
4109 } catch (RemoteException e) {
4110 // If the process died while doing this, we will later
4111 // do the cleanup with the process death link.
4112 }
4113 }
4114 }
4115
4116 if (changed) {
4117 updateOomAdjLocked();
4118 }
4119 }
4120 }
4121
4122 // =========================================================
4123 // PERMISSIONS
4124 // =========================================================
4125
4126 static class PermissionController extends IPermissionController.Stub {
4127 ActivityManagerService mActivityManagerService;
4128 PermissionController(ActivityManagerService activityManagerService) {
4129 mActivityManagerService = activityManagerService;
4130 }
4131
4132 public boolean checkPermission(String permission, int pid, int uid) {
4133 return mActivityManagerService.checkPermission(permission, pid,
4134 uid) == PackageManager.PERMISSION_GRANTED;
4135 }
4136 }
4137
4138 /**
4139 * This can be called with or without the global lock held.
4140 */
4141 int checkComponentPermission(String permission, int pid, int uid,
4142 int reqUid) {
4143 // We might be performing an operation on behalf of an indirect binder
4144 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4145 // client identity accordingly before proceeding.
4146 Identity tlsIdentity = sCallerIdentity.get();
4147 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004148 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004149 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4150 uid = tlsIdentity.uid;
4151 pid = tlsIdentity.pid;
4152 }
4153
4154 // Root, system server and our own process get to do everything.
4155 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4156 !Process.supportsProcesses()) {
4157 return PackageManager.PERMISSION_GRANTED;
4158 }
4159 // If the target requires a specific UID, always fail for others.
4160 if (reqUid >= 0 && uid != reqUid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004161 Slog.w(TAG, "Permission denied: checkComponentPermission() reqUid=" + reqUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 return PackageManager.PERMISSION_DENIED;
4163 }
4164 if (permission == null) {
4165 return PackageManager.PERMISSION_GRANTED;
4166 }
4167 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004168 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 .checkUidPermission(permission, uid);
4170 } catch (RemoteException e) {
4171 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004172 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 }
4174 return PackageManager.PERMISSION_DENIED;
4175 }
4176
4177 /**
4178 * As the only public entry point for permissions checking, this method
4179 * can enforce the semantic that requesting a check on a null global
4180 * permission is automatically denied. (Internally a null permission
4181 * string is used when calling {@link #checkComponentPermission} in cases
4182 * when only uid-based security is needed.)
4183 *
4184 * This can be called with or without the global lock held.
4185 */
4186 public int checkPermission(String permission, int pid, int uid) {
4187 if (permission == null) {
4188 return PackageManager.PERMISSION_DENIED;
4189 }
4190 return checkComponentPermission(permission, pid, uid, -1);
4191 }
4192
4193 /**
4194 * Binder IPC calls go through the public entry point.
4195 * This can be called with or without the global lock held.
4196 */
4197 int checkCallingPermission(String permission) {
4198 return checkPermission(permission,
4199 Binder.getCallingPid(),
4200 Binder.getCallingUid());
4201 }
4202
4203 /**
4204 * This can be called with or without the global lock held.
4205 */
4206 void enforceCallingPermission(String permission, String func) {
4207 if (checkCallingPermission(permission)
4208 == PackageManager.PERMISSION_GRANTED) {
4209 return;
4210 }
4211
4212 String msg = "Permission Denial: " + func + " from pid="
4213 + Binder.getCallingPid()
4214 + ", uid=" + Binder.getCallingUid()
4215 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004216 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 throw new SecurityException(msg);
4218 }
4219
4220 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004221 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4222 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4223 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4224 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4225 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004226 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004227 // Is the component private from the target uid?
4228 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4229
4230 // Acceptable if the there is no read permission needed from the
4231 // target or the target is holding the read permission.
4232 if (!readPerm) {
4233 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004235 == PackageManager.PERMISSION_GRANTED)) {
4236 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 }
4238 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004239
4240 // Acceptable if the there is no write permission needed from the
4241 // target or the target is holding the read permission.
4242 if (!writePerm) {
4243 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004244 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004245 == PackageManager.PERMISSION_GRANTED)) {
4246 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 }
4248 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004249
4250 // Acceptable if there is a path permission matching the URI that
4251 // the target holds the permission on.
4252 PathPermission[] pps = pi.pathPermissions;
4253 if (pps != null && (!readPerm || !writePerm)) {
4254 final String path = uri.getPath();
4255 int i = pps.length;
4256 while (i > 0 && (!readPerm || !writePerm)) {
4257 i--;
4258 PathPermission pp = pps[i];
4259 if (!readPerm) {
4260 final String pprperm = pp.getReadPermission();
4261 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4262 + pprperm + " for " + pp.getPath()
4263 + ": match=" + pp.match(path)
4264 + " check=" + pm.checkUidPermission(pprperm, uid));
4265 if (pprperm != null && pp.match(path) &&
4266 (pm.checkUidPermission(pprperm, uid)
4267 == PackageManager.PERMISSION_GRANTED)) {
4268 readPerm = true;
4269 }
4270 }
4271 if (!writePerm) {
4272 final String ppwperm = pp.getWritePermission();
4273 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4274 + ppwperm + " for " + pp.getPath()
4275 + ": match=" + pp.match(path)
4276 + " check=" + pm.checkUidPermission(ppwperm, uid));
4277 if (ppwperm != null && pp.match(path) &&
4278 (pm.checkUidPermission(ppwperm, uid)
4279 == PackageManager.PERMISSION_GRANTED)) {
4280 writePerm = true;
4281 }
4282 }
4283 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 } catch (RemoteException e) {
4286 return false;
4287 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004288
4289 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 }
4291
4292 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4293 int modeFlags) {
4294 // Root gets to do everything.
4295 if (uid == 0 || !Process.supportsProcesses()) {
4296 return true;
4297 }
4298 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4299 if (perms == null) return false;
4300 UriPermission perm = perms.get(uri);
4301 if (perm == null) return false;
4302 return (modeFlags&perm.modeFlags) == modeFlags;
4303 }
4304
4305 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4306 // Another redirected-binder-call permissions check as in
4307 // {@link checkComponentPermission}.
4308 Identity tlsIdentity = sCallerIdentity.get();
4309 if (tlsIdentity != null) {
4310 uid = tlsIdentity.uid;
4311 pid = tlsIdentity.pid;
4312 }
4313
4314 // Our own process gets to do everything.
4315 if (pid == MY_PID) {
4316 return PackageManager.PERMISSION_GRANTED;
4317 }
4318 synchronized(this) {
4319 return checkUriPermissionLocked(uri, uid, modeFlags)
4320 ? PackageManager.PERMISSION_GRANTED
4321 : PackageManager.PERMISSION_DENIED;
4322 }
4323 }
4324
Dianne Hackborn39792d22010-08-19 18:01:52 -07004325 /**
4326 * Check if the targetPkg can be granted permission to access uri by
4327 * the callingUid using the given modeFlags. Throws a security exception
4328 * if callingUid is not allowed to do this. Returns the uid of the target
4329 * if the URI permission grant should be performed; returns -1 if it is not
4330 * needed (for example targetPkg already has permission to access the URI).
4331 */
4332 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4333 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004334 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4335 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4336 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004337 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 }
4339
Joe Onorato8a9b2202010-02-26 18:56:32 -08004340 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004341 "Checking grant " + targetPkg + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004342
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004343 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344
4345 // If this is not a content: uri, we can't do anything with it.
4346 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004347 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004348 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004349 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 }
4351
4352 String name = uri.getAuthority();
4353 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004354 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 if (cpr != null) {
4356 pi = cpr.info;
4357 } else {
4358 try {
4359 pi = pm.resolveContentProvider(name,
4360 PackageManager.GET_URI_PERMISSION_PATTERNS);
4361 } catch (RemoteException ex) {
4362 }
4363 }
4364 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004365 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004366 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 }
4368
4369 int targetUid;
4370 try {
4371 targetUid = pm.getPackageUid(targetPkg);
4372 if (targetUid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004373 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004374 "Can't grant URI permission no uid for: " + targetPkg);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004375 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 }
4377 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004378 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004379 }
4380
4381 // First... does the target actually need this permission?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004382 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 // No need to grant the target this permission.
Joe Onorato8a9b2202010-02-26 18:56:32 -08004384 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004385 "Target " + targetPkg + " already has full permission to " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004386 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004387 }
4388
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004389 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004390 if (!pi.grantUriPermissions) {
4391 throw new SecurityException("Provider " + pi.packageName
4392 + "/" + pi.name
4393 + " does not allow granting of Uri permissions (uri "
4394 + uri + ")");
4395 }
4396 if (pi.uriPermissionPatterns != null) {
4397 final int N = pi.uriPermissionPatterns.length;
4398 boolean allowed = false;
4399 for (int i=0; i<N; i++) {
4400 if (pi.uriPermissionPatterns[i] != null
4401 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4402 allowed = true;
4403 break;
4404 }
4405 }
4406 if (!allowed) {
4407 throw new SecurityException("Provider " + pi.packageName
4408 + "/" + pi.name
4409 + " does not allow granting of permission to path of Uri "
4410 + uri);
4411 }
4412 }
4413
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004414 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415 // this uri?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004416 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4418 throw new SecurityException("Uid " + callingUid
4419 + " does not have permission to uri " + uri);
4420 }
4421 }
4422
Dianne Hackborn39792d22010-08-19 18:01:52 -07004423 return targetUid;
4424 }
4425
4426 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4427 Uri uri, int modeFlags, UriPermissionOwner owner) {
4428 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4429 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4430 if (modeFlags == 0) {
4431 return;
4432 }
4433
4434 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 // to the uri, and the target doesn't. Let's now give this to
4436 // the target.
4437
Joe Onorato8a9b2202010-02-26 18:56:32 -08004438 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004439 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 HashMap<Uri, UriPermission> targetUris
4442 = mGrantedUriPermissions.get(targetUid);
4443 if (targetUris == null) {
4444 targetUris = new HashMap<Uri, UriPermission>();
4445 mGrantedUriPermissions.put(targetUid, targetUris);
4446 }
4447
4448 UriPermission perm = targetUris.get(uri);
4449 if (perm == null) {
4450 perm = new UriPermission(targetUid, uri);
4451 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004452 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004454 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004455 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 perm.globalModeFlags |= modeFlags;
4457 } else if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004458 perm.readOwners.add(owner);
4459 owner.addReadPermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004460 } else if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004461 perm.writeOwners.add(owner);
4462 owner.addWritePermission(perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 }
4464 }
4465
Dianne Hackborn39792d22010-08-19 18:01:52 -07004466 void grantUriPermissionLocked(int callingUid,
4467 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
4468 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4469 if (targetUid < 0) {
4470 return;
4471 }
4472
4473 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4474 }
4475
4476 /**
4477 * Like checkGrantUriPermissionLocked, but takes an Intent.
4478 */
4479 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4480 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004481 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004482 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004483 + " from " + intent + "; flags=0x"
4484 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004487 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 }
4489 Uri data = intent.getData();
4490 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004491 return -1;
4492 }
4493 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4494 intent.getFlags());
4495 }
4496
4497 /**
4498 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4499 */
4500 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4501 String targetPkg, Intent intent, UriPermissionOwner owner) {
4502 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4503 intent.getFlags(), owner);
4504 }
4505
4506 void grantUriPermissionFromIntentLocked(int callingUid,
4507 String targetPkg, Intent intent, UriPermissionOwner owner) {
4508 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4509 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 return;
4511 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004512
4513 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 }
4515
4516 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4517 Uri uri, int modeFlags) {
4518 synchronized(this) {
4519 final ProcessRecord r = getRecordForAppLocked(caller);
4520 if (r == null) {
4521 throw new SecurityException("Unable to find app for caller "
4522 + caller
4523 + " when granting permission to uri " + uri);
4524 }
4525 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004526 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 }
4528 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004529 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004530 }
4531
4532 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4533 null);
4534 }
4535 }
4536
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004537 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4539 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4540 HashMap<Uri, UriPermission> perms
4541 = mGrantedUriPermissions.get(perm.uid);
4542 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004543 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004544 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 perms.remove(perm.uri);
4546 if (perms.size() == 0) {
4547 mGrantedUriPermissions.remove(perm.uid);
4548 }
4549 }
4550 }
4551 }
4552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004553 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4554 int modeFlags) {
4555 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4556 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4557 if (modeFlags == 0) {
4558 return;
4559 }
4560
Joe Onorato8a9b2202010-02-26 18:56:32 -08004561 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004562 "Revoking all granted permissions to " + uri);
4563
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004564 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565
4566 final String authority = uri.getAuthority();
4567 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004568 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 if (cpr != null) {
4570 pi = cpr.info;
4571 } else {
4572 try {
4573 pi = pm.resolveContentProvider(authority,
4574 PackageManager.GET_URI_PERMISSION_PATTERNS);
4575 } catch (RemoteException ex) {
4576 }
4577 }
4578 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004579 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004580 return;
4581 }
4582
4583 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004584 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 // Right now, if you are not the original owner of the permission,
4586 // you are not allowed to revoke it.
4587 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4588 throw new SecurityException("Uid " + callingUid
4589 + " does not have permission to uri " + uri);
4590 //}
4591 }
4592
4593 // Go through all of the permissions and remove any that match.
4594 final List<String> SEGMENTS = uri.getPathSegments();
4595 if (SEGMENTS != null) {
4596 final int NS = SEGMENTS.size();
4597 int N = mGrantedUriPermissions.size();
4598 for (int i=0; i<N; i++) {
4599 HashMap<Uri, UriPermission> perms
4600 = mGrantedUriPermissions.valueAt(i);
4601 Iterator<UriPermission> it = perms.values().iterator();
4602 toploop:
4603 while (it.hasNext()) {
4604 UriPermission perm = it.next();
4605 Uri targetUri = perm.uri;
4606 if (!authority.equals(targetUri.getAuthority())) {
4607 continue;
4608 }
4609 List<String> targetSegments = targetUri.getPathSegments();
4610 if (targetSegments == null) {
4611 continue;
4612 }
4613 if (targetSegments.size() < NS) {
4614 continue;
4615 }
4616 for (int j=0; j<NS; j++) {
4617 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4618 continue toploop;
4619 }
4620 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004621 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004622 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 perm.clearModes(modeFlags);
4624 if (perm.modeFlags == 0) {
4625 it.remove();
4626 }
4627 }
4628 if (perms.size() == 0) {
4629 mGrantedUriPermissions.remove(
4630 mGrantedUriPermissions.keyAt(i));
4631 N--;
4632 i--;
4633 }
4634 }
4635 }
4636 }
4637
4638 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4639 int modeFlags) {
4640 synchronized(this) {
4641 final ProcessRecord r = getRecordForAppLocked(caller);
4642 if (r == null) {
4643 throw new SecurityException("Unable to find app for caller "
4644 + caller
4645 + " when revoking permission to uri " + uri);
4646 }
4647 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004648 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649 return;
4650 }
4651
4652 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4653 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4654 if (modeFlags == 0) {
4655 return;
4656 }
4657
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004658 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659
4660 final String authority = uri.getAuthority();
4661 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004662 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004663 if (cpr != null) {
4664 pi = cpr.info;
4665 } else {
4666 try {
4667 pi = pm.resolveContentProvider(authority,
4668 PackageManager.GET_URI_PERMISSION_PATTERNS);
4669 } catch (RemoteException ex) {
4670 }
4671 }
4672 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004673 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004674 return;
4675 }
4676
4677 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4678 }
4679 }
4680
Dianne Hackborn7e269642010-08-25 19:50:20 -07004681 @Override
4682 public IBinder newUriPermissionOwner(String name) {
4683 synchronized(this) {
4684 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4685 return owner.getExternalTokenLocked();
4686 }
4687 }
4688
4689 @Override
4690 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4691 Uri uri, int modeFlags) {
4692 synchronized(this) {
4693 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4694 if (owner == null) {
4695 throw new IllegalArgumentException("Unknown owner: " + token);
4696 }
4697 if (fromUid != Binder.getCallingUid()) {
4698 if (Binder.getCallingUid() != Process.myUid()) {
4699 // Only system code can grant URI permissions on behalf
4700 // of other users.
4701 throw new SecurityException("nice try");
4702 }
4703 }
4704 if (targetPkg == null) {
4705 throw new IllegalArgumentException("null target");
4706 }
4707 if (uri == null) {
4708 throw new IllegalArgumentException("null uri");
4709 }
4710
4711 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4712 }
4713 }
4714
4715 @Override
4716 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4717 synchronized(this) {
4718 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4719 if (owner == null) {
4720 throw new IllegalArgumentException("Unknown owner: " + token);
4721 }
4722
4723 if (uri == null) {
4724 owner.removeUriPermissionsLocked(mode);
4725 } else {
4726 owner.removeUriPermissionLocked(uri, mode);
4727 }
4728 }
4729 }
4730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4732 synchronized (this) {
4733 ProcessRecord app =
4734 who != null ? getRecordForAppLocked(who) : null;
4735 if (app == null) return;
4736
4737 Message msg = Message.obtain();
4738 msg.what = WAIT_FOR_DEBUGGER_MSG;
4739 msg.obj = app;
4740 msg.arg1 = waiting ? 1 : 0;
4741 mHandler.sendMessage(msg);
4742 }
4743 }
4744
4745 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4746 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004747 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004748 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004749 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750 }
4751
4752 // =========================================================
4753 // TASK MANAGEMENT
4754 // =========================================================
4755
4756 public List getTasks(int maxNum, int flags,
4757 IThumbnailReceiver receiver) {
4758 ArrayList list = new ArrayList();
4759
4760 PendingThumbnailsRecord pending = null;
4761 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004762 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763
4764 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004765 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004766 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4767 + ", receiver=" + receiver);
4768
4769 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4770 != PackageManager.PERMISSION_GRANTED) {
4771 if (receiver != null) {
4772 // If the caller wants to wait for pending thumbnails,
4773 // it ain't gonna get them.
4774 try {
4775 receiver.finished();
4776 } catch (RemoteException ex) {
4777 }
4778 }
4779 String msg = "Permission Denial: getTasks() from pid="
4780 + Binder.getCallingPid()
4781 + ", uid=" + Binder.getCallingUid()
4782 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004783 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004784 throw new SecurityException(msg);
4785 }
4786
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004787 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004788 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004789 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004790 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 CharSequence topDescription = null;
4792 TaskRecord curTask = null;
4793 int numActivities = 0;
4794 int numRunning = 0;
4795 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004796 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004798 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004799
4800 // Initialize state for next task if needed.
4801 if (top == null ||
4802 (top.state == ActivityState.INITIALIZING
4803 && top.task == r.task)) {
4804 top = r;
4805 topDescription = r.description;
4806 curTask = r.task;
4807 numActivities = numRunning = 0;
4808 }
4809
4810 // Add 'r' into the current task.
4811 numActivities++;
4812 if (r.app != null && r.app.thread != null) {
4813 numRunning++;
4814 }
4815 if (topDescription == null) {
4816 topDescription = r.description;
4817 }
4818
Joe Onorato8a9b2202010-02-26 18:56:32 -08004819 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 TAG, r.intent.getComponent().flattenToShortString()
4821 + ": task=" + r.task);
4822
4823 // If the next one is a different task, generate a new
4824 // TaskInfo entry for what we have.
4825 if (next == null || next.task != curTask) {
4826 ActivityManager.RunningTaskInfo ci
4827 = new ActivityManager.RunningTaskInfo();
4828 ci.id = curTask.taskId;
4829 ci.baseActivity = r.intent.getComponent();
4830 ci.topActivity = top.intent.getComponent();
4831 ci.thumbnail = top.thumbnail;
4832 ci.description = topDescription;
4833 ci.numActivities = numActivities;
4834 ci.numRunning = numRunning;
4835 //System.out.println(
4836 // "#" + maxNum + ": " + " descr=" + ci.description);
4837 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004838 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004839 TAG, "State=" + top.state + "Idle=" + top.idle
4840 + " app=" + top.app
4841 + " thr=" + (top.app != null ? top.app.thread : null));
4842 if (top.state == ActivityState.RESUMED
4843 || top.state == ActivityState.PAUSING) {
4844 if (top.idle && top.app != null
4845 && top.app.thread != null) {
4846 topRecord = top;
4847 topThumbnail = top.app.thread;
4848 } else {
4849 top.thumbnailNeeded = true;
4850 }
4851 }
4852 if (pending == null) {
4853 pending = new PendingThumbnailsRecord(receiver);
4854 }
4855 pending.pendingRecords.add(top);
4856 }
4857 list.add(ci);
4858 maxNum--;
4859 top = null;
4860 }
4861 }
4862
4863 if (pending != null) {
4864 mPendingThumbnails.add(pending);
4865 }
4866 }
4867
Joe Onorato8a9b2202010-02-26 18:56:32 -08004868 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869
4870 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004871 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 try {
4873 topThumbnail.requestThumbnail(topRecord);
4874 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004875 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 sendPendingThumbnail(null, topRecord, null, null, true);
4877 }
4878 }
4879
4880 if (pending == null && receiver != null) {
4881 // In this case all thumbnails were available and the client
4882 // is being asked to be told when the remaining ones come in...
4883 // which is unusually, since the top-most currently running
4884 // activity should never have a canned thumbnail! Oh well.
4885 try {
4886 receiver.finished();
4887 } catch (RemoteException ex) {
4888 }
4889 }
4890
4891 return list;
4892 }
4893
4894 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4895 int flags) {
4896 synchronized (this) {
4897 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4898 "getRecentTasks()");
4899
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004900 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 final int N = mRecentTasks.size();
4903 ArrayList<ActivityManager.RecentTaskInfo> res
4904 = new ArrayList<ActivityManager.RecentTaskInfo>(
4905 maxNum < N ? maxNum : N);
4906 for (int i=0; i<N && maxNum > 0; i++) {
4907 TaskRecord tr = mRecentTasks.get(i);
4908 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4909 || (tr.intent == null)
4910 || ((tr.intent.getFlags()
4911 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4912 ActivityManager.RecentTaskInfo rti
4913 = new ActivityManager.RecentTaskInfo();
4914 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
4915 rti.baseIntent = new Intent(
4916 tr.intent != null ? tr.intent : tr.affinityIntent);
4917 rti.origActivity = tr.origActivity;
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004918
4919 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
4920 // Check whether this activity is currently available.
4921 try {
4922 if (rti.origActivity != null) {
4923 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
4924 continue;
4925 }
4926 } else if (rti.baseIntent != null) {
4927 if (pm.queryIntentActivities(rti.baseIntent,
4928 null, 0) == null) {
4929 continue;
4930 }
4931 }
4932 } catch (RemoteException e) {
4933 // Will never happen.
4934 }
4935 }
4936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 res.add(rti);
4938 maxNum--;
4939 }
4940 }
4941 return res;
4942 }
4943 }
4944
4945 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
4946 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004947 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 TaskRecord jt = startTask;
4949
4950 // First look backwards
4951 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004952 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 if (r.task != jt) {
4954 jt = r.task;
4955 if (affinity.equals(jt.affinity)) {
4956 return j;
4957 }
4958 }
4959 }
4960
4961 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004962 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 jt = startTask;
4964 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004965 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004966 if (r.task != jt) {
4967 if (affinity.equals(jt.affinity)) {
4968 return j;
4969 }
4970 jt = r.task;
4971 }
4972 }
4973
4974 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004975 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004976 return N-1;
4977 }
4978
4979 return -1;
4980 }
4981
4982 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07004983 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004984 */
4985 public void moveTaskToFront(int task) {
4986 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
4987 "moveTaskToFront()");
4988
4989 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004990 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
4991 Binder.getCallingUid(), "Task to front")) {
4992 return;
4993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004994 final long origId = Binder.clearCallingIdentity();
4995 try {
4996 int N = mRecentTasks.size();
4997 for (int i=0; i<N; i++) {
4998 TaskRecord tr = mRecentTasks.get(i);
4999 if (tr.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005000 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 return;
5002 }
5003 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005004 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5005 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005006 if (hr.task.taskId == task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005007 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 return;
5009 }
5010 }
5011 } finally {
5012 Binder.restoreCallingIdentity(origId);
5013 }
5014 }
5015 }
5016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005017 public void moveTaskToBack(int task) {
5018 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5019 "moveTaskToBack()");
5020
5021 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005022 if (mMainStack.mResumedActivity != null
5023 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005024 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5025 Binder.getCallingUid(), "Task to back")) {
5026 return;
5027 }
5028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005029 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005030 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005031 Binder.restoreCallingIdentity(origId);
5032 }
5033 }
5034
5035 /**
5036 * Moves an activity, and all of the other activities within the same task, to the bottom
5037 * of the history stack. The activity's order within the task is unchanged.
5038 *
5039 * @param token A reference to the activity we wish to move
5040 * @param nonRoot If false then this only works if the activity is the root
5041 * of a task; if true it will work for any activity in a task.
5042 * @return Returns true if the move completed, false if not.
5043 */
5044 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5045 synchronized(this) {
5046 final long origId = Binder.clearCallingIdentity();
5047 int taskId = getTaskForActivityLocked(token, !nonRoot);
5048 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005049 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005050 }
5051 Binder.restoreCallingIdentity(origId);
5052 }
5053 return false;
5054 }
5055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 public void moveTaskBackwards(int task) {
5057 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5058 "moveTaskBackwards()");
5059
5060 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005061 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5062 Binder.getCallingUid(), "Task backwards")) {
5063 return;
5064 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 final long origId = Binder.clearCallingIdentity();
5066 moveTaskBackwardsLocked(task);
5067 Binder.restoreCallingIdentity(origId);
5068 }
5069 }
5070
5071 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005072 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005073 }
5074
5075 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5076 synchronized(this) {
5077 return getTaskForActivityLocked(token, onlyRoot);
5078 }
5079 }
5080
5081 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005082 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 TaskRecord lastTask = null;
5084 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005085 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005086 if (r == token) {
5087 if (!onlyRoot || lastTask != r.task) {
5088 return r.task.taskId;
5089 }
5090 return -1;
5091 }
5092 lastTask = r.task;
5093 }
5094
5095 return -1;
5096 }
5097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005098 public void finishOtherInstances(IBinder token, ComponentName className) {
5099 synchronized(this) {
5100 final long origId = Binder.clearCallingIdentity();
5101
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005102 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 TaskRecord lastTask = null;
5104 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005105 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005106 if (r.realActivity.equals(className)
5107 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005108 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 null, "others")) {
5110 i--;
5111 N--;
5112 }
5113 }
5114 lastTask = r.task;
5115 }
5116
5117 Binder.restoreCallingIdentity(origId);
5118 }
5119 }
5120
5121 // =========================================================
5122 // THUMBNAILS
5123 // =========================================================
5124
5125 public void reportThumbnail(IBinder token,
5126 Bitmap thumbnail, CharSequence description) {
5127 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5128 final long origId = Binder.clearCallingIdentity();
5129 sendPendingThumbnail(null, token, thumbnail, description, true);
5130 Binder.restoreCallingIdentity(origId);
5131 }
5132
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005133 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 Bitmap thumbnail, CharSequence description, boolean always) {
5135 TaskRecord task = null;
5136 ArrayList receivers = null;
5137
5138 //System.out.println("Send pending thumbnail: " + r);
5139
5140 synchronized(this) {
5141 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005142 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 if (index < 0) {
5144 return;
5145 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005146 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 }
5148 if (thumbnail == null) {
5149 thumbnail = r.thumbnail;
5150 description = r.description;
5151 }
5152 if (thumbnail == null && !always) {
5153 // If there is no thumbnail, and this entry is not actually
5154 // going away, then abort for now and pick up the next
5155 // thumbnail we get.
5156 return;
5157 }
5158 task = r.task;
5159
5160 int N = mPendingThumbnails.size();
5161 int i=0;
5162 while (i<N) {
5163 PendingThumbnailsRecord pr =
5164 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5165 //System.out.println("Looking in " + pr.pendingRecords);
5166 if (pr.pendingRecords.remove(r)) {
5167 if (receivers == null) {
5168 receivers = new ArrayList();
5169 }
5170 receivers.add(pr);
5171 if (pr.pendingRecords.size() == 0) {
5172 pr.finished = true;
5173 mPendingThumbnails.remove(i);
5174 N--;
5175 continue;
5176 }
5177 }
5178 i++;
5179 }
5180 }
5181
5182 if (receivers != null) {
5183 final int N = receivers.size();
5184 for (int i=0; i<N; i++) {
5185 try {
5186 PendingThumbnailsRecord pr =
5187 (PendingThumbnailsRecord)receivers.get(i);
5188 pr.receiver.newThumbnail(
5189 task != null ? task.taskId : -1, thumbnail, description);
5190 if (pr.finished) {
5191 pr.receiver.finished();
5192 }
5193 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005194 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 }
5196 }
5197 }
5198 }
5199
5200 // =========================================================
5201 // CONTENT PROVIDERS
5202 // =========================================================
5203
5204 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5205 List providers = null;
5206 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005207 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005208 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005209 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 } catch (RemoteException ex) {
5211 }
5212 if (providers != null) {
5213 final int N = providers.size();
5214 for (int i=0; i<N; i++) {
5215 ProviderInfo cpi =
5216 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005217 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 if (cpr == null) {
5219 cpr = new ContentProviderRecord(cpi, app.info);
5220 mProvidersByClass.put(cpi.name, cpr);
5221 }
5222 app.pubProviders.put(cpi.name, cpr);
5223 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005224 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 }
5226 }
5227 return providers;
5228 }
5229
5230 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005231 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5233 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5234 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
5235 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005236 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005237 return null;
5238 }
5239 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
5240 cpi.exported ? -1 : cpi.applicationInfo.uid)
5241 == PackageManager.PERMISSION_GRANTED) {
5242 return null;
5243 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005244
5245 PathPermission[] pps = cpi.pathPermissions;
5246 if (pps != null) {
5247 int i = pps.length;
5248 while (i > 0) {
5249 i--;
5250 PathPermission pp = pps[i];
5251 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
5252 cpi.exported ? -1 : cpi.applicationInfo.uid)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005253 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005254 return null;
5255 }
5256 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
5257 cpi.exported ? -1 : cpi.applicationInfo.uid)
5258 == PackageManager.PERMISSION_GRANTED) {
5259 return null;
5260 }
5261 }
5262 }
5263
Dianne Hackbornb424b632010-08-18 15:59:05 -07005264 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5265 if (perms != null) {
5266 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5267 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5268 return null;
5269 }
5270 }
5271 }
5272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 String msg = "Permission Denial: opening provider " + cpi.name
5274 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5275 + ", uid=" + callingUid + ") requires "
5276 + cpi.readPermission + " or " + cpi.writePermission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005277 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 return msg;
5279 }
5280
5281 private final ContentProviderHolder getContentProviderImpl(
5282 IApplicationThread caller, String name) {
5283 ContentProviderRecord cpr;
5284 ProviderInfo cpi = null;
5285
5286 synchronized(this) {
5287 ProcessRecord r = null;
5288 if (caller != null) {
5289 r = getRecordForAppLocked(caller);
5290 if (r == null) {
5291 throw new SecurityException(
5292 "Unable to find app for caller " + caller
5293 + " (pid=" + Binder.getCallingPid()
5294 + ") when getting content provider " + name);
5295 }
5296 }
5297
5298 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005299 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005300 if (cpr != null) {
5301 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005302 String msg;
5303 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5304 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 }
5306
5307 if (r != null && cpr.canRunHere(r)) {
5308 // This provider has been published or is in the process
5309 // of being published... but it is also allowed to run
5310 // in the caller's process, so don't make a connection
5311 // and just let the caller instantiate its own instance.
5312 if (cpr.provider != null) {
5313 // don't give caller the provider object, it needs
5314 // to make its own.
5315 cpr = new ContentProviderRecord(cpr);
5316 }
5317 return cpr;
5318 }
5319
5320 final long origId = Binder.clearCallingIdentity();
5321
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005322 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 // return it right away.
5324 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005325 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005326 "Adding provider requested by "
5327 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005328 + cpr.info.processName);
5329 Integer cnt = r.conProviders.get(cpr);
5330 if (cnt == null) {
5331 r.conProviders.put(cpr, new Integer(1));
5332 } else {
5333 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005336 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5337 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005338 // make sure to count it as being accessed and thus
5339 // back up on the LRU list. This is good because
5340 // content providers are often expensive to start.
5341 updateLruProcessLocked(cpr.app, false, true);
5342 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005343 } else {
5344 cpr.externals++;
5345 }
5346
5347 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 updateOomAdjLocked(cpr.app);
5349 }
5350
5351 Binder.restoreCallingIdentity(origId);
5352
5353 } else {
5354 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005355 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005356 resolveContentProvider(name,
5357 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 } catch (RemoteException ex) {
5359 }
5360 if (cpi == null) {
5361 return null;
5362 }
5363
Dianne Hackbornb424b632010-08-18 15:59:05 -07005364 String msg;
5365 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5366 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367 }
5368
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005369 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005370 && !cpi.processName.equals("system")) {
5371 // If this content provider does not run in the system
5372 // process, and the system is not yet ready to run other
5373 // processes, then fail fast instead of hanging.
5374 throw new IllegalArgumentException(
5375 "Attempt to launch content provider before system ready");
5376 }
5377
Dianne Hackborn860755f2010-06-03 18:47:52 -07005378 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 final boolean firstClass = cpr == null;
5380 if (firstClass) {
5381 try {
5382 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005383 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005384 getApplicationInfo(
5385 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005386 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005387 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005388 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005389 + cpi.name);
5390 return null;
5391 }
5392 cpr = new ContentProviderRecord(cpi, ai);
5393 } catch (RemoteException ex) {
5394 // pm is in same process, this will never happen.
5395 }
5396 }
5397
5398 if (r != null && cpr.canRunHere(r)) {
5399 // If this is a multiprocess provider, then just return its
5400 // info and allow the caller to instantiate it. Only do
5401 // this if the provider is the same user as the caller's
5402 // process, or can run as root (so can be in any process).
5403 return cpr;
5404 }
5405
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005406 if (DEBUG_PROVIDER) {
5407 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005408 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005409 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 }
5411
5412 // This is single process, and our app is now connecting to it.
5413 // See if we are already in the process of launching this
5414 // provider.
5415 final int N = mLaunchingProviders.size();
5416 int i;
5417 for (i=0; i<N; i++) {
5418 if (mLaunchingProviders.get(i) == cpr) {
5419 break;
5420 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 }
5422
5423 // If the provider is not already being launched, then get it
5424 // started.
5425 if (i >= N) {
5426 final long origId = Binder.clearCallingIdentity();
5427 ProcessRecord proc = startProcessLocked(cpi.processName,
5428 cpr.appInfo, false, 0, "content provider",
5429 new ComponentName(cpi.applicationInfo.packageName,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07005430 cpi.name), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005431 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005432 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005433 + cpi.applicationInfo.packageName + "/"
5434 + cpi.applicationInfo.uid + " for provider "
5435 + name + ": process is bad");
5436 return null;
5437 }
5438 cpr.launchingApp = proc;
5439 mLaunchingProviders.add(cpr);
5440 Binder.restoreCallingIdentity(origId);
5441 }
5442
5443 // Make sure the provider is published (the same provider class
5444 // may be published under multiple names).
5445 if (firstClass) {
5446 mProvidersByClass.put(cpi.name, cpr);
5447 }
5448 mProvidersByName.put(name, cpr);
5449
5450 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005451 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005452 "Adding provider requested by "
5453 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005454 + cpr.info.processName);
5455 Integer cnt = r.conProviders.get(cpr);
5456 if (cnt == null) {
5457 r.conProviders.put(cpr, new Integer(1));
5458 } else {
5459 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005461 cpr.clients.add(r);
5462 } else {
5463 cpr.externals++;
5464 }
5465 }
5466 }
5467
5468 // Wait for the provider to be published...
5469 synchronized (cpr) {
5470 while (cpr.provider == null) {
5471 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005472 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 + cpi.applicationInfo.packageName + "/"
5474 + cpi.applicationInfo.uid + " for provider "
5475 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005476 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477 cpi.applicationInfo.packageName,
5478 cpi.applicationInfo.uid, name);
5479 return null;
5480 }
5481 try {
5482 cpr.wait();
5483 } catch (InterruptedException ex) {
5484 }
5485 }
5486 }
5487 return cpr;
5488 }
5489
5490 public final ContentProviderHolder getContentProvider(
5491 IApplicationThread caller, String name) {
5492 if (caller == null) {
5493 String msg = "null IApplicationThread when getting content provider "
5494 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005495 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005496 throw new SecurityException(msg);
5497 }
5498
5499 return getContentProviderImpl(caller, name);
5500 }
5501
5502 private ContentProviderHolder getContentProviderExternal(String name) {
5503 return getContentProviderImpl(null, name);
5504 }
5505
5506 /**
5507 * Drop a content provider from a ProcessRecord's bookkeeping
5508 * @param cpr
5509 */
5510 public void removeContentProvider(IApplicationThread caller, String name) {
5511 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005512 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005514 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005515 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005516 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 return;
5518 }
5519 final ProcessRecord r = getRecordForAppLocked(caller);
5520 if (r == null) {
5521 throw new SecurityException(
5522 "Unable to find app for caller " + caller +
5523 " when removing content provider " + name);
5524 }
5525 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005526 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005527 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005528 + r.info.processName + " from process "
5529 + localCpr.appInfo.processName);
5530 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005531 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005532 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005533 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 return;
5535 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005536 Integer cnt = r.conProviders.get(localCpr);
5537 if (cnt == null || cnt.intValue() <= 1) {
5538 localCpr.clients.remove(r);
5539 r.conProviders.remove(localCpr);
5540 } else {
5541 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005543 }
5544 updateOomAdjLocked();
5545 }
5546 }
5547
5548 private void removeContentProviderExternal(String name) {
5549 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005550 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 if(cpr == null) {
5552 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005553 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005554 return;
5555 }
5556
5557 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005558 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559 localCpr.externals--;
5560 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005561 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005562 }
5563 updateOomAdjLocked();
5564 }
5565 }
5566
5567 public final void publishContentProviders(IApplicationThread caller,
5568 List<ContentProviderHolder> providers) {
5569 if (providers == null) {
5570 return;
5571 }
5572
5573 synchronized(this) {
5574 final ProcessRecord r = getRecordForAppLocked(caller);
5575 if (r == null) {
5576 throw new SecurityException(
5577 "Unable to find app for caller " + caller
5578 + " (pid=" + Binder.getCallingPid()
5579 + ") when publishing content providers");
5580 }
5581
5582 final long origId = Binder.clearCallingIdentity();
5583
5584 final int N = providers.size();
5585 for (int i=0; i<N; i++) {
5586 ContentProviderHolder src = providers.get(i);
5587 if (src == null || src.info == null || src.provider == null) {
5588 continue;
5589 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005590 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005591 if (dst != null) {
5592 mProvidersByClass.put(dst.info.name, dst);
5593 String names[] = dst.info.authority.split(";");
5594 for (int j = 0; j < names.length; j++) {
5595 mProvidersByName.put(names[j], dst);
5596 }
5597
5598 int NL = mLaunchingProviders.size();
5599 int j;
5600 for (j=0; j<NL; j++) {
5601 if (mLaunchingProviders.get(j) == dst) {
5602 mLaunchingProviders.remove(j);
5603 j--;
5604 NL--;
5605 }
5606 }
5607 synchronized (dst) {
5608 dst.provider = src.provider;
5609 dst.app = r;
5610 dst.notifyAll();
5611 }
5612 updateOomAdjLocked(r);
5613 }
5614 }
5615
5616 Binder.restoreCallingIdentity(origId);
5617 }
5618 }
5619
5620 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005621 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005622 synchronized (mSelf) {
5623 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5624 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005625 if (providers != null) {
5626 for (int i=providers.size()-1; i>=0; i--) {
5627 ProviderInfo pi = (ProviderInfo)providers.get(i);
5628 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5629 Slog.w(TAG, "Not installing system proc provider " + pi.name
5630 + ": not system .apk");
5631 providers.remove(i);
5632 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005633 }
5634 }
5635 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005636 if (providers != null) {
5637 mSystemThread.installSystemProviders(providers);
5638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005639 }
5640
Dianne Hackborn8313fc72010-09-26 18:34:53 -07005641 /**
5642 * Allows app to retrieve the MIME type of a URI without having permission
5643 * to access its content provider.
5644 *
5645 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5646 *
5647 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5648 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5649 */
5650 public String getProviderMimeType(Uri uri) {
5651 final String name = uri.getAuthority();
5652 final long ident = Binder.clearCallingIdentity();
5653 ContentProviderHolder holder = null;
5654
5655 try {
5656 holder = getContentProviderExternal(name);
5657 if (holder != null) {
5658 return holder.provider.getType(uri);
5659 }
5660 } catch (RemoteException e) {
5661 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5662 return null;
5663 } finally {
5664 if (holder != null) {
5665 removeContentProviderExternal(name);
5666 }
5667 Binder.restoreCallingIdentity(ident);
5668 }
5669
5670 return null;
5671 }
5672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005673 // =========================================================
5674 // GLOBAL MANAGEMENT
5675 // =========================================================
5676
5677 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5678 ApplicationInfo info, String customProcess) {
5679 String proc = customProcess != null ? customProcess : info.processName;
5680 BatteryStatsImpl.Uid.Proc ps = null;
5681 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5682 synchronized (stats) {
5683 ps = stats.getProcessStatsLocked(info.uid, proc);
5684 }
5685 return new ProcessRecord(ps, thread, info, proc);
5686 }
5687
5688 final ProcessRecord addAppLocked(ApplicationInfo info) {
5689 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5690
5691 if (app == null) {
5692 app = newProcessRecordLocked(null, info, null);
5693 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005694 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005695 }
5696
5697 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5698 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5699 app.persistent = true;
5700 app.maxAdj = CORE_SERVER_ADJ;
5701 }
5702 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5703 mPersistentStartingProcesses.add(app);
5704 startProcessLocked(app, "added application", app.processName);
5705 }
5706
5707 return app;
5708 }
5709
5710 public void unhandledBack() {
5711 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5712 "unhandledBack()");
5713
5714 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005715 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005716 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 TAG, "Performing unhandledBack(): stack size = " + count);
5718 if (count > 1) {
5719 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005720 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005721 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5722 Binder.restoreCallingIdentity(origId);
5723 }
5724 }
5725 }
5726
5727 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5728 String name = uri.getAuthority();
5729 ContentProviderHolder cph = getContentProviderExternal(name);
5730 ParcelFileDescriptor pfd = null;
5731 if (cph != null) {
5732 // We record the binder invoker's uid in thread-local storage before
5733 // going to the content provider to open the file. Later, in the code
5734 // that handles all permissions checks, we look for this uid and use
5735 // that rather than the Activity Manager's own uid. The effect is that
5736 // we do the check against the caller's permissions even though it looks
5737 // to the content provider like the Activity Manager itself is making
5738 // the request.
5739 sCallerIdentity.set(new Identity(
5740 Binder.getCallingPid(), Binder.getCallingUid()));
5741 try {
5742 pfd = cph.provider.openFile(uri, "r");
5743 } catch (FileNotFoundException e) {
5744 // do nothing; pfd will be returned null
5745 } finally {
5746 // Ensure that whatever happens, we clean up the identity state
5747 sCallerIdentity.remove();
5748 }
5749
5750 // We've got the fd now, so we're done with the provider.
5751 removeContentProviderExternal(name);
5752 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005753 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 }
5755 return pfd;
5756 }
5757
5758 public void goingToSleep() {
5759 synchronized(this) {
5760 mSleeping = true;
5761 mWindowManager.setEventDispatching(false);
5762
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005763 if (mMainStack.mResumedActivity != null) {
5764 mMainStack.pauseIfSleepingLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005766 Slog.w(TAG, "goingToSleep with no resumed activity!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005767 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005768
5769 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005770 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005771 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5772 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005773 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005774 }
5775 }
5776
Dianne Hackborn55280a92009-05-07 15:53:46 -07005777 public boolean shutdown(int timeout) {
5778 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5779 != PackageManager.PERMISSION_GRANTED) {
5780 throw new SecurityException("Requires permission "
5781 + android.Manifest.permission.SHUTDOWN);
5782 }
5783
5784 boolean timedout = false;
5785
5786 synchronized(this) {
5787 mShuttingDown = true;
5788 mWindowManager.setEventDispatching(false);
5789
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005790 if (mMainStack.mResumedActivity != null) {
5791 mMainStack.pauseIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005792 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005793 while (mMainStack.mResumedActivity != null
5794 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005795 long delay = endTime - System.currentTimeMillis();
5796 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005797 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005798 timedout = true;
5799 break;
5800 }
5801 try {
5802 this.wait();
5803 } catch (InterruptedException e) {
5804 }
5805 }
5806 }
5807 }
5808
5809 mUsageStatsService.shutdown();
5810 mBatteryStatsService.shutdown();
5811
5812 return timedout;
5813 }
5814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 public void wakingUp() {
5816 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005817 if (mMainStack.mGoingToSleep.isHeld()) {
5818 mMainStack.mGoingToSleep.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 }
5820 mWindowManager.setEventDispatching(true);
5821 mSleeping = false;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005822 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 }
5824 }
5825
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005826 public void stopAppSwitches() {
5827 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5828 != PackageManager.PERMISSION_GRANTED) {
5829 throw new SecurityException("Requires permission "
5830 + android.Manifest.permission.STOP_APP_SWITCHES);
5831 }
5832
5833 synchronized(this) {
5834 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
5835 + APP_SWITCH_DELAY_TIME;
5836 mDidAppSwitch = false;
5837 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5838 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
5839 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
5840 }
5841 }
5842
5843 public void resumeAppSwitches() {
5844 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
5845 != PackageManager.PERMISSION_GRANTED) {
5846 throw new SecurityException("Requires permission "
5847 + android.Manifest.permission.STOP_APP_SWITCHES);
5848 }
5849
5850 synchronized(this) {
5851 // Note that we don't execute any pending app switches... we will
5852 // let those wait until either the timeout, or the next start
5853 // activity request.
5854 mAppSwitchesAllowedTime = 0;
5855 }
5856 }
5857
5858 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
5859 String name) {
5860 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
5861 return true;
5862 }
5863
5864 final int perm = checkComponentPermission(
5865 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
5866 callingUid, -1);
5867 if (perm == PackageManager.PERMISSION_GRANTED) {
5868 return true;
5869 }
5870
Joe Onorato8a9b2202010-02-26 18:56:32 -08005871 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005872 return false;
5873 }
5874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005875 public void setDebugApp(String packageName, boolean waitForDebugger,
5876 boolean persistent) {
5877 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
5878 "setDebugApp()");
5879
5880 // Note that this is not really thread safe if there are multiple
5881 // callers into it at the same time, but that's not a situation we
5882 // care about.
5883 if (persistent) {
5884 final ContentResolver resolver = mContext.getContentResolver();
5885 Settings.System.putString(
5886 resolver, Settings.System.DEBUG_APP,
5887 packageName);
5888 Settings.System.putInt(
5889 resolver, Settings.System.WAIT_FOR_DEBUGGER,
5890 waitForDebugger ? 1 : 0);
5891 }
5892
5893 synchronized (this) {
5894 if (!persistent) {
5895 mOrigDebugApp = mDebugApp;
5896 mOrigWaitForDebugger = mWaitForDebugger;
5897 }
5898 mDebugApp = packageName;
5899 mWaitForDebugger = waitForDebugger;
5900 mDebugTransient = !persistent;
5901 if (packageName != null) {
5902 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005903 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 Binder.restoreCallingIdentity(origId);
5905 }
5906 }
5907 }
5908
5909 public void setAlwaysFinish(boolean enabled) {
5910 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
5911 "setAlwaysFinish()");
5912
5913 Settings.System.putInt(
5914 mContext.getContentResolver(),
5915 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
5916
5917 synchronized (this) {
5918 mAlwaysFinishActivities = enabled;
5919 }
5920 }
5921
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005922 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005923 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005924 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005925 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005926 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005927 }
5928 }
5929
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08005930 public boolean isUserAMonkey() {
5931 // For now the fact that there is a controller implies
5932 // we have a monkey.
5933 synchronized (this) {
5934 return mController != null;
5935 }
5936 }
5937
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005938 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005939 synchronized (this) {
5940 mWatchers.register(watcher);
5941 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005942 }
5943
5944 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06005945 synchronized (this) {
5946 mWatchers.unregister(watcher);
5947 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005948 }
5949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005950 public final void enterSafeMode() {
5951 synchronized(this) {
5952 // It only makes sense to do this before the system is ready
5953 // and started launching other packages.
5954 if (!mSystemReady) {
5955 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005956 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 } catch (RemoteException e) {
5958 }
5959
5960 View v = LayoutInflater.from(mContext).inflate(
5961 com.android.internal.R.layout.safe_mode, null);
5962 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
5963 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
5964 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
5965 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
5966 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
5967 lp.format = v.getBackground().getOpacity();
5968 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5969 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
5970 ((WindowManager)mContext.getSystemService(
5971 Context.WINDOW_SERVICE)).addView(v, lp);
5972 }
5973 }
5974 }
5975
5976 public void noteWakeupAlarm(IIntentSender sender) {
5977 if (!(sender instanceof PendingIntentRecord)) {
5978 return;
5979 }
5980 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5981 synchronized (stats) {
5982 if (mBatteryStatsService.isOnBattery()) {
5983 mBatteryStatsService.enforceCallingPermission();
5984 PendingIntentRecord rec = (PendingIntentRecord)sender;
5985 int MY_UID = Binder.getCallingUid();
5986 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
5987 BatteryStatsImpl.Uid.Pkg pkg =
5988 stats.getPackageStatsLocked(uid, rec.key.packageName);
5989 pkg.incWakeupsLocked();
5990 }
5991 }
5992 }
5993
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005994 public boolean killPids(int[] pids, String pReason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005995 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005996 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07005998 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005999 // XXX Note: don't acquire main activity lock here, because the window
6000 // manager calls in with its locks held.
6001
6002 boolean killed = false;
6003 synchronized (mPidsSelfLocked) {
6004 int[] types = new int[pids.length];
6005 int worstType = 0;
6006 for (int i=0; i<pids.length; i++) {
6007 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6008 if (proc != null) {
6009 int type = proc.setAdj;
6010 types[i] = type;
6011 if (type > worstType) {
6012 worstType = type;
6013 }
6014 }
6015 }
6016
6017 // If the worse oom_adj is somewhere in the hidden proc LRU range,
6018 // then constrain it so we will kill all hidden procs.
6019 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6020 worstType = HIDDEN_APP_MIN_ADJ;
6021 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006022 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006023 for (int i=0; i<pids.length; i++) {
6024 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6025 if (proc == null) {
6026 continue;
6027 }
6028 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006029 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006030 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006031 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6032 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006034 proc.killedBackground = true;
6035 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006036 }
6037 }
6038 }
6039 return killed;
6040 }
6041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 public final void startRunning(String pkg, String cls, String action,
6043 String data) {
6044 synchronized(this) {
6045 if (mStartRunning) {
6046 return;
6047 }
6048 mStartRunning = true;
6049 mTopComponent = pkg != null && cls != null
6050 ? new ComponentName(pkg, cls) : null;
6051 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6052 mTopData = data;
6053 if (!mSystemReady) {
6054 return;
6055 }
6056 }
6057
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006058 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006059 }
6060
6061 private void retrieveSettings() {
6062 final ContentResolver resolver = mContext.getContentResolver();
6063 String debugApp = Settings.System.getString(
6064 resolver, Settings.System.DEBUG_APP);
6065 boolean waitForDebugger = Settings.System.getInt(
6066 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6067 boolean alwaysFinishActivities = Settings.System.getInt(
6068 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6069
6070 Configuration configuration = new Configuration();
6071 Settings.System.getConfiguration(resolver, configuration);
6072
6073 synchronized (this) {
6074 mDebugApp = mOrigDebugApp = debugApp;
6075 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6076 mAlwaysFinishActivities = alwaysFinishActivities;
6077 // This happens before any activities are started, so we can
6078 // change mConfiguration in-place.
6079 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006080 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006081 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006082 }
6083 }
6084
6085 public boolean testIsSystemReady() {
6086 // no need to synchronize(this) just to read & return the value
6087 return mSystemReady;
6088 }
6089
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006090 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006091 // In the simulator, startRunning will never have been called, which
6092 // normally sets a few crucial variables. Do it here instead.
6093 if (!Process.supportsProcesses()) {
6094 mStartRunning = true;
6095 mTopAction = Intent.ACTION_MAIN;
6096 }
6097
6098 synchronized(this) {
6099 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006100 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006101 return;
6102 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006103
6104 // Check to see if there are any update receivers to run.
6105 if (!mDidUpdate) {
6106 if (mWaitingUpdate) {
6107 return;
6108 }
6109 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6110 List<ResolveInfo> ris = null;
6111 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006112 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006113 intent, null, 0);
6114 } catch (RemoteException e) {
6115 }
6116 if (ris != null) {
6117 for (int i=ris.size()-1; i>=0; i--) {
6118 if ((ris.get(i).activityInfo.applicationInfo.flags
6119 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6120 ris.remove(i);
6121 }
6122 }
6123 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
6124 for (int i=0; i<ris.size(); i++) {
6125 ActivityInfo ai = ris.get(i).activityInfo;
6126 intent.setComponent(new ComponentName(ai.packageName, ai.name));
6127 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006128 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006129 finisher = new IIntentReceiver.Stub() {
6130 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006131 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006132 boolean sticky) {
6133 // The raw IIntentReceiver interface is called
6134 // with the AM lock held, so redispatch to
6135 // execute our code without the lock.
6136 mHandler.post(new Runnable() {
6137 public void run() {
6138 synchronized (ActivityManagerService.this) {
6139 mDidUpdate = true;
6140 }
6141 systemReady(goingCallback);
6142 }
6143 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006144 }
6145 };
6146 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006147 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006148 broadcastIntentLocked(null, null, intent, null, finisher,
6149 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006150 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006151 mWaitingUpdate = true;
6152 }
6153 }
6154 }
6155 if (mWaitingUpdate) {
6156 return;
6157 }
6158 mDidUpdate = true;
6159 }
6160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006161 mSystemReady = true;
6162 if (!mStartRunning) {
6163 return;
6164 }
6165 }
6166
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006167 ArrayList<ProcessRecord> procsToKill = null;
6168 synchronized(mPidsSelfLocked) {
6169 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6170 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6171 if (!isAllowedWhileBooting(proc.info)){
6172 if (procsToKill == null) {
6173 procsToKill = new ArrayList<ProcessRecord>();
6174 }
6175 procsToKill.add(proc);
6176 }
6177 }
6178 }
6179
6180 if (procsToKill != null) {
6181 synchronized(this) {
6182 for (int i=procsToKill.size()-1; i>=0; i--) {
6183 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006184 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006185 removeProcessLocked(proc, true);
6186 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07006187
6188 // Now that we have cleaned up any update processes, we
6189 // are ready to start launching real processes and know that
6190 // we won't trample on them any more.
6191 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006192 }
6193 }
6194
Joe Onorato8a9b2202010-02-26 18:56:32 -08006195 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006196 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006197 SystemClock.uptimeMillis());
6198
6199 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006200 // Make sure we have no pre-ready processes sitting around.
6201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006202 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6203 ResolveInfo ri = mContext.getPackageManager()
6204 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006205 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 CharSequence errorMsg = null;
6207 if (ri != null) {
6208 ActivityInfo ai = ri.activityInfo;
6209 ApplicationInfo app = ai.applicationInfo;
6210 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6211 mTopAction = Intent.ACTION_FACTORY_TEST;
6212 mTopData = null;
6213 mTopComponent = new ComponentName(app.packageName,
6214 ai.name);
6215 } else {
6216 errorMsg = mContext.getResources().getText(
6217 com.android.internal.R.string.factorytest_not_system);
6218 }
6219 } else {
6220 errorMsg = mContext.getResources().getText(
6221 com.android.internal.R.string.factorytest_no_action);
6222 }
6223 if (errorMsg != null) {
6224 mTopAction = null;
6225 mTopData = null;
6226 mTopComponent = null;
6227 Message msg = Message.obtain();
6228 msg.what = SHOW_FACTORY_ERROR_MSG;
6229 msg.getData().putCharSequence("msg", errorMsg);
6230 mHandler.sendMessage(msg);
6231 }
6232 }
6233 }
6234
6235 retrieveSettings();
6236
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006237 if (goingCallback != null) goingCallback.run();
6238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006239 synchronized (this) {
6240 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6241 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006242 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006243 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006244 if (apps != null) {
6245 int N = apps.size();
6246 int i;
6247 for (i=0; i<N; i++) {
6248 ApplicationInfo info
6249 = (ApplicationInfo)apps.get(i);
6250 if (info != null &&
6251 !info.packageName.equals("android")) {
6252 addAppLocked(info);
6253 }
6254 }
6255 }
6256 } catch (RemoteException ex) {
6257 // pm is in same process, this will never happen.
6258 }
6259 }
6260
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006261 // Start up initial activity.
6262 mBooting = true;
6263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006264 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006265 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006266 Message msg = Message.obtain();
6267 msg.what = SHOW_UID_ERROR_MSG;
6268 mHandler.sendMessage(msg);
6269 }
6270 } catch (RemoteException e) {
6271 }
6272
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006273 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 }
6275 }
6276
Dan Egnorb7f03672009-12-09 16:22:32 -08006277 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006278 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006279 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006280 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006281 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006282 startAppProblemLocked(app);
6283 app.stopFreezingAllLocked();
6284 return handleAppCrashLocked(app);
6285 }
6286
Dan Egnorb7f03672009-12-09 16:22:32 -08006287 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006288 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006290 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006291 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6292 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 startAppProblemLocked(app);
6294 app.stopFreezingAllLocked();
6295 }
6296
6297 /**
6298 * Generate a process error record, suitable for attachment to a ProcessRecord.
6299 *
6300 * @param app The ProcessRecord in which the error occurred.
6301 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6302 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006303 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 * @param shortMsg Short message describing the crash.
6305 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006306 * @param stackTrace Full crash stack trace, may be null.
6307 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006308 * @return Returns a fully-formed AppErrorStateInfo record.
6309 */
6310 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006311 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006312 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006314 report.condition = condition;
6315 report.processName = app.processName;
6316 report.pid = app.pid;
6317 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006318 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006319 report.shortMsg = shortMsg;
6320 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006321 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322
6323 return report;
6324 }
6325
Dan Egnor42471dd2010-01-07 17:25:22 -08006326 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 synchronized (this) {
6328 app.crashing = false;
6329 app.crashingReport = null;
6330 app.notResponding = false;
6331 app.notRespondingReport = null;
6332 if (app.anrDialog == fromDialog) {
6333 app.anrDialog = null;
6334 }
6335 if (app.waitDialog == fromDialog) {
6336 app.waitDialog = null;
6337 }
6338 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006339 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006340 Slog.i(ActivityManagerService.TAG, "Killing "
6341 + app.processName + " (pid=" + app.pid + "): user's request");
6342 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6343 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006344 Process.killProcess(app.pid);
6345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 }
6347 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006348
Dan Egnorb7f03672009-12-09 16:22:32 -08006349 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006350 long now = SystemClock.uptimeMillis();
6351
6352 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6353 app.info.uid);
6354 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6355 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006356 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006357 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006358 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359 app.info.processName, app.info.uid);
6360 killServicesLocked(app, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006361 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6362 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006364 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006366 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006367 }
6368 }
6369 if (!app.persistent) {
6370 // We don't want to start this process again until the user
6371 // explicitly does so... but for persistent process, we really
6372 // need to keep it running. If a persistent process is actually
6373 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006374 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 app.info.processName);
6376 mBadProcesses.put(app.info.processName, app.info.uid, now);
6377 app.bad = true;
6378 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6379 app.removed = true;
6380 removeProcessLocked(app, false);
6381 return false;
6382 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006383 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006384 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006385 if (r.app == app) {
6386 // If the top running activity is from this crashing
6387 // process, then terminate it to avoid getting in a loop.
6388 Slog.w(TAG, " Force finishing activity "
6389 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006390 int index = mMainStack.indexOfTokenLocked(r);
6391 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006392 Activity.RESULT_CANCELED, null, "crashed");
6393 // Also terminate an activities below it that aren't yet
6394 // stopped, to avoid a situation where one will get
6395 // re-start our crashing activity once it gets resumed again.
6396 index--;
6397 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006398 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006399 if (r.state == ActivityState.RESUMED
6400 || r.state == ActivityState.PAUSING
6401 || r.state == ActivityState.PAUSED) {
6402 if (!r.isHomeActivity) {
6403 Slog.w(TAG, " Force finishing activity "
6404 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006405 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006406 Activity.RESULT_CANCELED, null, "crashed");
6407 }
6408 }
6409 }
6410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006411 }
6412
6413 // Bump up the crash count of any services currently running in the proc.
6414 if (app.services.size() != 0) {
6415 // Any services running in the application need to be placed
6416 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006417 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006418 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006419 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 sr.crashCount++;
6421 }
6422 }
6423
6424 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6425 return true;
6426 }
6427
6428 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006429 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6430 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006431 skipCurrentReceiverLocked(app);
6432 }
6433
6434 void skipCurrentReceiverLocked(ProcessRecord app) {
6435 boolean reschedule = false;
6436 BroadcastRecord r = app.curReceiver;
6437 if (r != null) {
6438 // The current broadcast is waiting for this app's receiver
6439 // to be finished. Looks like that's not going to happen, so
6440 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006441 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6443 r.resultExtras, r.resultAbort, true);
6444 reschedule = true;
6445 }
6446 r = mPendingBroadcast;
6447 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006448 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006449 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006450 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6452 r.resultExtras, r.resultAbort, true);
6453 reschedule = true;
6454 }
6455 if (reschedule) {
6456 scheduleBroadcastsLocked();
6457 }
6458 }
6459
Dan Egnor60d87622009-12-16 16:32:58 -08006460 /**
6461 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6462 * The application process will exit immediately after this call returns.
6463 * @param app object of the crashing app, null for the system server
6464 * @param crashInfo describing the exception
6465 */
6466 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6467 ProcessRecord r = findAppProcess(app);
6468
6469 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6470 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006471 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006472 crashInfo.exceptionClassName,
6473 crashInfo.exceptionMessage,
6474 crashInfo.throwFileName,
6475 crashInfo.throwLineNumber);
6476
Dan Egnor42471dd2010-01-07 17:25:22 -08006477 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006478
6479 crashApplication(r, crashInfo);
6480 }
6481
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006482 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006483 IBinder app,
6484 int violationMask,
6485 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006486 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006487
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006488 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006489 Integer stackFingerprint = info.crashInfo.stackTrace.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006490 boolean logIt = true;
6491 synchronized (mAlreadyLoggedViolatedStacks) {
6492 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6493 logIt = false;
6494 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006495 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006496 // the relative pain numbers, without logging all
6497 // the stack traces repeatedly. We'd want to do
6498 // likewise in the client code, which also does
6499 // dup suppression, before the Binder call.
6500 } else {
6501 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6502 mAlreadyLoggedViolatedStacks.clear();
6503 }
6504 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6505 }
6506 }
6507 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006508 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006509 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006510 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006511
6512 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6513 AppErrorResult result = new AppErrorResult();
6514 synchronized (this) {
6515 final long origId = Binder.clearCallingIdentity();
6516
6517 Message msg = Message.obtain();
6518 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6519 HashMap<String, Object> data = new HashMap<String, Object>();
6520 data.put("result", result);
6521 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006522 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006523 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006524 msg.obj = data;
6525 mHandler.sendMessage(msg);
6526
6527 Binder.restoreCallingIdentity(origId);
6528 }
6529 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006530 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006531 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006532 }
6533
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006534 // Depending on the policy in effect, there could be a bunch of
6535 // these in quick succession so we try to batch these together to
6536 // minimize disk writes, number of dropbox entries, and maximize
6537 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006538 private void logStrictModeViolationToDropBox(
6539 ProcessRecord process,
6540 StrictMode.ViolationInfo info) {
6541 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006542 return;
6543 }
6544 final boolean isSystemApp = process == null ||
6545 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6546 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6547 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6548 final DropBoxManager dbox = (DropBoxManager)
6549 mContext.getSystemService(Context.DROPBOX_SERVICE);
6550
6551 // Exit early if the dropbox isn't configured to accept this report type.
6552 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6553
6554 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006555 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006556 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6557 synchronized (sb) {
6558 bufferWasEmpty = sb.length() == 0;
6559 appendDropBoxProcessHeaders(process, sb);
6560 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6561 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006562 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6563 if (info.violationNumThisLoop != 0) {
6564 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6565 }
6566 if (info != null && info.durationMillis != -1) {
6567 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006568 }
6569 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006570 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6571 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006572 }
6573 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006574
6575 // Only buffer up to ~64k. Various logging bits truncate
6576 // things at 128k.
6577 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006578 }
6579
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006580 // Flush immediately if the buffer's grown too large, or this
6581 // is a non-system app. Non-system apps are isolated with a
6582 // different tag & policy and not batched.
6583 //
6584 // Batching is useful during internal testing with
6585 // StrictMode settings turned up high. Without batching,
6586 // thousands of separate files could be created on boot.
6587 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006588 new Thread("Error dump: " + dropboxTag) {
6589 @Override
6590 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006591 String report;
6592 synchronized (sb) {
6593 report = sb.toString();
6594 sb.delete(0, sb.length());
6595 sb.trimToSize();
6596 }
6597 if (report.length() != 0) {
6598 dbox.addText(dropboxTag, report);
6599 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006600 }
6601 }.start();
6602 return;
6603 }
6604
6605 // System app batching:
6606 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006607 // An existing dropbox-writing thread is outstanding, so
6608 // we don't need to start it up. The existing thread will
6609 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006610 return;
6611 }
6612
6613 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6614 // (After this point, we shouldn't access AMS internal data structures.)
6615 new Thread("Error dump: " + dropboxTag) {
6616 @Override
6617 public void run() {
6618 // 5 second sleep to let stacks arrive and be batched together
6619 try {
6620 Thread.sleep(5000); // 5 seconds
6621 } catch (InterruptedException e) {}
6622
6623 String errorReport;
6624 synchronized (mStrictModeBuffer) {
6625 errorReport = mStrictModeBuffer.toString();
6626 if (errorReport.length() == 0) {
6627 return;
6628 }
6629 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6630 mStrictModeBuffer.trimToSize();
6631 }
6632 dbox.addText(dropboxTag, errorReport);
6633 }
6634 }.start();
6635 }
6636
Dan Egnor60d87622009-12-16 16:32:58 -08006637 /**
6638 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6639 * @param app object of the crashing app, null for the system server
6640 * @param tag reported by the caller
6641 * @param crashInfo describing the context of the error
6642 * @return true if the process should exit immediately (WTF is fatal)
6643 */
6644 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006645 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006646 ProcessRecord r = findAppProcess(app);
6647
6648 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6649 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006650 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006651 tag, crashInfo.exceptionMessage);
6652
Dan Egnor42471dd2010-01-07 17:25:22 -08006653 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006654
Doug Zongker43866e02010-01-07 12:09:54 -08006655 if (Settings.Secure.getInt(mContext.getContentResolver(),
6656 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006657 crashApplication(r, crashInfo);
6658 return true;
6659 } else {
6660 return false;
6661 }
6662 }
6663
6664 /**
6665 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
6666 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
6667 */
6668 private ProcessRecord findAppProcess(IBinder app) {
6669 if (app == null) {
6670 return null;
6671 }
6672
6673 synchronized (this) {
6674 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
6675 final int NA = apps.size();
6676 for (int ia=0; ia<NA; ia++) {
6677 ProcessRecord p = apps.valueAt(ia);
6678 if (p.thread != null && p.thread.asBinder() == app) {
6679 return p;
6680 }
6681 }
6682 }
6683
Joe Onorato8a9b2202010-02-26 18:56:32 -08006684 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08006685 return null;
6686 }
6687 }
6688
6689 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006690 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
6691 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08006692 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07006693 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
6694 // Note: ProcessRecord 'process' is guarded by the service
6695 // instance. (notably process.pkgList, which could otherwise change
6696 // concurrently during execution of this method)
6697 synchronized (this) {
6698 if (process == null || process.pid == MY_PID) {
6699 sb.append("Process: system_server\n");
6700 } else {
6701 sb.append("Process: ").append(process.processName).append("\n");
6702 }
6703 if (process == null) {
6704 return;
6705 }
Dan Egnora455d192010-03-12 08:52:28 -08006706 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006707 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08006708 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
6709 for (String pkg : process.pkgList) {
6710 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08006711 try {
Dan Egnora455d192010-03-12 08:52:28 -08006712 PackageInfo pi = pm.getPackageInfo(pkg, 0);
6713 if (pi != null) {
6714 sb.append(" v").append(pi.versionCode);
6715 if (pi.versionName != null) {
6716 sb.append(" (").append(pi.versionName).append(")");
6717 }
6718 }
6719 } catch (RemoteException e) {
6720 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08006721 }
Dan Egnora455d192010-03-12 08:52:28 -08006722 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08006723 }
Dan Egnora455d192010-03-12 08:52:28 -08006724 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006725 }
6726
6727 private static String processClass(ProcessRecord process) {
6728 if (process == null || process.pid == MY_PID) {
6729 return "system_server";
6730 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6731 return "system_app";
6732 } else {
6733 return "data_app";
6734 }
6735 }
6736
6737 /**
6738 * Write a description of an error (crash, WTF, ANR) to the drop box.
6739 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
6740 * @param process which caused the error, null means the system server
6741 * @param activity which triggered the error, null if unknown
6742 * @param parent activity related to the error, null if unknown
6743 * @param subject line related to the error, null if absent
6744 * @param report in long form describing the error, null if absent
6745 * @param logFile to include in the report, null if none
6746 * @param crashInfo giving an application stack trace, null if absent
6747 */
6748 public void addErrorToDropBox(String eventType,
6749 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
6750 final String report, final File logFile,
6751 final ApplicationErrorReport.CrashInfo crashInfo) {
6752 // NOTE -- this must never acquire the ActivityManagerService lock,
6753 // otherwise the watchdog may be prevented from resetting the system.
6754
6755 final String dropboxTag = processClass(process) + "_" + eventType;
6756 final DropBoxManager dbox = (DropBoxManager)
6757 mContext.getSystemService(Context.DROPBOX_SERVICE);
6758
6759 // Exit early if the dropbox isn't configured to accept this report type.
6760 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6761
6762 final StringBuilder sb = new StringBuilder(1024);
6763 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08006764 if (activity != null) {
6765 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
6766 }
6767 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
6768 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
6769 }
6770 if (parent != null && parent != activity) {
6771 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
6772 }
6773 if (subject != null) {
6774 sb.append("Subject: ").append(subject).append("\n");
6775 }
6776 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6777 sb.append("\n");
6778
6779 // Do the rest in a worker thread to avoid blocking the caller on I/O
6780 // (After this point, we shouldn't access AMS internal data structures.)
6781 Thread worker = new Thread("Error dump: " + dropboxTag) {
6782 @Override
6783 public void run() {
6784 if (report != null) {
6785 sb.append(report);
6786 }
6787 if (logFile != null) {
6788 try {
6789 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
6790 } catch (IOException e) {
6791 Slog.e(TAG, "Error reading " + logFile, e);
6792 }
6793 }
6794 if (crashInfo != null && crashInfo.stackTrace != null) {
6795 sb.append(crashInfo.stackTrace);
6796 }
6797
6798 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
6799 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
6800 if (lines > 0) {
6801 sb.append("\n");
6802
6803 // Merge several logcat streams, and take the last N lines
6804 InputStreamReader input = null;
6805 try {
6806 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
6807 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
6808 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
6809
6810 try { logcat.getOutputStream().close(); } catch (IOException e) {}
6811 try { logcat.getErrorStream().close(); } catch (IOException e) {}
6812 input = new InputStreamReader(logcat.getInputStream());
6813
6814 int num;
6815 char[] buf = new char[8192];
6816 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
6817 } catch (IOException e) {
6818 Slog.e(TAG, "Error running logcat", e);
6819 } finally {
6820 if (input != null) try { input.close(); } catch (IOException e) {}
6821 }
6822 }
6823
6824 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08006825 }
Dan Egnora455d192010-03-12 08:52:28 -08006826 };
6827
6828 if (process == null || process.pid == MY_PID) {
6829 worker.run(); // We may be about to die -- need to run this synchronously
6830 } else {
6831 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08006832 }
6833 }
6834
6835 /**
6836 * Bring up the "unexpected error" dialog box for a crashing app.
6837 * Deal with edge cases (intercepts from instrumented applications,
6838 * ActivityController, error intent receivers, that sort of thing).
6839 * @param r the application crashing
6840 * @param crashInfo describing the failure
6841 */
6842 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006843 long timeMillis = System.currentTimeMillis();
6844 String shortMsg = crashInfo.exceptionClassName;
6845 String longMsg = crashInfo.exceptionMessage;
6846 String stackTrace = crashInfo.stackTrace;
6847 if (shortMsg != null && longMsg != null) {
6848 longMsg = shortMsg + ": " + longMsg;
6849 } else if (shortMsg != null) {
6850 longMsg = shortMsg;
6851 }
6852
Dan Egnor60d87622009-12-16 16:32:58 -08006853 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006855 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006856 try {
6857 String name = r != null ? r.processName : null;
6858 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08006859 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08006860 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006861 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006862 + " at watcher's request");
6863 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08006864 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006865 }
6866 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006867 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006868 }
6869 }
6870
6871 final long origId = Binder.clearCallingIdentity();
6872
6873 // If this process is running instrumentation, finish it.
6874 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006875 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006876 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006877 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
6878 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006879 Bundle info = new Bundle();
6880 info.putString("shortMsg", shortMsg);
6881 info.putString("longMsg", longMsg);
6882 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
6883 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006884 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006885 }
6886
Dan Egnor60d87622009-12-16 16:32:58 -08006887 // If we can't identify the process or it's already exceeded its crash quota,
6888 // quit right away without showing a crash dialog.
6889 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006890 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08006891 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006892 }
6893
6894 Message msg = Message.obtain();
6895 msg.what = SHOW_ERROR_MSG;
6896 HashMap data = new HashMap();
6897 data.put("result", result);
6898 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006899 msg.obj = data;
6900 mHandler.sendMessage(msg);
6901
6902 Binder.restoreCallingIdentity(origId);
6903 }
6904
6905 int res = result.get();
6906
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006907 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006908 synchronized (this) {
6909 if (r != null) {
6910 mProcessCrashTimes.put(r.info.processName, r.info.uid,
6911 SystemClock.uptimeMillis());
6912 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006913 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08006914 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006915 }
6916 }
6917
6918 if (appErrorIntent != null) {
6919 try {
6920 mContext.startActivity(appErrorIntent);
6921 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006922 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006925 }
Dan Egnorb7f03672009-12-09 16:22:32 -08006926
6927 Intent createAppErrorIntentLocked(ProcessRecord r,
6928 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
6929 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006930 if (report == null) {
6931 return null;
6932 }
6933 Intent result = new Intent(Intent.ACTION_APP_ERROR);
6934 result.setComponent(r.errorReportReceiver);
6935 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
6936 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6937 return result;
6938 }
6939
Dan Egnorb7f03672009-12-09 16:22:32 -08006940 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
6941 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006942 if (r.errorReportReceiver == null) {
6943 return null;
6944 }
6945
6946 if (!r.crashing && !r.notResponding) {
6947 return null;
6948 }
6949
Dan Egnorb7f03672009-12-09 16:22:32 -08006950 ApplicationErrorReport report = new ApplicationErrorReport();
6951 report.packageName = r.info.packageName;
6952 report.installerPackageName = r.errorReportReceiver.getPackageName();
6953 report.processName = r.processName;
6954 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01006955 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006956
Dan Egnorb7f03672009-12-09 16:22:32 -08006957 if (r.crashing) {
6958 report.type = ApplicationErrorReport.TYPE_CRASH;
6959 report.crashInfo = crashInfo;
6960 } else if (r.notResponding) {
6961 report.type = ApplicationErrorReport.TYPE_ANR;
6962 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006963
Dan Egnorb7f03672009-12-09 16:22:32 -08006964 report.anrInfo.activity = r.notRespondingReport.tag;
6965 report.anrInfo.cause = r.notRespondingReport.shortMsg;
6966 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006967 }
6968
Dan Egnorb7f03672009-12-09 16:22:32 -08006969 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02006970 }
6971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
6973 // assume our apps are happy - lazy create the list
6974 List<ActivityManager.ProcessErrorStateInfo> errList = null;
6975
6976 synchronized (this) {
6977
6978 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006979 for (int i=mLruProcesses.size()-1; i>=0; i--) {
6980 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006981 if ((app.thread != null) && (app.crashing || app.notResponding)) {
6982 // This one's in trouble, so we'll generate a report for it
6983 // crashes are higher priority (in case there's a crash *and* an anr)
6984 ActivityManager.ProcessErrorStateInfo report = null;
6985 if (app.crashing) {
6986 report = app.crashingReport;
6987 } else if (app.notResponding) {
6988 report = app.notRespondingReport;
6989 }
6990
6991 if (report != null) {
6992 if (errList == null) {
6993 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
6994 }
6995 errList.add(report);
6996 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006997 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998 " crashing = " + app.crashing +
6999 " notResponding = " + app.notResponding);
7000 }
7001 }
7002 }
7003 }
7004
7005 return errList;
7006 }
7007
7008 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7009 // Lazy instantiation of list
7010 List<ActivityManager.RunningAppProcessInfo> runList = null;
7011 synchronized (this) {
7012 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007013 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7014 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007015 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7016 // Generate process state info for running application
7017 ActivityManager.RunningAppProcessInfo currApp =
7018 new ActivityManager.RunningAppProcessInfo(app.processName,
7019 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007020 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007021 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007022 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007024 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007025 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7027 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7028 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007029 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7030 } else if (adj >= HOME_APP_ADJ) {
7031 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7032 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007033 } else if (adj >= SECONDARY_SERVER_ADJ) {
7034 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007035 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
7036 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
7037 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7038 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007039 } else if (adj >= VISIBLE_APP_ADJ) {
7040 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7041 } else {
7042 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7043 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007044 currApp.importanceReasonCode = app.adjTypeCode;
7045 if (app.adjSource instanceof ProcessRecord) {
7046 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007047 } else if (app.adjSource instanceof ActivityRecord) {
7048 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007049 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7050 }
7051 if (app.adjTarget instanceof ComponentName) {
7052 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7053 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007054 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007055 // + " lru=" + currApp.lru);
7056 if (runList == null) {
7057 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7058 }
7059 runList.add(currApp);
7060 }
7061 }
7062 }
7063 return runList;
7064 }
7065
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007066 public List<ApplicationInfo> getRunningExternalApplications() {
7067 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7068 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7069 if (runningApps != null && runningApps.size() > 0) {
7070 Set<String> extList = new HashSet<String>();
7071 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7072 if (app.pkgList != null) {
7073 for (String pkg : app.pkgList) {
7074 extList.add(pkg);
7075 }
7076 }
7077 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007078 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007079 for (String pkg : extList) {
7080 try {
7081 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7082 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7083 retList.add(info);
7084 }
7085 } catch (RemoteException e) {
7086 }
7087 }
7088 }
7089 return retList;
7090 }
7091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 @Override
7093 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007094 if (checkCallingPermission(android.Manifest.permission.DUMP)
7095 != PackageManager.PERMISSION_GRANTED) {
7096 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7097 + Binder.getCallingPid()
7098 + ", uid=" + Binder.getCallingUid()
7099 + " without permission "
7100 + android.Manifest.permission.DUMP);
7101 return;
7102 }
7103
7104 boolean dumpAll = false;
7105
7106 int opti = 0;
7107 while (opti < args.length) {
7108 String opt = args[opti];
7109 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7110 break;
7111 }
7112 opti++;
7113 if ("-a".equals(opt)) {
7114 dumpAll = true;
7115 } else if ("-h".equals(opt)) {
7116 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007117 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007118 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007119 pw.println(" a[ctivities]: activity stack state");
7120 pw.println(" b[roadcasts]: broadcast state");
7121 pw.println(" i[ntents]: pending intent state");
7122 pw.println(" p[rocesses]: process state");
7123 pw.println(" o[om]: out of memory management");
7124 pw.println(" prov[iders]: content provider state");
7125 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007126 pw.println(" service [name]: service client-side state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007127 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007128 } else {
7129 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007131 }
7132
7133 // Is the caller requesting to dump a particular piece of data?
7134 if (opti < args.length) {
7135 String cmd = args[opti];
7136 opti++;
7137 if ("activities".equals(cmd) || "a".equals(cmd)) {
7138 synchronized (this) {
7139 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007141 return;
7142 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7143 synchronized (this) {
7144 dumpBroadcastsLocked(fd, pw, args, opti, true);
7145 }
7146 return;
7147 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7148 synchronized (this) {
7149 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7150 }
7151 return;
7152 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7153 synchronized (this) {
7154 dumpProcessesLocked(fd, pw, args, opti, true);
7155 }
7156 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007157 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7158 synchronized (this) {
7159 dumpOomLocked(fd, pw, args, opti, true);
7160 }
7161 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007162 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7163 synchronized (this) {
7164 dumpProvidersLocked(fd, pw, args, opti, true);
7165 }
7166 return;
7167 } else if ("service".equals(cmd)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007168 dumpService(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007169 return;
7170 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7171 synchronized (this) {
7172 dumpServicesLocked(fd, pw, args, opti, true);
7173 }
7174 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007176 }
7177
7178 // No piece of data specified, dump everything.
7179 synchronized (this) {
7180 boolean needSep;
7181 if (dumpAll) {
7182 pw.println("Providers in Current Activity Manager State:");
7183 }
7184 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7185 if (needSep) {
7186 pw.println(" ");
7187 }
7188 if (dumpAll) {
7189 pw.println("-------------------------------------------------------------------------------");
7190 pw.println("Broadcasts in Current Activity Manager State:");
7191 }
7192 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7193 if (needSep) {
7194 pw.println(" ");
7195 }
7196 if (dumpAll) {
7197 pw.println("-------------------------------------------------------------------------------");
7198 pw.println("Services in Current Activity Manager State:");
7199 }
7200 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7201 if (needSep) {
7202 pw.println(" ");
7203 }
7204 if (dumpAll) {
7205 pw.println("-------------------------------------------------------------------------------");
7206 pw.println("PendingIntents in Current Activity Manager State:");
7207 }
7208 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7209 if (needSep) {
7210 pw.println(" ");
7211 }
7212 if (dumpAll) {
7213 pw.println("-------------------------------------------------------------------------------");
7214 pw.println("Activities in Current Activity Manager State:");
7215 }
7216 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7217 if (needSep) {
7218 pw.println(" ");
7219 }
7220 if (dumpAll) {
7221 pw.println("-------------------------------------------------------------------------------");
7222 pw.println("Processes in Current Activity Manager State:");
7223 }
7224 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7225 }
7226 }
7227
7228 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7229 int opti, boolean dumpAll, boolean needHeader) {
7230 if (needHeader) {
7231 pw.println(" Activity stack:");
7232 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007233 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007234 pw.println(" ");
7235 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007236 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7237 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007238 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007239 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007240 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007241 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007242 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007243 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007244 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007245 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007246 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007247 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007248 pw.println(" ");
7249 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007250 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
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 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007254 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7255 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007256 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007257 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007258
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007259 if (dumpAll && mRecentTasks.size() > 0) {
7260 pw.println(" ");
7261 pw.println("Recent tasks in Current Activity Manager State:");
7262
7263 final int N = mRecentTasks.size();
7264 for (int i=0; i<N; i++) {
7265 TaskRecord tr = mRecentTasks.get(i);
7266 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7267 pw.println(tr);
7268 mRecentTasks.get(i).dump(pw, " ");
7269 }
7270 }
7271
7272 pw.println(" ");
7273 pw.println(" mCurTask: " + mCurTask);
7274
7275 return true;
7276 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007277
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007278 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7279 int opti, boolean dumpAll) {
7280 boolean needSep = false;
7281 int numPers = 0;
7282
7283 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007284 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7285 final int NA = procs.size();
7286 for (int ia=0; ia<NA; ia++) {
7287 if (!needSep) {
7288 pw.println(" All known processes:");
7289 needSep = true;
7290 }
7291 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007292 pw.print(r.persistent ? " *PERS*" : " *APP*");
7293 pw.print(" UID "); pw.print(procs.keyAt(ia));
7294 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 r.dump(pw, " ");
7296 if (r.persistent) {
7297 numPers++;
7298 }
7299 }
7300 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007301 }
7302
7303 if (mLruProcesses.size() > 0) {
7304 if (needSep) pw.println(" ");
7305 needSep = true;
7306 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007307 dumpProcessOomList(pw, this, mLruProcesses, " ",
7308 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007309 needSep = true;
7310 }
7311
7312 synchronized (mPidsSelfLocked) {
7313 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314 if (needSep) pw.println(" ");
7315 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007316 pw.println(" PID mappings:");
7317 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7318 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7319 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 }
7321 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007322 }
7323
7324 if (mForegroundProcesses.size() > 0) {
7325 if (needSep) pw.println(" ");
7326 needSep = true;
7327 pw.println(" Foreground Processes:");
7328 for (int i=0; i<mForegroundProcesses.size(); i++) {
7329 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7330 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007331 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007332 }
7333
7334 if (mPersistentStartingProcesses.size() > 0) {
7335 if (needSep) pw.println(" ");
7336 needSep = true;
7337 pw.println(" Persisent processes that are starting:");
7338 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007339 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007342 if (mStartingProcesses.size() > 0) {
7343 if (needSep) pw.println(" ");
7344 needSep = true;
7345 pw.println(" Processes that are starting:");
7346 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007347 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007349
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007350 if (mRemovedProcesses.size() > 0) {
7351 if (needSep) pw.println(" ");
7352 needSep = true;
7353 pw.println(" Processes that are being removed:");
7354 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007355 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007356 }
7357
7358 if (mProcessesOnHold.size() > 0) {
7359 if (needSep) pw.println(" ");
7360 needSep = true;
7361 pw.println(" Processes that are on old until the system is ready:");
7362 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007363 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365
Dianne Hackborn287952c2010-09-22 22:34:31 -07007366 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007367
7368 if (mProcessCrashTimes.getMap().size() > 0) {
7369 if (needSep) pw.println(" ");
7370 needSep = true;
7371 pw.println(" Time since processes crashed:");
7372 long now = SystemClock.uptimeMillis();
7373 for (Map.Entry<String, SparseArray<Long>> procs
7374 : mProcessCrashTimes.getMap().entrySet()) {
7375 SparseArray<Long> uids = procs.getValue();
7376 final int N = uids.size();
7377 for (int i=0; i<N; i++) {
7378 pw.print(" Process "); pw.print(procs.getKey());
7379 pw.print(" uid "); pw.print(uids.keyAt(i));
7380 pw.print(": last crashed ");
7381 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007382 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007383 }
7384 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007387 if (mBadProcesses.getMap().size() > 0) {
7388 if (needSep) pw.println(" ");
7389 needSep = true;
7390 pw.println(" Bad processes:");
7391 for (Map.Entry<String, SparseArray<Long>> procs
7392 : mBadProcesses.getMap().entrySet()) {
7393 SparseArray<Long> uids = procs.getValue();
7394 final int N = uids.size();
7395 for (int i=0; i<N; i++) {
7396 pw.print(" Bad process "); pw.print(procs.getKey());
7397 pw.print(" uid "); pw.print(uids.keyAt(i));
7398 pw.print(": crashed at time ");
7399 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400 }
7401 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007404 pw.println(" ");
7405 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007406 if (mHeavyWeightProcess != null) {
7407 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7408 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007409 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007410 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007411 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7412 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7413 || mOrigWaitForDebugger) {
7414 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7415 + " mDebugTransient=" + mDebugTransient
7416 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7417 }
7418 if (mAlwaysFinishActivities || mController != null) {
7419 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7420 + " mController=" + mController);
7421 }
7422 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007425 + " mProcessesReady=" + mProcessesReady
7426 + " mSystemReady=" + mSystemReady);
7427 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007428 + " mBooted=" + mBooted
7429 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007430 pw.print(" mLastPowerCheckRealtime=");
7431 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7432 pw.println("");
7433 pw.print(" mLastPowerCheckUptime=");
7434 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7435 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007436 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7437 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007438 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007439 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007440
7441 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442 }
7443
Dianne Hackborn287952c2010-09-22 22:34:31 -07007444 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7445 int opti, boolean needSep, boolean dumpAll) {
7446 if (mProcessesToGc.size() > 0) {
7447 if (needSep) pw.println(" ");
7448 needSep = true;
7449 pw.println(" Processes that are waiting to GC:");
7450 long now = SystemClock.uptimeMillis();
7451 for (int i=0; i<mProcessesToGc.size(); i++) {
7452 ProcessRecord proc = mProcessesToGc.get(i);
7453 pw.print(" Process "); pw.println(proc);
7454 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7455 pw.print(", last gced=");
7456 pw.print(now-proc.lastRequestedGc);
7457 pw.print(" ms ago, last lowMem=");
7458 pw.print(now-proc.lastLowMemory);
7459 pw.println(" ms ago");
7460
7461 }
7462 }
7463 return needSep;
7464 }
7465
7466 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7467 int opti, boolean dumpAll) {
7468 boolean needSep = false;
7469
7470 if (mLruProcesses.size() > 0) {
7471 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7472
7473 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7474 @Override
7475 public int compare(ProcessRecord object1, ProcessRecord object2) {
7476 if (object1.setAdj != object2.setAdj) {
7477 return object1.setAdj > object2.setAdj ? -1 : 1;
7478 }
7479 if (object1.setSchedGroup != object2.setSchedGroup) {
7480 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7481 }
7482 if (object1.keeping != object2.keeping) {
7483 return object1.keeping ? -1 : 1;
7484 }
7485 if (object1.pid != object2.pid) {
7486 return object1.pid > object2.pid ? -1 : 1;
7487 }
7488 return 0;
7489 }
7490 };
7491
7492 Collections.sort(procs, comparator);
7493
7494 if (needSep) pw.println(" ");
7495 needSep = true;
7496 pw.println(" Process OOM control:");
7497 dumpProcessOomList(pw, this, procs, " ",
7498 "Proc", "PERS", true);
7499 needSep = true;
7500 }
7501
7502 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7503
7504 pw.println(" ");
7505 pw.println(" mHomeProcess: " + mHomeProcess);
7506 if (mHeavyWeightProcess != null) {
7507 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7508 }
7509
7510 return true;
7511 }
7512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007513 /**
7514 * There are three ways to call this:
7515 * - no service specified: dump all the services
7516 * - a flattened component name that matched an existing service was specified as the
7517 * first arg: dump that one service
7518 * - the first arg isn't the flattened component name of an existing service:
7519 * dump all services whose component contains the first arg as a substring
7520 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007521 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
7522 int opti, boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 String[] newArgs;
7524 String componentNameString;
7525 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007526 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007527 componentNameString = null;
7528 newArgs = EMPTY_STRING_ARRAY;
7529 r = null;
7530 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007531 componentNameString = args[opti];
7532 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007533 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007534 synchronized (this) {
7535 r = componentName != null ? mServices.get(componentName) : null;
7536 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007537 newArgs = new String[args.length - opti];
7538 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007539 }
7540
7541 if (r != null) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007542 dumpService(fd, pw, r, newArgs, dumpAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007543 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007544 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7545 synchronized (this) {
7546 for (ServiceRecord r1 : mServices.values()) {
7547 if (componentNameString == null
7548 || r1.name.flattenToString().contains(componentNameString)) {
7549 services.add(r1);
7550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 }
7552 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007553 for (int i=0; i<services.size(); i++) {
7554 dumpService(fd, pw, services.get(i), newArgs, dumpAll);
7555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007556 }
7557 }
7558
7559 /**
7560 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7561 * there is a thread associated with the service.
7562 */
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007563 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
7564 boolean dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 pw.println(" Service " + r.name.flattenToString());
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007566 if (dumpAll) {
7567 synchronized (this) {
7568 pw.print(" * "); pw.println(r);
7569 r.dump(pw, " ");
7570 }
7571 pw.println("");
7572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 if (r.app != null && r.app.thread != null) {
7574 try {
7575 // flush anything that is already in the PrintWriter since the thread is going
7576 // to write to the file descriptor directly
7577 pw.flush();
7578 r.app.thread.dumpService(fd, r, args);
7579 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007580 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 } catch (RemoteException e) {
7582 pw.println("got a RemoteException while dumping the service");
7583 }
7584 }
7585 }
7586
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007587 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7588 int opti, boolean dumpAll) {
7589 boolean needSep = false;
7590
7591 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592 if (mRegisteredReceivers.size() > 0) {
7593 pw.println(" ");
7594 pw.println(" Registered Receivers:");
7595 Iterator it = mRegisteredReceivers.values().iterator();
7596 while (it.hasNext()) {
7597 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007598 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 r.dump(pw, " ");
7600 }
7601 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 pw.println(" ");
7604 pw.println("Receiver Resolver Table:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007605 mReceiverResolver.dump(pw, null, " ", null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007606 needSep = true;
7607 }
7608
7609 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
7610 || mPendingBroadcast != null) {
7611 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007612 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007613 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007615 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
7616 pw.println(" Broadcast #" + i + ":");
7617 mParallelBroadcasts.get(i).dump(pw, " ");
7618 }
7619 if (mOrderedBroadcasts.size() > 0) {
7620 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007621 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007622 }
7623 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
7624 pw.println(" Serialized Broadcast #" + i + ":");
7625 mOrderedBroadcasts.get(i).dump(pw, " ");
7626 }
7627 pw.println(" ");
7628 pw.println(" Pending broadcast:");
7629 if (mPendingBroadcast != null) {
7630 mPendingBroadcast.dump(pw, " ");
7631 } else {
7632 pw.println(" (null)");
7633 }
7634 needSep = true;
7635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007637 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007638 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08007639 pw.println(" Historical broadcasts:");
7640 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
7641 BroadcastRecord r = mBroadcastHistory[i];
7642 if (r == null) {
7643 break;
7644 }
7645 pw.println(" Historical Broadcast #" + i + ":");
7646 r.dump(pw, " ");
7647 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007648 needSep = true;
7649 }
7650
7651 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08007652 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007653 pw.println(" Sticky broadcasts:");
7654 StringBuilder sb = new StringBuilder(128);
7655 for (Map.Entry<String, ArrayList<Intent>> ent
7656 : mStickyBroadcasts.entrySet()) {
7657 pw.print(" * Sticky action "); pw.print(ent.getKey());
7658 pw.println(":");
7659 ArrayList<Intent> intents = ent.getValue();
7660 final int N = intents.size();
7661 for (int i=0; i<N; i++) {
7662 sb.setLength(0);
7663 sb.append(" Intent: ");
7664 intents.get(i).toShortString(sb, true, false);
7665 pw.println(sb.toString());
7666 Bundle bundle = intents.get(i).getExtras();
7667 if (bundle != null) {
7668 pw.print(" ");
7669 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007670 }
7671 }
7672 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007673 needSep = true;
7674 }
7675
7676 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007678 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007679 pw.println(" mHandler:");
7680 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007681 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007683
7684 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007685 }
7686
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007687 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7688 int opti, boolean dumpAll) {
7689 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007691 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692 if (mServices.size() > 0) {
7693 pw.println(" Active services:");
7694 Iterator<ServiceRecord> it = mServices.values().iterator();
7695 while (it.hasNext()) {
7696 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007697 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 r.dump(pw, " ");
7699 }
7700 needSep = true;
7701 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007704 if (mPendingServices.size() > 0) {
7705 if (needSep) pw.println(" ");
7706 pw.println(" Pending services:");
7707 for (int i=0; i<mPendingServices.size(); i++) {
7708 ServiceRecord r = mPendingServices.get(i);
7709 pw.print(" * Pending "); pw.println(r);
7710 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007712 needSep = true;
7713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007715 if (mRestartingServices.size() > 0) {
7716 if (needSep) pw.println(" ");
7717 pw.println(" Restarting services:");
7718 for (int i=0; i<mRestartingServices.size(); i++) {
7719 ServiceRecord r = mRestartingServices.get(i);
7720 pw.print(" * Restarting "); pw.println(r);
7721 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007723 needSep = true;
7724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007726 if (mStoppingServices.size() > 0) {
7727 if (needSep) pw.println(" ");
7728 pw.println(" Stopping services:");
7729 for (int i=0; i<mStoppingServices.size(); i++) {
7730 ServiceRecord r = mStoppingServices.get(i);
7731 pw.print(" * Stopping "); pw.println(r);
7732 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007734 needSep = true;
7735 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007736
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007737 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007738 if (mServiceConnections.size() > 0) {
7739 if (needSep) pw.println(" ");
7740 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007741 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 = mServiceConnections.values().iterator();
7743 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07007744 ArrayList<ConnectionRecord> r = it.next();
7745 for (int i=0; i<r.size(); i++) {
7746 pw.print(" * "); pw.println(r.get(i));
7747 r.get(i).dump(pw, " ");
7748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007749 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007750 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 }
7752 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753
7754 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755 }
7756
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007757 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7758 int opti, boolean dumpAll) {
7759 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007760
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007761 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762 if (mProvidersByClass.size() > 0) {
7763 if (needSep) pw.println(" ");
7764 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007765 Iterator<Map.Entry<String, ContentProviderRecord>> it
7766 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007767 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007768 Map.Entry<String, ContentProviderRecord> e = it.next();
7769 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007770 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 r.dump(pw, " ");
7772 }
7773 needSep = true;
7774 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007775
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007776 if (mProvidersByName.size() > 0) {
7777 pw.println(" ");
7778 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07007779 Iterator<Map.Entry<String, ContentProviderRecord>> it
7780 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007781 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007782 Map.Entry<String, ContentProviderRecord> e = it.next();
7783 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007784 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
7785 pw.println(r);
7786 }
7787 needSep = true;
7788 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007789 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007790
7791 if (mLaunchingProviders.size() > 0) {
7792 if (needSep) pw.println(" ");
7793 pw.println(" Launching content providers:");
7794 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
7795 pw.print(" Launching #"); pw.print(i); pw.print(": ");
7796 pw.println(mLaunchingProviders.get(i));
7797 }
7798 needSep = true;
7799 }
7800
7801 if (mGrantedUriPermissions.size() > 0) {
7802 pw.println();
7803 pw.println("Granted Uri Permissions:");
7804 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
7805 int uid = mGrantedUriPermissions.keyAt(i);
7806 HashMap<Uri, UriPermission> perms
7807 = mGrantedUriPermissions.valueAt(i);
7808 pw.print(" * UID "); pw.print(uid);
7809 pw.println(" holds:");
7810 for (UriPermission perm : perms.values()) {
7811 pw.print(" "); pw.println(perm);
7812 perm.dump(pw, " ");
7813 }
7814 }
7815 needSep = true;
7816 }
7817
7818 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007819 }
7820
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007821 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7822 int opti, boolean dumpAll) {
7823 boolean needSep = false;
7824
7825 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007826 if (this.mIntentSenderRecords.size() > 0) {
7827 Iterator<WeakReference<PendingIntentRecord>> it
7828 = mIntentSenderRecords.values().iterator();
7829 while (it.hasNext()) {
7830 WeakReference<PendingIntentRecord> ref = it.next();
7831 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007832 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007834 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 rec.dump(pw, " ");
7836 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007837 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 }
7839 }
7840 }
7841 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007842
7843 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007844 }
7845
7846 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007847 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007848 TaskRecord lastTask = null;
7849 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007850 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007851 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007852 if (lastTask != r.task) {
7853 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007854 pw.print(prefix);
7855 pw.print(full ? "* " : " ");
7856 pw.println(lastTask);
7857 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007858 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007860 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007861 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
7862 pw.print(" #"); pw.print(i); pw.print(": ");
7863 pw.println(r);
7864 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007865 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07007866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 }
7868 }
7869
Dianne Hackborn09c916b2009-12-08 14:50:51 -08007870 private static String buildOomTag(String prefix, String space, int val, int base) {
7871 if (val == base) {
7872 if (space == null) return prefix;
7873 return prefix + " ";
7874 }
7875 return prefix + "+" + Integer.toString(val-base);
7876 }
7877
7878 private static final int dumpProcessList(PrintWriter pw,
7879 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07007880 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007882 final int N = list.size()-1;
7883 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007885 pw.println(String.format("%s%s #%2d: %s",
7886 prefix, (r.persistent ? persistentLabel : normalLabel),
7887 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007888 if (r.persistent) {
7889 numPers++;
7890 }
7891 }
7892 return numPers;
7893 }
7894
Dianne Hackborn287952c2010-09-22 22:34:31 -07007895 private static final void dumpProcessOomList(PrintWriter pw,
7896 ActivityManagerService service, List<ProcessRecord> list,
7897 String prefix, String normalLabel, String persistentLabel,
7898 boolean inclDetails) {
7899
7900 final long curRealtime = SystemClock.elapsedRealtime();
7901 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
7902 final long curUptime = SystemClock.uptimeMillis();
7903 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
7904
7905 final int N = list.size()-1;
7906 for (int i=N; i>=0; i--) {
7907 ProcessRecord r = list.get(i);
7908 String oomAdj;
7909 if (r.setAdj >= EMPTY_APP_ADJ) {
7910 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
7911 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
7912 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
7913 } else if (r.setAdj >= HOME_APP_ADJ) {
7914 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
7915 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
7916 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
7917 } else if (r.setAdj >= BACKUP_APP_ADJ) {
7918 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
7919 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
7920 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
7921 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
7922 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
7923 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
7924 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
7925 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
7926 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
7927 } else if (r.setAdj >= CORE_SERVER_ADJ) {
7928 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
7929 } else if (r.setAdj >= SYSTEM_ADJ) {
7930 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
7931 } else {
7932 oomAdj = Integer.toString(r.setAdj);
7933 }
7934 String schedGroup;
7935 switch (r.setSchedGroup) {
7936 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
7937 schedGroup = "B";
7938 break;
7939 case Process.THREAD_GROUP_DEFAULT:
7940 schedGroup = "F";
7941 break;
7942 default:
7943 schedGroup = Integer.toString(r.setSchedGroup);
7944 break;
7945 }
7946 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
7947 prefix, (r.persistent ? persistentLabel : normalLabel),
7948 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
7949 if (r.adjSource != null || r.adjTarget != null) {
7950 pw.print(prefix);
7951 pw.print(" ");
7952 if (r.adjTarget instanceof ComponentName) {
7953 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
7954 } else if (r.adjTarget != null) {
7955 pw.print(r.adjTarget.toString());
7956 } else {
7957 pw.print("{null}");
7958 }
7959 pw.print("<=");
7960 if (r.adjSource instanceof ProcessRecord) {
7961 pw.print("Proc{");
7962 pw.print(((ProcessRecord)r.adjSource).toShortString());
7963 pw.println("}");
7964 } else if (r.adjSource != null) {
7965 pw.println(r.adjSource.toString());
7966 } else {
7967 pw.println("{null}");
7968 }
7969 }
7970 if (inclDetails) {
7971 pw.print(prefix);
7972 pw.print(" ");
7973 pw.print("oom: max="); pw.print(r.maxAdj);
7974 pw.print(" hidden="); pw.print(r.hiddenAdj);
7975 pw.print(" curRaw="); pw.print(r.curRawAdj);
7976 pw.print(" setRaw="); pw.print(r.setRawAdj);
7977 pw.print(" cur="); pw.print(r.curAdj);
7978 pw.print(" set="); pw.println(r.setAdj);
7979 pw.print(prefix);
7980 pw.print(" ");
7981 pw.print("keeping="); pw.print(r.keeping);
7982 pw.print(" hidden="); pw.print(r.hidden);
7983 pw.print(" empty="); pw.println(r.empty);
7984
7985 if (!r.keeping) {
7986 if (r.lastWakeTime != 0) {
7987 long wtime;
7988 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
7989 synchronized (stats) {
7990 wtime = stats.getProcessWakeTime(r.info.uid,
7991 r.pid, curRealtime);
7992 }
7993 long timeUsed = wtime - r.lastWakeTime;
7994 pw.print(prefix);
7995 pw.print(" ");
7996 pw.print("keep awake over ");
7997 TimeUtils.formatDuration(realtimeSince, pw);
7998 pw.print(" used ");
7999 TimeUtils.formatDuration(timeUsed, pw);
8000 pw.print(" (");
8001 pw.print((timeUsed*100)/realtimeSince);
8002 pw.println("%)");
8003 }
8004 if (r.lastCpuTime != 0) {
8005 long timeUsed = r.curCpuTime - r.lastCpuTime;
8006 pw.print(prefix);
8007 pw.print(" ");
8008 pw.print("run cpu over ");
8009 TimeUtils.formatDuration(uptimeSince, pw);
8010 pw.print(" used ");
8011 TimeUtils.formatDuration(timeUsed, pw);
8012 pw.print(" (");
8013 pw.print((timeUsed*100)/uptimeSince);
8014 pw.println("%)");
8015 }
8016 }
8017 }
8018 }
8019 }
8020
Dianne Hackborn472ad872010-04-07 17:31:48 -07008021 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008023 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 long uptime = SystemClock.uptimeMillis();
8025 long realtime = SystemClock.elapsedRealtime();
8026
8027 if (isCheckinRequest) {
8028 // short checkin version
8029 pw.println(uptime + "," + realtime);
8030 pw.flush();
8031 } else {
8032 pw.println("Applications Memory Usage (kB):");
8033 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8034 }
8035 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8036 ProcessRecord r = (ProcessRecord)list.get(i);
8037 if (r.thread != null) {
8038 if (!isCheckinRequest) {
8039 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8040 pw.flush();
8041 }
8042 try {
8043 r.thread.asBinder().dump(fd, args);
8044 } catch (RemoteException e) {
8045 if (!isCheckinRequest) {
8046 pw.println("Got RemoteException!");
8047 pw.flush();
8048 }
8049 }
8050 }
8051 }
8052 }
8053
8054 /**
8055 * Searches array of arguments for the specified string
8056 * @param args array of argument strings
8057 * @param value value to search for
8058 * @return true if the value is contained in the array
8059 */
8060 private static boolean scanArgs(String[] args, String value) {
8061 if (args != null) {
8062 for (String arg : args) {
8063 if (value.equals(arg)) {
8064 return true;
8065 }
8066 }
8067 }
8068 return false;
8069 }
8070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008071 private final void killServicesLocked(ProcessRecord app,
8072 boolean allowRestart) {
8073 // Report disconnected services.
8074 if (false) {
8075 // XXX we are letting the client link to the service for
8076 // death notifications.
8077 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008078 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008079 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008080 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008082 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008083 = r.connections.values().iterator();
8084 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008085 ArrayList<ConnectionRecord> cl = jt.next();
8086 for (int i=0; i<cl.size(); i++) {
8087 ConnectionRecord c = cl.get(i);
8088 if (c.binding.client != app) {
8089 try {
8090 //c.conn.connected(r.className, null);
8091 } catch (Exception e) {
8092 // todo: this should be asynchronous!
8093 Slog.w(TAG, "Exception thrown disconnected servce "
8094 + r.shortName
8095 + " from app " + app.processName, e);
8096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008097 }
8098 }
8099 }
8100 }
8101 }
8102 }
8103 }
8104
8105 // Clean up any connections this application has to other services.
8106 if (app.connections.size() > 0) {
8107 Iterator<ConnectionRecord> it = app.connections.iterator();
8108 while (it.hasNext()) {
8109 ConnectionRecord r = it.next();
8110 removeConnectionLocked(r, app, null);
8111 }
8112 }
8113 app.connections.clear();
8114
8115 if (app.services.size() != 0) {
8116 // Any services running in the application need to be placed
8117 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008118 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008120 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 synchronized (sr.stats.getBatteryStats()) {
8122 sr.stats.stopLaunchedLocked();
8123 }
8124 sr.app = null;
8125 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008126 if (mStoppingServices.remove(sr)) {
8127 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8128 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008129
8130 boolean hasClients = sr.bindings.size() > 0;
8131 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008132 Iterator<IntentBindRecord> bindings
8133 = sr.bindings.values().iterator();
8134 while (bindings.hasNext()) {
8135 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008136 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 + ": shouldUnbind=" + b.hasBound);
8138 b.binder = null;
8139 b.requested = b.received = b.hasBound = false;
8140 }
8141 }
8142
8143 if (sr.crashCount >= 2) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008144 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008146 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008147 sr.crashCount, sr.shortName, app.pid);
8148 bringDownServiceLocked(sr, true);
8149 } else if (!allowRestart) {
8150 bringDownServiceLocked(sr, true);
8151 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008152 boolean canceled = scheduleServiceRestartLocked(sr, true);
8153
8154 // Should the service remain running? Note that in the
8155 // extreme case of so many attempts to deliver a command
8156 // that it failed, that we also will stop it here.
8157 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8158 if (sr.pendingStarts.size() == 0) {
8159 sr.startRequested = false;
8160 if (!hasClients) {
8161 // Whoops, no reason to restart!
8162 bringDownServiceLocked(sr, true);
8163 }
8164 }
8165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008166 }
8167 }
8168
8169 if (!allowRestart) {
8170 app.services.clear();
8171 }
8172 }
8173
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008174 // Make sure we have no more records on the stopping list.
8175 int i = mStoppingServices.size();
8176 while (i > 0) {
8177 i--;
8178 ServiceRecord sr = mStoppingServices.get(i);
8179 if (sr.app == app) {
8180 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008181 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008182 }
8183 }
8184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 app.executingServices.clear();
8186 }
8187
8188 private final void removeDyingProviderLocked(ProcessRecord proc,
8189 ContentProviderRecord cpr) {
8190 synchronized (cpr) {
8191 cpr.launchingApp = null;
8192 cpr.notifyAll();
8193 }
8194
8195 mProvidersByClass.remove(cpr.info.name);
8196 String names[] = cpr.info.authority.split(";");
8197 for (int j = 0; j < names.length; j++) {
8198 mProvidersByName.remove(names[j]);
8199 }
8200
8201 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8202 while (cit.hasNext()) {
8203 ProcessRecord capp = cit.next();
8204 if (!capp.persistent && capp.thread != null
8205 && capp.pid != 0
8206 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008207 Slog.i(TAG, "Kill " + capp.processName
8208 + " (pid " + capp.pid + "): provider " + cpr.info.name
8209 + " in dying process " + proc.processName);
8210 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8211 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008212 Process.killProcess(capp.pid);
8213 }
8214 }
8215
8216 mLaunchingProviders.remove(cpr);
8217 }
8218
8219 /**
8220 * Main code for cleaning up a process when it has gone away. This is
8221 * called both as a result of the process dying, or directly when stopping
8222 * a process when running in single process mode.
8223 */
8224 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8225 boolean restarting, int index) {
8226 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008227 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008228 }
8229
Dianne Hackborn36124872009-10-08 16:22:03 -07008230 mProcessesToGc.remove(app);
8231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008232 // Dismiss any open dialogs.
8233 if (app.crashDialog != null) {
8234 app.crashDialog.dismiss();
8235 app.crashDialog = null;
8236 }
8237 if (app.anrDialog != null) {
8238 app.anrDialog.dismiss();
8239 app.anrDialog = null;
8240 }
8241 if (app.waitDialog != null) {
8242 app.waitDialog.dismiss();
8243 app.waitDialog = null;
8244 }
8245
8246 app.crashing = false;
8247 app.notResponding = false;
8248
8249 app.resetPackageList();
8250 app.thread = null;
8251 app.forcingToForeground = null;
8252 app.foregroundServices = false;
8253
8254 killServicesLocked(app, true);
8255
8256 boolean restart = false;
8257
8258 int NL = mLaunchingProviders.size();
8259
8260 // Remove published content providers.
8261 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008262 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008263 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008264 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008265 cpr.provider = null;
8266 cpr.app = null;
8267
8268 // See if someone is waiting for this provider... in which
8269 // case we don't remove it, but just let it restart.
8270 int i = 0;
8271 if (!app.bad) {
8272 for (; i<NL; i++) {
8273 if (mLaunchingProviders.get(i) == cpr) {
8274 restart = true;
8275 break;
8276 }
8277 }
8278 } else {
8279 i = NL;
8280 }
8281
8282 if (i >= NL) {
8283 removeDyingProviderLocked(app, cpr);
8284 NL = mLaunchingProviders.size();
8285 }
8286 }
8287 app.pubProviders.clear();
8288 }
8289
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008290 // Take care of any launching providers waiting for this process.
8291 if (checkAppInLaunchingProvidersLocked(app, false)) {
8292 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008293 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 // Unregister from connected content providers.
8296 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008297 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008298 while (it.hasNext()) {
8299 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8300 cpr.clients.remove(app);
8301 }
8302 app.conProviders.clear();
8303 }
8304
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008305 // At this point there may be remaining entries in mLaunchingProviders
8306 // where we were the only one waiting, so they are no longer of use.
8307 // Look for these and clean up if found.
8308 // XXX Commented out for now. Trying to figure out a way to reproduce
8309 // the actual situation to identify what is actually going on.
8310 if (false) {
8311 for (int i=0; i<NL; i++) {
8312 ContentProviderRecord cpr = (ContentProviderRecord)
8313 mLaunchingProviders.get(i);
8314 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8315 synchronized (cpr) {
8316 cpr.launchingApp = null;
8317 cpr.notifyAll();
8318 }
8319 }
8320 }
8321 }
8322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008323 skipCurrentReceiverLocked(app);
8324
8325 // Unregister any receivers.
8326 if (app.receivers.size() > 0) {
8327 Iterator<ReceiverList> it = app.receivers.iterator();
8328 while (it.hasNext()) {
8329 removeReceiverLocked(it.next());
8330 }
8331 app.receivers.clear();
8332 }
8333
Christopher Tate181fafa2009-05-14 11:12:14 -07008334 // If the app is undergoing backup, tell the backup manager about it
8335 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008336 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008337 try {
8338 IBackupManager bm = IBackupManager.Stub.asInterface(
8339 ServiceManager.getService(Context.BACKUP_SERVICE));
8340 bm.agentDisconnected(app.info.packageName);
8341 } catch (RemoteException e) {
8342 // can't happen; backup manager is local
8343 }
8344 }
8345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 // If the caller is restarting this app, then leave it in its
8347 // current lists and let the caller take care of it.
8348 if (restarting) {
8349 return;
8350 }
8351
8352 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008353 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008354 "Removing non-persistent process during cleanup: " + app);
8355 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008356 if (mHeavyWeightProcess == app) {
8357 mHeavyWeightProcess = null;
8358 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008360 } else if (!app.removed) {
8361 // This app is persistent, so we need to keep its record around.
8362 // If it is not already on the pending app list, add it there
8363 // and start a new process for it.
8364 app.thread = null;
8365 app.forcingToForeground = null;
8366 app.foregroundServices = false;
8367 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8368 mPersistentStartingProcesses.add(app);
8369 restart = true;
8370 }
8371 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008372 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8373 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008374 mProcessesOnHold.remove(app);
8375
The Android Open Source Project4df24232009-03-05 14:34:35 -08008376 if (app == mHomeProcess) {
8377 mHomeProcess = null;
8378 }
8379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008380 if (restart) {
8381 // We have components that still need to be running in the
8382 // process, so re-launch it.
8383 mProcessNames.put(app.processName, app.info.uid, app);
8384 startProcessLocked(app, "restart", app.processName);
8385 } else if (app.pid > 0 && app.pid != MY_PID) {
8386 // Goodbye!
8387 synchronized (mPidsSelfLocked) {
8388 mPidsSelfLocked.remove(app.pid);
8389 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8390 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008391 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008392 }
8393 }
8394
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008395 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8396 // Look through the content providers we are waiting to have launched,
8397 // and if any run in this process then either schedule a restart of
8398 // the process or kill the client waiting for it if this process has
8399 // gone bad.
8400 int NL = mLaunchingProviders.size();
8401 boolean restart = false;
8402 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008403 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008404 if (cpr.launchingApp == app) {
8405 if (!alwaysBad && !app.bad) {
8406 restart = true;
8407 } else {
8408 removeDyingProviderLocked(app, cpr);
8409 NL = mLaunchingProviders.size();
8410 }
8411 }
8412 }
8413 return restart;
8414 }
8415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008416 // =========================================================
8417 // SERVICES
8418 // =========================================================
8419
8420 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8421 ActivityManager.RunningServiceInfo info =
8422 new ActivityManager.RunningServiceInfo();
8423 info.service = r.name;
8424 if (r.app != null) {
8425 info.pid = r.app.pid;
8426 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008427 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 info.process = r.processName;
8429 info.foreground = r.isForeground;
8430 info.activeSince = r.createTime;
8431 info.started = r.startRequested;
8432 info.clientCount = r.connections.size();
8433 info.crashCount = r.crashCount;
8434 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008435 if (r.isForeground) {
8436 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8437 }
8438 if (r.startRequested) {
8439 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8440 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008441 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008442 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8443 }
8444 if (r.app != null && r.app.persistent) {
8445 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8446 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008447
8448 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8449 for (int i=0; i<connl.size(); i++) {
8450 ConnectionRecord conn = connl.get(i);
8451 if (conn.clientLabel != 0) {
8452 info.clientPackage = conn.binding.client.info.packageName;
8453 info.clientLabel = conn.clientLabel;
8454 return info;
8455 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008456 }
8457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008458 return info;
8459 }
8460
8461 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8462 int flags) {
8463 synchronized (this) {
8464 ArrayList<ActivityManager.RunningServiceInfo> res
8465 = new ArrayList<ActivityManager.RunningServiceInfo>();
8466
8467 if (mServices.size() > 0) {
8468 Iterator<ServiceRecord> it = mServices.values().iterator();
8469 while (it.hasNext() && res.size() < maxNum) {
8470 res.add(makeRunningServiceInfoLocked(it.next()));
8471 }
8472 }
8473
8474 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8475 ServiceRecord r = mRestartingServices.get(i);
8476 ActivityManager.RunningServiceInfo info =
8477 makeRunningServiceInfoLocked(r);
8478 info.restarting = r.nextRestartTime;
8479 res.add(info);
8480 }
8481
8482 return res;
8483 }
8484 }
8485
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008486 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8487 synchronized (this) {
8488 ServiceRecord r = mServices.get(name);
8489 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008490 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8491 for (int i=0; i<conn.size(); i++) {
8492 if (conn.get(i).clientIntent != null) {
8493 return conn.get(i).clientIntent;
8494 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008495 }
8496 }
8497 }
8498 }
8499 return null;
8500 }
8501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 private final ServiceRecord findServiceLocked(ComponentName name,
8503 IBinder token) {
8504 ServiceRecord r = mServices.get(name);
8505 return r == token ? r : null;
8506 }
8507
8508 private final class ServiceLookupResult {
8509 final ServiceRecord record;
8510 final String permission;
8511
8512 ServiceLookupResult(ServiceRecord _record, String _permission) {
8513 record = _record;
8514 permission = _permission;
8515 }
8516 };
8517
8518 private ServiceLookupResult findServiceLocked(Intent service,
8519 String resolvedType) {
8520 ServiceRecord r = null;
8521 if (service.getComponent() != null) {
8522 r = mServices.get(service.getComponent());
8523 }
8524 if (r == null) {
8525 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8526 r = mServicesByIntent.get(filter);
8527 }
8528
8529 if (r == null) {
8530 try {
8531 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008532 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008533 service, resolvedType, 0);
8534 ServiceInfo sInfo =
8535 rInfo != null ? rInfo.serviceInfo : null;
8536 if (sInfo == null) {
8537 return null;
8538 }
8539
8540 ComponentName name = new ComponentName(
8541 sInfo.applicationInfo.packageName, sInfo.name);
8542 r = mServices.get(name);
8543 } catch (RemoteException ex) {
8544 // pm is in same process, this will never happen.
8545 }
8546 }
8547 if (r != null) {
8548 int callingPid = Binder.getCallingPid();
8549 int callingUid = Binder.getCallingUid();
8550 if (checkComponentPermission(r.permission,
8551 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8552 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008553 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008554 + " from pid=" + callingPid
8555 + ", uid=" + callingUid
8556 + " requires " + r.permission);
8557 return new ServiceLookupResult(null, r.permission);
8558 }
8559 return new ServiceLookupResult(r, null);
8560 }
8561 return null;
8562 }
8563
8564 private class ServiceRestarter implements Runnable {
8565 private ServiceRecord mService;
8566
8567 void setService(ServiceRecord service) {
8568 mService = service;
8569 }
8570
8571 public void run() {
8572 synchronized(ActivityManagerService.this) {
8573 performServiceRestartLocked(mService);
8574 }
8575 }
8576 }
8577
8578 private ServiceLookupResult retrieveServiceLocked(Intent service,
8579 String resolvedType, int callingPid, int callingUid) {
8580 ServiceRecord r = null;
8581 if (service.getComponent() != null) {
8582 r = mServices.get(service.getComponent());
8583 }
8584 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8585 r = mServicesByIntent.get(filter);
8586 if (r == null) {
8587 try {
8588 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008589 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07008590 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008591 ServiceInfo sInfo =
8592 rInfo != null ? rInfo.serviceInfo : null;
8593 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008594 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008595 ": not found");
8596 return null;
8597 }
8598
8599 ComponentName name = new ComponentName(
8600 sInfo.applicationInfo.packageName, sInfo.name);
8601 r = mServices.get(name);
8602 if (r == null) {
8603 filter = new Intent.FilterComparison(service.cloneFilter());
8604 ServiceRestarter res = new ServiceRestarter();
8605 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
8606 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
8607 synchronized (stats) {
8608 ss = stats.getServiceStatsLocked(
8609 sInfo.applicationInfo.uid, sInfo.packageName,
8610 sInfo.name);
8611 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08008612 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 res.setService(r);
8614 mServices.put(name, r);
8615 mServicesByIntent.put(filter, r);
8616
8617 // Make sure this component isn't in the pending list.
8618 int N = mPendingServices.size();
8619 for (int i=0; i<N; i++) {
8620 ServiceRecord pr = mPendingServices.get(i);
8621 if (pr.name.equals(name)) {
8622 mPendingServices.remove(i);
8623 i--;
8624 N--;
8625 }
8626 }
8627 }
8628 } catch (RemoteException ex) {
8629 // pm is in same process, this will never happen.
8630 }
8631 }
8632 if (r != null) {
8633 if (checkComponentPermission(r.permission,
8634 callingPid, callingUid, r.exported ? -1 : r.appInfo.uid)
8635 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008636 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637 + " from pid=" + Binder.getCallingPid()
8638 + ", uid=" + Binder.getCallingUid()
8639 + " requires " + r.permission);
8640 return new ServiceLookupResult(null, r.permission);
8641 }
8642 return new ServiceLookupResult(r, null);
8643 }
8644 return null;
8645 }
8646
Dianne Hackborn287952c2010-09-22 22:34:31 -07008647 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
8648 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
8649 + why + " of " + r + " in app " + r.app);
8650 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
8651 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 long now = SystemClock.uptimeMillis();
8653 if (r.executeNesting == 0 && r.app != null) {
8654 if (r.app.executingServices.size() == 0) {
8655 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
8656 msg.obj = r.app;
8657 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
8658 }
8659 r.app.executingServices.add(r);
8660 }
8661 r.executeNesting++;
8662 r.executingStart = now;
8663 }
8664
8665 private final void sendServiceArgsLocked(ServiceRecord r,
8666 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008667 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008668 if (N == 0) {
8669 return;
8670 }
8671
Dianne Hackborn39792d22010-08-19 18:01:52 -07008672 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008673 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07008674 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008675 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
8676 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008677 if (si.intent == null) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008678 // If somehow we got a dummy start at the front, then
8679 // just drop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008680 continue;
8681 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008682 si.deliveredTime = SystemClock.uptimeMillis();
8683 r.deliveredStarts.add(si);
8684 si.deliveryCount++;
8685 if (si.targetPermissionUid >= 0) {
8686 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07008687 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07008688 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008689 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008690 if (!oomAdjusted) {
8691 oomAdjusted = true;
8692 updateOomAdjLocked(r.app);
8693 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008694 int flags = 0;
8695 if (si.deliveryCount > 0) {
8696 flags |= Service.START_FLAG_RETRY;
8697 }
8698 if (si.doneExecutingCount > 0) {
8699 flags |= Service.START_FLAG_REDELIVERY;
8700 }
8701 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008702 } catch (RemoteException e) {
8703 // Remote process gone... we'll let the normal cleanup take
8704 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008705 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008706 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008707 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008708 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008709 break;
8710 }
8711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008712 }
8713
8714 private final boolean requestServiceBindingLocked(ServiceRecord r,
8715 IntentBindRecord i, boolean rebind) {
8716 if (r.app == null || r.app.thread == null) {
8717 // If service is not currently running, can't yet bind.
8718 return false;
8719 }
8720 if ((!i.requested || rebind) && i.apps.size() > 0) {
8721 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008722 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
8724 if (!rebind) {
8725 i.requested = true;
8726 }
8727 i.hasBound = true;
8728 i.doRebind = false;
8729 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008730 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008731 return false;
8732 }
8733 }
8734 return true;
8735 }
8736
8737 private final void requestServiceBindingsLocked(ServiceRecord r) {
8738 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
8739 while (bindings.hasNext()) {
8740 IntentBindRecord i = bindings.next();
8741 if (!requestServiceBindingLocked(r, i, false)) {
8742 break;
8743 }
8744 }
8745 }
8746
8747 private final void realStartServiceLocked(ServiceRecord r,
8748 ProcessRecord app) throws RemoteException {
8749 if (app.thread == null) {
8750 throw new RemoteException();
8751 }
8752
8753 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07008754 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008755
8756 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008757 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008758 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008759
8760 boolean created = false;
8761 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008762 mStringBuilder.setLength(0);
8763 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008764 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008765 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008766 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008767 synchronized (r.stats.getBatteryStats()) {
8768 r.stats.startLaunchedLocked();
8769 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07008770 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008771 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008772 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008773 created = true;
8774 } finally {
8775 if (!created) {
8776 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008777 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008778 }
8779 }
8780
8781 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008782
8783 // If the service is in the started state, and there are no
8784 // pending arguments, then fake up one so its onStartCommand() will
8785 // be called.
8786 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
8787 r.lastStartId++;
8788 if (r.lastStartId < 1) {
8789 r.lastStartId = 1;
8790 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07008791 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008792 }
8793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 sendServiceArgsLocked(r, true);
8795 }
8796
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008797 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
8798 boolean allowCancel) {
8799 boolean canceled = false;
8800
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008801 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008802 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07008803 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008804
8805 // Any delivered but not yet finished starts should be put back
8806 // on the pending list.
8807 final int N = r.deliveredStarts.size();
8808 if (N > 0) {
8809 for (int i=N-1; i>=0; i--) {
8810 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07008811 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008812 if (si.intent == null) {
8813 // We'll generate this again if needed.
8814 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
8815 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
8816 r.pendingStarts.add(0, si);
8817 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
8818 dur *= 2;
8819 if (minDuration < dur) minDuration = dur;
8820 if (resetTime < dur) resetTime = dur;
8821 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008822 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008823 + r.name);
8824 canceled = true;
8825 }
8826 }
8827 r.deliveredStarts.clear();
8828 }
8829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008830 r.totalRestartCount++;
8831 if (r.restartDelay == 0) {
8832 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008833 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 } else {
8835 // If it has been a "reasonably long time" since the service
8836 // was started, then reset our restart duration back to
8837 // the beginning, so we don't infinitely increase the duration
8838 // on a service that just occasionally gets killed (which is
8839 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008840 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008841 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008842 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008843 } else {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008844 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008845 if (r.restartDelay < minDuration) {
8846 r.restartDelay = minDuration;
8847 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008848 }
8849 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008850
8851 r.nextRestartTime = now + r.restartDelay;
8852
8853 // Make sure that we don't end up restarting a bunch of services
8854 // all at the same time.
8855 boolean repeat;
8856 do {
8857 repeat = false;
8858 for (int i=mRestartingServices.size()-1; i>=0; i--) {
8859 ServiceRecord r2 = mRestartingServices.get(i);
8860 if (r2 != r && r.nextRestartTime
8861 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
8862 && r.nextRestartTime
8863 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
8864 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
8865 r.restartDelay = r.nextRestartTime - now;
8866 repeat = true;
8867 break;
8868 }
8869 }
8870 } while (repeat);
8871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008872 if (!mRestartingServices.contains(r)) {
8873 mRestartingServices.add(r);
8874 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008875
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07008876 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008878 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008879 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008880 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008881 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008882 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08008883 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008884 r.shortName, r.restartDelay);
8885
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008886 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 }
8888
8889 final void performServiceRestartLocked(ServiceRecord r) {
8890 if (!mRestartingServices.contains(r)) {
8891 return;
8892 }
8893 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
8894 }
8895
8896 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
8897 if (r.restartDelay == 0) {
8898 return false;
8899 }
8900 r.resetRestartCounter();
8901 mRestartingServices.remove(r);
8902 mHandler.removeCallbacks(r.restarter);
8903 return true;
8904 }
8905
8906 private final boolean bringUpServiceLocked(ServiceRecord r,
8907 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008908 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008909 //r.dump(" ");
8910
Dianne Hackborn36124872009-10-08 16:22:03 -07008911 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008912 sendServiceArgsLocked(r, false);
8913 return true;
8914 }
8915
8916 if (!whileRestarting && r.restartDelay > 0) {
8917 // If waiting for a restart, then do nothing.
8918 return true;
8919 }
8920
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008921 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008922
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008923 // We are now bringing the service up, so no longer in the
8924 // restarting state.
8925 mRestartingServices.remove(r);
8926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008927 final String appName = r.processName;
8928 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
8929 if (app != null && app.thread != null) {
8930 try {
8931 realStartServiceLocked(r, app);
8932 return true;
8933 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008934 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008935 }
8936
8937 // If a dead object exception was thrown -- fall through to
8938 // restart the application.
8939 }
8940
Dianne Hackborn36124872009-10-08 16:22:03 -07008941 // Not running -- get it started, and enqueue this service record
8942 // to be executed when the app comes up.
8943 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
8944 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008945 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07008946 + r.appInfo.packageName + "/"
8947 + r.appInfo.uid + " for service "
8948 + r.intent.getIntent() + ": process is bad");
8949 bringDownServiceLocked(r, true);
8950 return false;
8951 }
8952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008953 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008954 mPendingServices.add(r);
8955 }
Dianne Hackborn36124872009-10-08 16:22:03 -07008956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008957 return true;
8958 }
8959
8960 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008961 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 //r.dump(" ");
8963
8964 // Does it still need to run?
8965 if (!force && r.startRequested) {
8966 return;
8967 }
8968 if (r.connections.size() > 0) {
8969 if (!force) {
8970 // XXX should probably keep a count of the number of auto-create
8971 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008972 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008974 ArrayList<ConnectionRecord> cr = it.next();
8975 for (int i=0; i<cr.size(); i++) {
8976 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
8977 return;
8978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979 }
8980 }
8981 }
8982
8983 // Report to all of the connections that the service is no longer
8984 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008985 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008986 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008987 ArrayList<ConnectionRecord> c = it.next();
8988 for (int i=0; i<c.size(); i++) {
8989 try {
8990 c.get(i).conn.connected(r.name, null);
8991 } catch (Exception e) {
8992 Slog.w(TAG, "Failure disconnecting service " + r.name +
8993 " to connection " + c.get(i).conn.asBinder() +
8994 " (in " + c.get(i).binding.client.processName + ")", e);
8995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008996 }
8997 }
8998 }
8999
9000 // Tell the service that it has been unbound.
9001 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9002 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9003 while (it.hasNext()) {
9004 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009005 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009006 + ": hasBound=" + ibr.hasBound);
9007 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9008 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009009 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009010 updateOomAdjLocked(r.app);
9011 ibr.hasBound = false;
9012 r.app.thread.scheduleUnbindService(r,
9013 ibr.intent.getIntent());
9014 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009015 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009016 + r.shortName, e);
9017 serviceDoneExecutingLocked(r, true);
9018 }
9019 }
9020 }
9021 }
9022
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009023 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009024 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009025 System.identityHashCode(r), r.shortName,
9026 (r.app != null) ? r.app.pid : -1);
9027
9028 mServices.remove(r.name);
9029 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009030 r.totalRestartCount = 0;
9031 unscheduleServiceRestartLocked(r);
9032
9033 // Also make sure it is not on the pending list.
9034 int N = mPendingServices.size();
9035 for (int i=0; i<N; i++) {
9036 if (mPendingServices.get(i) == r) {
9037 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009038 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009039 i--;
9040 N--;
9041 }
9042 }
9043
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009044 r.cancelNotification();
9045 r.isForeground = false;
9046 r.foregroundId = 0;
9047 r.foregroundNoti = null;
9048
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009049 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009050 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009051 r.pendingStarts.clear();
9052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009053 if (r.app != null) {
9054 synchronized (r.stats.getBatteryStats()) {
9055 r.stats.stopLaunchedLocked();
9056 }
9057 r.app.services.remove(r);
9058 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009059 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009060 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009061 mStoppingServices.add(r);
9062 updateOomAdjLocked(r.app);
9063 r.app.thread.scheduleStopService(r);
9064 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009065 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009066 + r.shortName, e);
9067 serviceDoneExecutingLocked(r, true);
9068 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009069 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009070 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009071 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009072 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 }
9074 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009075 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009076 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 }
9078 }
9079
9080 ComponentName startServiceLocked(IApplicationThread caller,
9081 Intent service, String resolvedType,
9082 int callingPid, int callingUid) {
9083 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009084 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085 + " type=" + resolvedType + " args=" + service.getExtras());
9086
9087 if (caller != null) {
9088 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9089 if (callerApp == null) {
9090 throw new SecurityException(
9091 "Unable to find app for caller " + caller
9092 + " (pid=" + Binder.getCallingPid()
9093 + ") when starting service " + service);
9094 }
9095 }
9096
9097 ServiceLookupResult res =
9098 retrieveServiceLocked(service, resolvedType,
9099 callingPid, callingUid);
9100 if (res == null) {
9101 return null;
9102 }
9103 if (res.record == null) {
9104 return new ComponentName("!", res.permission != null
9105 ? res.permission : "private to package");
9106 }
9107 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009108 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9109 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009110 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009111 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 }
9113 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009114 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009115 r.lastStartId++;
9116 if (r.lastStartId < 1) {
9117 r.lastStartId = 1;
9118 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009119 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9120 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009121 r.lastActivity = SystemClock.uptimeMillis();
9122 synchronized (r.stats.getBatteryStats()) {
9123 r.stats.startRunningLocked();
9124 }
9125 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9126 return new ComponentName("!", "Service process is bad");
9127 }
9128 return r.name;
9129 }
9130 }
9131
9132 public ComponentName startService(IApplicationThread caller, Intent service,
9133 String resolvedType) {
9134 // Refuse possible leaked file descriptors
9135 if (service != null && service.hasFileDescriptors() == true) {
9136 throw new IllegalArgumentException("File descriptors passed in Intent");
9137 }
9138
9139 synchronized(this) {
9140 final int callingPid = Binder.getCallingPid();
9141 final int callingUid = Binder.getCallingUid();
9142 final long origId = Binder.clearCallingIdentity();
9143 ComponentName res = startServiceLocked(caller, service,
9144 resolvedType, callingPid, callingUid);
9145 Binder.restoreCallingIdentity(origId);
9146 return res;
9147 }
9148 }
9149
9150 ComponentName startServiceInPackage(int uid,
9151 Intent service, String resolvedType) {
9152 synchronized(this) {
9153 final long origId = Binder.clearCallingIdentity();
9154 ComponentName res = startServiceLocked(null, service,
9155 resolvedType, -1, uid);
9156 Binder.restoreCallingIdentity(origId);
9157 return res;
9158 }
9159 }
9160
9161 public int stopService(IApplicationThread caller, Intent service,
9162 String resolvedType) {
9163 // Refuse possible leaked file descriptors
9164 if (service != null && service.hasFileDescriptors() == true) {
9165 throw new IllegalArgumentException("File descriptors passed in Intent");
9166 }
9167
9168 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009169 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 + " type=" + resolvedType);
9171
9172 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9173 if (caller != null && callerApp == null) {
9174 throw new SecurityException(
9175 "Unable to find app for caller " + caller
9176 + " (pid=" + Binder.getCallingPid()
9177 + ") when stopping service " + service);
9178 }
9179
9180 // If this service is active, make sure it is stopped.
9181 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9182 if (r != null) {
9183 if (r.record != null) {
9184 synchronized (r.record.stats.getBatteryStats()) {
9185 r.record.stats.stopRunningLocked();
9186 }
9187 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009188 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 final long origId = Binder.clearCallingIdentity();
9190 bringDownServiceLocked(r.record, false);
9191 Binder.restoreCallingIdentity(origId);
9192 return 1;
9193 }
9194 return -1;
9195 }
9196 }
9197
9198 return 0;
9199 }
9200
9201 public IBinder peekService(Intent service, String resolvedType) {
9202 // Refuse possible leaked file descriptors
9203 if (service != null && service.hasFileDescriptors() == true) {
9204 throw new IllegalArgumentException("File descriptors passed in Intent");
9205 }
9206
9207 IBinder ret = null;
9208
9209 synchronized(this) {
9210 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9211
9212 if (r != null) {
9213 // r.record is null if findServiceLocked() failed the caller permission check
9214 if (r.record == null) {
9215 throw new SecurityException(
9216 "Permission Denial: Accessing service " + r.record.name
9217 + " from pid=" + Binder.getCallingPid()
9218 + ", uid=" + Binder.getCallingUid()
9219 + " requires " + r.permission);
9220 }
9221 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9222 if (ib != null) {
9223 ret = ib.binder;
9224 }
9225 }
9226 }
9227
9228 return ret;
9229 }
9230
9231 public boolean stopServiceToken(ComponentName className, IBinder token,
9232 int startId) {
9233 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009234 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009235 + " " + token + " startId=" + startId);
9236 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009237 if (r != null) {
9238 if (startId >= 0) {
9239 // Asked to only stop if done with all work. Note that
9240 // to avoid leaks, we will take this as dropping all
9241 // start items up to and including this one.
9242 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9243 if (si != null) {
9244 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009245 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9246 cur.removeUriPermissionsLocked();
9247 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009248 break;
9249 }
9250 }
9251 }
9252
9253 if (r.lastStartId != startId) {
9254 return false;
9255 }
9256
9257 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009258 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009259 + " is last, but have " + r.deliveredStarts.size()
9260 + " remaining args");
9261 }
9262 }
9263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 synchronized (r.stats.getBatteryStats()) {
9265 r.stats.stopRunningLocked();
9266 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009267 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009268 }
9269 final long origId = Binder.clearCallingIdentity();
9270 bringDownServiceLocked(r, false);
9271 Binder.restoreCallingIdentity(origId);
9272 return true;
9273 }
9274 }
9275 return false;
9276 }
9277
9278 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009279 int id, Notification notification, boolean removeNotification) {
9280 final long origId = Binder.clearCallingIdentity();
9281 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009282 synchronized(this) {
9283 ServiceRecord r = findServiceLocked(className, token);
9284 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009285 if (id != 0) {
9286 if (notification == null) {
9287 throw new IllegalArgumentException("null notification");
9288 }
9289 if (r.foregroundId != id) {
9290 r.cancelNotification();
9291 r.foregroundId = id;
9292 }
9293 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9294 r.foregroundNoti = notification;
9295 r.isForeground = true;
9296 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009297 if (r.app != null) {
9298 updateServiceForegroundLocked(r.app, true);
9299 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009300 } else {
9301 if (r.isForeground) {
9302 r.isForeground = false;
9303 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009304 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009305 updateServiceForegroundLocked(r.app, true);
9306 }
9307 }
9308 if (removeNotification) {
9309 r.cancelNotification();
9310 r.foregroundId = 0;
9311 r.foregroundNoti = null;
9312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009313 }
9314 }
9315 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009316 } finally {
9317 Binder.restoreCallingIdentity(origId);
9318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009319 }
9320
9321 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9322 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009323 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 if (sr.isForeground) {
9325 anyForeground = true;
9326 break;
9327 }
9328 }
9329 if (anyForeground != proc.foregroundServices) {
9330 proc.foregroundServices = anyForeground;
9331 if (oomAdj) {
9332 updateOomAdjLocked();
9333 }
9334 }
9335 }
9336
9337 public int bindService(IApplicationThread caller, IBinder token,
9338 Intent service, String resolvedType,
9339 IServiceConnection connection, int flags) {
9340 // Refuse possible leaked file descriptors
9341 if (service != null && service.hasFileDescriptors() == true) {
9342 throw new IllegalArgumentException("File descriptors passed in Intent");
9343 }
9344
9345 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009346 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009347 + " type=" + resolvedType + " conn=" + connection.asBinder()
9348 + " flags=0x" + Integer.toHexString(flags));
9349 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9350 if (callerApp == null) {
9351 throw new SecurityException(
9352 "Unable to find app for caller " + caller
9353 + " (pid=" + Binder.getCallingPid()
9354 + ") when binding service " + service);
9355 }
9356
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009357 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009358 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009359 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009361 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009362 return 0;
9363 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009364 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365 }
9366
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009367 int clientLabel = 0;
9368 PendingIntent clientIntent = null;
9369
9370 if (callerApp.info.uid == Process.SYSTEM_UID) {
9371 // Hacky kind of thing -- allow system stuff to tell us
9372 // what they are, so we can report this elsewhere for
9373 // others to know why certain services are running.
9374 try {
9375 clientIntent = (PendingIntent)service.getParcelableExtra(
9376 Intent.EXTRA_CLIENT_INTENT);
9377 } catch (RuntimeException e) {
9378 }
9379 if (clientIntent != null) {
9380 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9381 if (clientLabel != 0) {
9382 // There are no useful extras in the intent, trash them.
9383 // System code calling with this stuff just needs to know
9384 // this will happen.
9385 service = service.cloneFilter();
9386 }
9387 }
9388 }
9389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009390 ServiceLookupResult res =
9391 retrieveServiceLocked(service, resolvedType,
9392 Binder.getCallingPid(), Binder.getCallingUid());
9393 if (res == null) {
9394 return 0;
9395 }
9396 if (res.record == null) {
9397 return -1;
9398 }
9399 ServiceRecord s = res.record;
9400
9401 final long origId = Binder.clearCallingIdentity();
9402
9403 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009404 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009405 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009406 }
9407
9408 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9409 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009410 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009411
9412 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009413 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9414 if (clist == null) {
9415 clist = new ArrayList<ConnectionRecord>();
9416 s.connections.put(binder, clist);
9417 }
9418 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009419 b.connections.add(c);
9420 if (activity != null) {
9421 if (activity.connections == null) {
9422 activity.connections = new HashSet<ConnectionRecord>();
9423 }
9424 activity.connections.add(c);
9425 }
9426 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009427 clist = mServiceConnections.get(binder);
9428 if (clist == null) {
9429 clist = new ArrayList<ConnectionRecord>();
9430 mServiceConnections.put(binder, clist);
9431 }
9432 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009433
9434 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9435 s.lastActivity = SystemClock.uptimeMillis();
9436 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9437 return 0;
9438 }
9439 }
9440
9441 if (s.app != null) {
9442 // This could have made the service more important.
9443 updateOomAdjLocked(s.app);
9444 }
9445
Joe Onorato8a9b2202010-02-26 18:56:32 -08009446 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009447 + ": received=" + b.intent.received
9448 + " apps=" + b.intent.apps.size()
9449 + " doRebind=" + b.intent.doRebind);
9450
9451 if (s.app != null && b.intent.received) {
9452 // Service is already running, so we can immediately
9453 // publish the connection.
9454 try {
9455 c.conn.connected(s.name, b.intent.binder);
9456 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009457 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009458 + " to connection " + c.conn.asBinder()
9459 + " (in " + c.binding.client.processName + ")", e);
9460 }
9461
9462 // If this is the first app connected back to this binding,
9463 // and the service had previously asked to be told when
9464 // rebound, then do so.
9465 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9466 requestServiceBindingLocked(s, b.intent, true);
9467 }
9468 } else if (!b.intent.requested) {
9469 requestServiceBindingLocked(s, b.intent, false);
9470 }
9471
9472 Binder.restoreCallingIdentity(origId);
9473 }
9474
9475 return 1;
9476 }
9477
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009478 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009479 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009480 IBinder binder = c.conn.asBinder();
9481 AppBindRecord b = c.binding;
9482 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009483 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9484 if (clist != null) {
9485 clist.remove(c);
9486 if (clist.size() == 0) {
9487 s.connections.remove(binder);
9488 }
9489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009490 b.connections.remove(c);
9491 if (c.activity != null && c.activity != skipAct) {
9492 if (c.activity.connections != null) {
9493 c.activity.connections.remove(c);
9494 }
9495 }
9496 if (b.client != skipApp) {
9497 b.client.connections.remove(c);
9498 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009499 clist = mServiceConnections.get(binder);
9500 if (clist != null) {
9501 clist.remove(c);
9502 if (clist.size() == 0) {
9503 mServiceConnections.remove(binder);
9504 }
9505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009506
9507 if (b.connections.size() == 0) {
9508 b.intent.apps.remove(b.client);
9509 }
9510
Joe Onorato8a9b2202010-02-26 18:56:32 -08009511 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009512 + ": shouldUnbind=" + b.intent.hasBound);
9513 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
9514 && b.intent.hasBound) {
9515 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009516 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517 updateOomAdjLocked(s.app);
9518 b.intent.hasBound = false;
9519 // Assume the client doesn't want to know about a rebind;
9520 // we will deal with that later if it asks for one.
9521 b.intent.doRebind = false;
9522 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
9523 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009524 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009525 serviceDoneExecutingLocked(s, true);
9526 }
9527 }
9528
9529 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
9530 bringDownServiceLocked(s, false);
9531 }
9532 }
9533
9534 public boolean unbindService(IServiceConnection connection) {
9535 synchronized (this) {
9536 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009537 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009538 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
9539 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009540 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009541 + connection.asBinder());
9542 return false;
9543 }
9544
9545 final long origId = Binder.clearCallingIdentity();
9546
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009547 while (clist.size() > 0) {
9548 ConnectionRecord r = clist.get(0);
9549 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009551 if (r.binding.service.app != null) {
9552 // This could have made the service less important.
9553 updateOomAdjLocked(r.binding.service.app);
9554 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009555 }
9556
9557 Binder.restoreCallingIdentity(origId);
9558 }
9559
9560 return true;
9561 }
9562
9563 public void publishService(IBinder token, Intent intent, IBinder service) {
9564 // Refuse possible leaked file descriptors
9565 if (intent != null && intent.hasFileDescriptors() == true) {
9566 throw new IllegalArgumentException("File descriptors passed in Intent");
9567 }
9568
9569 synchronized(this) {
9570 if (!(token instanceof ServiceRecord)) {
9571 throw new IllegalArgumentException("Invalid service token");
9572 }
9573 ServiceRecord r = (ServiceRecord)token;
9574
9575 final long origId = Binder.clearCallingIdentity();
9576
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009577 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 + " " + intent + ": " + service);
9579 if (r != null) {
9580 Intent.FilterComparison filter
9581 = new Intent.FilterComparison(intent);
9582 IntentBindRecord b = r.bindings.get(filter);
9583 if (b != null && !b.received) {
9584 b.binder = service;
9585 b.requested = true;
9586 b.received = true;
9587 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009588 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009589 = r.connections.values().iterator();
9590 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009591 ArrayList<ConnectionRecord> clist = it.next();
9592 for (int i=0; i<clist.size(); i++) {
9593 ConnectionRecord c = clist.get(i);
9594 if (!filter.equals(c.binding.intent.intent)) {
9595 if (DEBUG_SERVICE) Slog.v(
9596 TAG, "Not publishing to: " + c);
9597 if (DEBUG_SERVICE) Slog.v(
9598 TAG, "Bound intent: " + c.binding.intent.intent);
9599 if (DEBUG_SERVICE) Slog.v(
9600 TAG, "Published intent: " + intent);
9601 continue;
9602 }
9603 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
9604 try {
9605 c.conn.connected(r.name, service);
9606 } catch (Exception e) {
9607 Slog.w(TAG, "Failure sending service " + r.name +
9608 " to connection " + c.conn.asBinder() +
9609 " (in " + c.binding.client.processName + ")", e);
9610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009611 }
9612 }
9613 }
9614 }
9615
9616 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9617
9618 Binder.restoreCallingIdentity(origId);
9619 }
9620 }
9621 }
9622
9623 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
9624 // Refuse possible leaked file descriptors
9625 if (intent != null && intent.hasFileDescriptors() == true) {
9626 throw new IllegalArgumentException("File descriptors passed in Intent");
9627 }
9628
9629 synchronized(this) {
9630 if (!(token instanceof ServiceRecord)) {
9631 throw new IllegalArgumentException("Invalid service token");
9632 }
9633 ServiceRecord r = (ServiceRecord)token;
9634
9635 final long origId = Binder.clearCallingIdentity();
9636
9637 if (r != null) {
9638 Intent.FilterComparison filter
9639 = new Intent.FilterComparison(intent);
9640 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009641 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009642 + " at " + b + ": apps="
9643 + (b != null ? b.apps.size() : 0));
9644 if (b != null) {
9645 if (b.apps.size() > 0) {
9646 // Applications have already bound since the last
9647 // unbind, so just rebind right here.
9648 requestServiceBindingLocked(r, b, true);
9649 } else {
9650 // Note to tell the service the next time there is
9651 // a new client.
9652 b.doRebind = true;
9653 }
9654 }
9655
9656 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
9657
9658 Binder.restoreCallingIdentity(origId);
9659 }
9660 }
9661 }
9662
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009663 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 synchronized(this) {
9665 if (!(token instanceof ServiceRecord)) {
9666 throw new IllegalArgumentException("Invalid service token");
9667 }
9668 ServiceRecord r = (ServiceRecord)token;
9669 boolean inStopping = mStoppingServices.contains(token);
9670 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009672 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009673 + " with incorrect token: given " + token
9674 + ", expected " + r);
9675 return;
9676 }
9677
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009678 if (type == 1) {
9679 // This is a call from a service start... take care of
9680 // book-keeping.
9681 r.callStart = true;
9682 switch (res) {
9683 case Service.START_STICKY_COMPATIBILITY:
9684 case Service.START_STICKY: {
9685 // We are done with the associated start arguments.
9686 r.findDeliveredStart(startId, true);
9687 // Don't stop if killed.
9688 r.stopIfKilled = false;
9689 break;
9690 }
9691 case Service.START_NOT_STICKY: {
9692 // We are done with the associated start arguments.
9693 r.findDeliveredStart(startId, true);
9694 if (r.lastStartId == startId) {
9695 // There is no more work, and this service
9696 // doesn't want to hang around if killed.
9697 r.stopIfKilled = true;
9698 }
9699 break;
9700 }
9701 case Service.START_REDELIVER_INTENT: {
9702 // We'll keep this item until they explicitly
9703 // call stop for it, but keep track of the fact
9704 // that it was delivered.
9705 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9706 if (si != null) {
9707 si.deliveryCount = 0;
9708 si.doneExecutingCount++;
9709 // Don't stop if killed.
9710 r.stopIfKilled = true;
9711 }
9712 break;
9713 }
9714 default:
9715 throw new IllegalArgumentException(
9716 "Unknown service start result: " + res);
9717 }
9718 if (res == Service.START_STICKY_COMPATIBILITY) {
9719 r.callStart = false;
9720 }
9721 }
9722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009723 final long origId = Binder.clearCallingIdentity();
9724 serviceDoneExecutingLocked(r, inStopping);
9725 Binder.restoreCallingIdentity(origId);
9726 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009727 Slog.w(TAG, "Done executing unknown service from pid "
9728 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009729 }
9730 }
9731 }
9732
9733 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009734 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
9735 + ": nesting=" + r.executeNesting
9736 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009737 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009738 r.executeNesting--;
9739 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009740 if (DEBUG_SERVICE) Slog.v(TAG,
9741 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009742 r.app.executingServices.remove(r);
9743 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009744 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
9745 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009746 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
9747 }
9748 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009749 if (DEBUG_SERVICE) Slog.v(TAG,
9750 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 mStoppingServices.remove(r);
9752 }
9753 updateOomAdjLocked(r.app);
9754 }
9755 }
9756
9757 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009758 String anrMessage = null;
9759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009760 synchronized(this) {
9761 if (proc.executingServices.size() == 0 || proc.thread == null) {
9762 return;
9763 }
9764 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
9765 Iterator<ServiceRecord> it = proc.executingServices.iterator();
9766 ServiceRecord timeout = null;
9767 long nextTime = 0;
9768 while (it.hasNext()) {
9769 ServiceRecord sr = it.next();
9770 if (sr.executingStart < maxTime) {
9771 timeout = sr;
9772 break;
9773 }
9774 if (sr.executingStart > nextTime) {
9775 nextTime = sr.executingStart;
9776 }
9777 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009778 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009779 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009780 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009781 } else {
9782 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9783 msg.obj = proc;
9784 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
9785 }
9786 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07009787
9788 if (anrMessage != null) {
9789 appNotResponding(proc, null, null, anrMessage);
9790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 }
9792
9793 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -07009794 // BACKUP AND RESTORE
9795 // =========================================================
9796
9797 // Cause the target app to be launched if necessary and its backup agent
9798 // instantiated. The backup agent will invoke backupAgentCreated() on the
9799 // activity manager to announce its creation.
9800 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009801 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07009802 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
9803
9804 synchronized(this) {
9805 // !!! TODO: currently no check here that we're already bound
9806 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9807 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9808 synchronized (stats) {
9809 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
9810 }
9811
9812 BackupRecord r = new BackupRecord(ss, app, backupMode);
9813 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
9814 // startProcessLocked() returns existing proc's record if it's already running
9815 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07009816 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -07009817 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009818 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -07009819 return false;
9820 }
9821
9822 r.app = proc;
9823 mBackupTarget = r;
9824 mBackupAppName = app.packageName;
9825
Christopher Tate6fa95972009-06-05 18:43:55 -07009826 // Try not to kill the process during backup
9827 updateOomAdjLocked(proc);
9828
Christopher Tate181fafa2009-05-14 11:12:14 -07009829 // If the process is already attached, schedule the creation of the backup agent now.
9830 // If it is not yet live, this will be done when it attaches to the framework.
9831 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009832 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -07009833 try {
9834 proc.thread.scheduleCreateBackupAgent(app, backupMode);
9835 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -07009836 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -07009837 }
9838 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009839 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -07009840 }
9841 // Invariants: at this point, the target app process exists and the application
9842 // is either already running or in the process of coming up. mBackupTarget and
9843 // mBackupAppName describe the app, so that when it binds back to the AM we
9844 // know that it's scheduled for a backup-agent operation.
9845 }
9846
9847 return true;
9848 }
9849
9850 // A backup agent has just come up
9851 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009852 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -07009853 + " = " + agent);
9854
9855 synchronized(this) {
9856 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009857 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -07009858 return;
9859 }
Dianne Hackborn06740692010-09-22 22:46:21 -07009860 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009861
Dianne Hackborn06740692010-09-22 22:46:21 -07009862 long oldIdent = Binder.clearCallingIdentity();
9863 try {
9864 IBackupManager bm = IBackupManager.Stub.asInterface(
9865 ServiceManager.getService(Context.BACKUP_SERVICE));
9866 bm.agentConnected(agentPackageName, agent);
9867 } catch (RemoteException e) {
9868 // can't happen; the backup manager service is local
9869 } catch (Exception e) {
9870 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
9871 e.printStackTrace();
9872 } finally {
9873 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -07009874 }
9875 }
9876
9877 // done with this agent
9878 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009879 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -07009880 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009881 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -07009882 return;
9883 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009884
9885 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -07009886 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009887 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -07009888 return;
9889 }
9890
Christopher Tate181fafa2009-05-14 11:12:14 -07009891 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009892 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -07009893 return;
9894 }
9895
Christopher Tate6fa95972009-06-05 18:43:55 -07009896 ProcessRecord proc = mBackupTarget.app;
9897 mBackupTarget = null;
9898 mBackupAppName = null;
9899
9900 // Not backing this app up any more; reset its OOM adjustment
9901 updateOomAdjLocked(proc);
9902
Christopher Tatec7b31e32009-06-10 15:49:30 -07009903 // If the app crashed during backup, 'thread' will be null here
9904 if (proc.thread != null) {
9905 try {
9906 proc.thread.scheduleDestroyBackupAgent(appInfo);
9907 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009908 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -07009909 e.printStackTrace();
9910 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009911 }
Christopher Tate181fafa2009-05-14 11:12:14 -07009912 }
9913 }
9914 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009915 // BROADCASTS
9916 // =========================================================
9917
Josh Bartel7f208742010-02-25 11:01:44 -06009918 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009919 List cur) {
9920 final ContentResolver resolver = mContext.getContentResolver();
9921 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
9922 if (list == null) {
9923 return cur;
9924 }
9925 int N = list.size();
9926 for (int i=0; i<N; i++) {
9927 Intent intent = list.get(i);
9928 if (filter.match(resolver, intent, true, TAG) >= 0) {
9929 if (cur == null) {
9930 cur = new ArrayList<Intent>();
9931 }
9932 cur.add(intent);
9933 }
9934 }
9935 return cur;
9936 }
9937
9938 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009939 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009940 + mBroadcastsScheduled);
9941
9942 if (mBroadcastsScheduled) {
9943 return;
9944 }
9945 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
9946 mBroadcastsScheduled = true;
9947 }
9948
9949 public Intent registerReceiver(IApplicationThread caller,
9950 IIntentReceiver receiver, IntentFilter filter, String permission) {
9951 synchronized(this) {
9952 ProcessRecord callerApp = null;
9953 if (caller != null) {
9954 callerApp = getRecordForAppLocked(caller);
9955 if (callerApp == null) {
9956 throw new SecurityException(
9957 "Unable to find app for caller " + caller
9958 + " (pid=" + Binder.getCallingPid()
9959 + ") when registering receiver " + receiver);
9960 }
9961 }
9962
9963 List allSticky = null;
9964
9965 // Look for any matching sticky broadcasts...
9966 Iterator actions = filter.actionsIterator();
9967 if (actions != null) {
9968 while (actions.hasNext()) {
9969 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -06009970 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 }
9972 } else {
Josh Bartel7f208742010-02-25 11:01:44 -06009973 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009974 }
9975
9976 // The first sticky in the list is returned directly back to
9977 // the client.
9978 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
9979
Joe Onorato8a9b2202010-02-26 18:56:32 -08009980 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981 + ": " + sticky);
9982
9983 if (receiver == null) {
9984 return sticky;
9985 }
9986
9987 ReceiverList rl
9988 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
9989 if (rl == null) {
9990 rl = new ReceiverList(this, callerApp,
9991 Binder.getCallingPid(),
9992 Binder.getCallingUid(), receiver);
9993 if (rl.app != null) {
9994 rl.app.receivers.add(rl);
9995 } else {
9996 try {
9997 receiver.asBinder().linkToDeath(rl, 0);
9998 } catch (RemoteException e) {
9999 return sticky;
10000 }
10001 rl.linkedToDeath = true;
10002 }
10003 mRegisteredReceivers.put(receiver.asBinder(), rl);
10004 }
10005 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10006 rl.add(bf);
10007 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010008 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010009 }
10010 mReceiverResolver.addFilter(bf);
10011
10012 // Enqueue broadcasts for all existing stickies that match
10013 // this filter.
10014 if (allSticky != null) {
10015 ArrayList receivers = new ArrayList();
10016 receivers.add(bf);
10017
10018 int N = allSticky.size();
10019 for (int i=0; i<N; i++) {
10020 Intent intent = (Intent)allSticky.get(i);
10021 BroadcastRecord r = new BroadcastRecord(intent, null,
10022 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010023 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010024 if (mParallelBroadcasts.size() == 0) {
10025 scheduleBroadcastsLocked();
10026 }
10027 mParallelBroadcasts.add(r);
10028 }
10029 }
10030
10031 return sticky;
10032 }
10033 }
10034
10035 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010036 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010037
10038 boolean doNext = false;
10039
10040 synchronized(this) {
10041 ReceiverList rl
10042 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10043 if (rl != null) {
10044 if (rl.curBroadcast != null) {
10045 BroadcastRecord r = rl.curBroadcast;
10046 doNext = finishReceiverLocked(
10047 receiver.asBinder(), r.resultCode, r.resultData,
10048 r.resultExtras, r.resultAbort, true);
10049 }
10050
10051 if (rl.app != null) {
10052 rl.app.receivers.remove(rl);
10053 }
10054 removeReceiverLocked(rl);
10055 if (rl.linkedToDeath) {
10056 rl.linkedToDeath = false;
10057 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10058 }
10059 }
10060 }
10061
10062 if (!doNext) {
10063 return;
10064 }
10065
10066 final long origId = Binder.clearCallingIdentity();
10067 processNextBroadcast(false);
10068 trimApplications();
10069 Binder.restoreCallingIdentity(origId);
10070 }
10071
10072 void removeReceiverLocked(ReceiverList rl) {
10073 mRegisteredReceivers.remove(rl.receiver.asBinder());
10074 int N = rl.size();
10075 for (int i=0; i<N; i++) {
10076 mReceiverResolver.removeFilter(rl.get(i));
10077 }
10078 }
10079
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010080 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10081 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10082 ProcessRecord r = mLruProcesses.get(i);
10083 if (r.thread != null) {
10084 try {
10085 r.thread.dispatchPackageBroadcast(cmd, packages);
10086 } catch (RemoteException ex) {
10087 }
10088 }
10089 }
10090 }
10091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010092 private final int broadcastIntentLocked(ProcessRecord callerApp,
10093 String callerPackage, Intent intent, String resolvedType,
10094 IIntentReceiver resultTo, int resultCode, String resultData,
10095 Bundle map, String requiredPermission,
10096 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10097 intent = new Intent(intent);
10098
Joe Onorato8a9b2202010-02-26 18:56:32 -080010099 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010100 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10101 + " ordered=" + ordered);
10102 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010103 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010104 }
10105
10106 // Handle special intents: if this broadcast is from the package
10107 // manager about a package being removed, we need to remove all of
10108 // its activities from the history stack.
10109 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10110 intent.getAction());
10111 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10112 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010113 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 || uidRemoved) {
10115 if (checkComponentPermission(
10116 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
10117 callingPid, callingUid, -1)
10118 == PackageManager.PERMISSION_GRANTED) {
10119 if (uidRemoved) {
10120 final Bundle intentExtras = intent.getExtras();
10121 final int uid = intentExtras != null
10122 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10123 if (uid >= 0) {
10124 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10125 synchronized (bs) {
10126 bs.removeUidStatsLocked(uid);
10127 }
10128 }
10129 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010130 // If resources are unvailble just force stop all
10131 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010132 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010133 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10134 if (list != null && (list.length > 0)) {
10135 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010136 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010137 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010138 sendPackageBroadcastLocked(
10139 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010140 }
10141 } else {
10142 Uri data = intent.getData();
10143 String ssp;
10144 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10145 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10146 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010147 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010148 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010149 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10150 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10151 new String[] {ssp});
10152 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010153 }
10154 }
10155 }
10156 } else {
10157 String msg = "Permission Denial: " + intent.getAction()
10158 + " broadcast from " + callerPackage + " (pid=" + callingPid
10159 + ", uid=" + callingUid + ")"
10160 + " requires "
10161 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010162 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010163 throw new SecurityException(msg);
10164 }
10165 }
10166
10167 /*
10168 * If this is the time zone changed action, queue up a message that will reset the timezone
10169 * of all currently running processes. This message will get queued up before the broadcast
10170 * happens.
10171 */
10172 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10173 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10174 }
10175
Dianne Hackborn854060af2009-07-09 18:14:31 -070010176 /*
10177 * Prevent non-system code (defined here to be non-persistent
10178 * processes) from sending protected broadcasts.
10179 */
10180 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10181 || callingUid == Process.SHELL_UID || callingUid == 0) {
10182 // Always okay.
10183 } else if (callerApp == null || !callerApp.persistent) {
10184 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010185 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010186 intent.getAction())) {
10187 String msg = "Permission Denial: not allowed to send broadcast "
10188 + intent.getAction() + " from pid="
10189 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010190 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010191 throw new SecurityException(msg);
10192 }
10193 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010194 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010195 return BROADCAST_SUCCESS;
10196 }
10197 }
10198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010199 // Add to the sticky list if requested.
10200 if (sticky) {
10201 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10202 callingPid, callingUid)
10203 != PackageManager.PERMISSION_GRANTED) {
10204 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10205 + callingPid + ", uid=" + callingUid
10206 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010207 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010208 throw new SecurityException(msg);
10209 }
10210 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010211 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010212 + " and enforce permission " + requiredPermission);
10213 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10214 }
10215 if (intent.getComponent() != null) {
10216 throw new SecurityException(
10217 "Sticky broadcasts can't target a specific component");
10218 }
10219 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10220 if (list == null) {
10221 list = new ArrayList<Intent>();
10222 mStickyBroadcasts.put(intent.getAction(), list);
10223 }
10224 int N = list.size();
10225 int i;
10226 for (i=0; i<N; i++) {
10227 if (intent.filterEquals(list.get(i))) {
10228 // This sticky already exists, replace it.
10229 list.set(i, new Intent(intent));
10230 break;
10231 }
10232 }
10233 if (i >= N) {
10234 list.add(new Intent(intent));
10235 }
10236 }
10237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 // Figure out who all will receive this broadcast.
10239 List receivers = null;
10240 List<BroadcastFilter> registeredReceivers = null;
10241 try {
10242 if (intent.getComponent() != null) {
10243 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010244 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010245 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010246 if (ai != null) {
10247 receivers = new ArrayList();
10248 ResolveInfo ri = new ResolveInfo();
10249 ri.activityInfo = ai;
10250 receivers.add(ri);
10251 }
10252 } else {
10253 // Need to resolve the intent to interested receivers...
10254 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10255 == 0) {
10256 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010257 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010258 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010259 }
Mihai Preda074edef2009-05-18 17:13:31 +020010260 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010261 }
10262 } catch (RemoteException ex) {
10263 // pm is in same process, this will never happen.
10264 }
10265
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010266 final boolean replacePending =
10267 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10268
Joe Onorato8a9b2202010-02-26 18:56:32 -080010269 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010270 + " replacePending=" + replacePending);
10271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10273 if (!ordered && NR > 0) {
10274 // If we are not serializing this broadcast, then send the
10275 // registered receivers separately so they don't wait for the
10276 // components to be launched.
10277 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10278 callerPackage, callingPid, callingUid, requiredPermission,
10279 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010280 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010281 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010282 TAG, "Enqueueing parallel broadcast " + r
10283 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010284 boolean replaced = false;
10285 if (replacePending) {
10286 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10287 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010288 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010289 "***** DROPPING PARALLEL: " + intent);
10290 mParallelBroadcasts.set(i, r);
10291 replaced = true;
10292 break;
10293 }
10294 }
10295 }
10296 if (!replaced) {
10297 mParallelBroadcasts.add(r);
10298 scheduleBroadcastsLocked();
10299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010300 registeredReceivers = null;
10301 NR = 0;
10302 }
10303
10304 // Merge into one list.
10305 int ir = 0;
10306 if (receivers != null) {
10307 // A special case for PACKAGE_ADDED: do not allow the package
10308 // being added to see this broadcast. This prevents them from
10309 // using this as a back door to get run as soon as they are
10310 // installed. Maybe in the future we want to have a special install
10311 // broadcast or such for apps, but we'd like to deliberately make
10312 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010313 String skipPackages[] = null;
10314 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10315 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10316 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10317 Uri data = intent.getData();
10318 if (data != null) {
10319 String pkgName = data.getSchemeSpecificPart();
10320 if (pkgName != null) {
10321 skipPackages = new String[] { pkgName };
10322 }
10323 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010324 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010325 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010326 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010327 if (skipPackages != null && (skipPackages.length > 0)) {
10328 for (String skipPackage : skipPackages) {
10329 if (skipPackage != null) {
10330 int NT = receivers.size();
10331 for (int it=0; it<NT; it++) {
10332 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10333 if (curt.activityInfo.packageName.equals(skipPackage)) {
10334 receivers.remove(it);
10335 it--;
10336 NT--;
10337 }
10338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010339 }
10340 }
10341 }
10342
10343 int NT = receivers != null ? receivers.size() : 0;
10344 int it = 0;
10345 ResolveInfo curt = null;
10346 BroadcastFilter curr = null;
10347 while (it < NT && ir < NR) {
10348 if (curt == null) {
10349 curt = (ResolveInfo)receivers.get(it);
10350 }
10351 if (curr == null) {
10352 curr = registeredReceivers.get(ir);
10353 }
10354 if (curr.getPriority() >= curt.priority) {
10355 // Insert this broadcast record into the final list.
10356 receivers.add(it, curr);
10357 ir++;
10358 curr = null;
10359 it++;
10360 NT++;
10361 } else {
10362 // Skip to the next ResolveInfo in the final list.
10363 it++;
10364 curt = null;
10365 }
10366 }
10367 }
10368 while (ir < NR) {
10369 if (receivers == null) {
10370 receivers = new ArrayList();
10371 }
10372 receivers.add(registeredReceivers.get(ir));
10373 ir++;
10374 }
10375
10376 if ((receivers != null && receivers.size() > 0)
10377 || resultTo != null) {
10378 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10379 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010380 receivers, resultTo, resultCode, resultData, map, ordered,
10381 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010382 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 TAG, "Enqueueing ordered broadcast " + r
10384 + ": prev had " + mOrderedBroadcasts.size());
10385 if (DEBUG_BROADCAST) {
10386 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010387 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010389 boolean replaced = false;
10390 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010391 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010392 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010393 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010394 "***** DROPPING ORDERED: " + intent);
10395 mOrderedBroadcasts.set(i, r);
10396 replaced = true;
10397 break;
10398 }
10399 }
10400 }
10401 if (!replaced) {
10402 mOrderedBroadcasts.add(r);
10403 scheduleBroadcastsLocked();
10404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 }
10406
10407 return BROADCAST_SUCCESS;
10408 }
10409
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010410 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010411 // Refuse possible leaked file descriptors
10412 if (intent != null && intent.hasFileDescriptors() == true) {
10413 throw new IllegalArgumentException("File descriptors passed in Intent");
10414 }
10415
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010416 int flags = intent.getFlags();
10417
10418 if (!mProcessesReady) {
10419 // if the caller really truly claims to know what they're doing, go
10420 // ahead and allow the broadcast without launching any receivers
10421 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10422 intent = new Intent(intent);
10423 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10424 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10425 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10426 + " before boot completion");
10427 throw new IllegalStateException("Cannot broadcast before boot completed");
10428 }
10429 }
10430
10431 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10432 throw new IllegalArgumentException(
10433 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10434 }
10435
10436 return intent;
10437 }
10438
10439 public final int broadcastIntent(IApplicationThread caller,
10440 Intent intent, String resolvedType, IIntentReceiver resultTo,
10441 int resultCode, String resultData, Bundle map,
10442 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010444 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10447 final int callingPid = Binder.getCallingPid();
10448 final int callingUid = Binder.getCallingUid();
10449 final long origId = Binder.clearCallingIdentity();
10450 int res = broadcastIntentLocked(callerApp,
10451 callerApp != null ? callerApp.info.packageName : null,
10452 intent, resolvedType, resultTo,
10453 resultCode, resultData, map, requiredPermission, serialized,
10454 sticky, callingPid, callingUid);
10455 Binder.restoreCallingIdentity(origId);
10456 return res;
10457 }
10458 }
10459
10460 int broadcastIntentInPackage(String packageName, int uid,
10461 Intent intent, String resolvedType, IIntentReceiver resultTo,
10462 int resultCode, String resultData, Bundle map,
10463 String requiredPermission, boolean serialized, boolean sticky) {
10464 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010465 intent = verifyBroadcastLocked(intent);
10466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010467 final long origId = Binder.clearCallingIdentity();
10468 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10469 resultTo, resultCode, resultData, map, requiredPermission,
10470 serialized, sticky, -1, uid);
10471 Binder.restoreCallingIdentity(origId);
10472 return res;
10473 }
10474 }
10475
10476 public final void unbroadcastIntent(IApplicationThread caller,
10477 Intent intent) {
10478 // Refuse possible leaked file descriptors
10479 if (intent != null && intent.hasFileDescriptors() == true) {
10480 throw new IllegalArgumentException("File descriptors passed in Intent");
10481 }
10482
10483 synchronized(this) {
10484 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
10485 != PackageManager.PERMISSION_GRANTED) {
10486 String msg = "Permission Denial: unbroadcastIntent() from pid="
10487 + Binder.getCallingPid()
10488 + ", uid=" + Binder.getCallingUid()
10489 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010490 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010491 throw new SecurityException(msg);
10492 }
10493 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10494 if (list != null) {
10495 int N = list.size();
10496 int i;
10497 for (i=0; i<N; i++) {
10498 if (intent.filterEquals(list.get(i))) {
10499 list.remove(i);
10500 break;
10501 }
10502 }
10503 }
10504 }
10505 }
10506
10507 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
10508 String resultData, Bundle resultExtras, boolean resultAbort,
10509 boolean explicit) {
10510 if (mOrderedBroadcasts.size() == 0) {
10511 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010512 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010513 }
10514 return false;
10515 }
10516 BroadcastRecord r = mOrderedBroadcasts.get(0);
10517 if (r.receiver == null) {
10518 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010519 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010520 }
10521 return false;
10522 }
10523 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010524 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010525 return false;
10526 }
10527 int state = r.state;
10528 r.state = r.IDLE;
10529 if (state == r.IDLE) {
10530 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010531 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010532 }
10533 }
10534 r.receiver = null;
10535 r.intent.setComponent(null);
10536 if (r.curApp != null) {
10537 r.curApp.curReceiver = null;
10538 }
10539 if (r.curFilter != null) {
10540 r.curFilter.receiverList.curBroadcast = null;
10541 }
10542 r.curFilter = null;
10543 r.curApp = null;
10544 r.curComponent = null;
10545 r.curReceiver = null;
10546 mPendingBroadcast = null;
10547
10548 r.resultCode = resultCode;
10549 r.resultData = resultData;
10550 r.resultExtras = resultExtras;
10551 r.resultAbort = resultAbort;
10552
10553 // We will process the next receiver right now if this is finishing
10554 // an app receiver (which is always asynchronous) or after we have
10555 // come back from calling a receiver.
10556 return state == BroadcastRecord.APP_RECEIVE
10557 || state == BroadcastRecord.CALL_DONE_RECEIVE;
10558 }
10559
10560 public void finishReceiver(IBinder who, int resultCode, String resultData,
10561 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010562 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010563
10564 // Refuse possible leaked file descriptors
10565 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
10566 throw new IllegalArgumentException("File descriptors passed in Bundle");
10567 }
10568
10569 boolean doNext;
10570
10571 final long origId = Binder.clearCallingIdentity();
10572
10573 synchronized(this) {
10574 doNext = finishReceiverLocked(
10575 who, resultCode, resultData, resultExtras, resultAbort, true);
10576 }
10577
10578 if (doNext) {
10579 processNextBroadcast(false);
10580 }
10581 trimApplications();
10582
10583 Binder.restoreCallingIdentity(origId);
10584 }
10585
Jeff Brown4d94a762010-09-23 11:33:28 -070010586 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010587 if (r.nextReceiver > 0) {
10588 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10589 if (curReceiver instanceof BroadcastFilter) {
10590 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080010591 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 System.identityHashCode(r),
10593 r.intent.getAction(),
10594 r.nextReceiver - 1,
10595 System.identityHashCode(bf));
10596 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080010597 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010598 System.identityHashCode(r),
10599 r.intent.getAction(),
10600 r.nextReceiver - 1,
10601 ((ResolveInfo)curReceiver).toString());
10602 }
10603 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010604 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010605 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010606 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010607 System.identityHashCode(r),
10608 r.intent.getAction(),
10609 r.nextReceiver,
10610 "NONE");
10611 }
10612 }
10613
Jeff Brown4d94a762010-09-23 11:33:28 -070010614 private final void setBroadcastTimeoutLocked(long timeoutTime) {
10615 if (! mPendingBroadcastTimeoutMessage) {
10616 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
10617 mHandler.sendMessageAtTime(msg, timeoutTime);
10618 mPendingBroadcastTimeoutMessage = true;
10619 }
10620 }
10621
10622 private final void cancelBroadcastTimeoutLocked() {
10623 if (mPendingBroadcastTimeoutMessage) {
10624 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
10625 mPendingBroadcastTimeoutMessage = false;
10626 }
10627 }
10628
10629 private final void broadcastTimeoutLocked(boolean fromMsg) {
10630 if (fromMsg) {
10631 mPendingBroadcastTimeoutMessage = false;
10632 }
10633
10634 if (mOrderedBroadcasts.size() == 0) {
10635 return;
10636 }
10637
10638 long now = SystemClock.uptimeMillis();
10639 BroadcastRecord r = mOrderedBroadcasts.get(0);
10640 if (fromMsg) {
10641 if (mDidDexOpt) {
10642 // Delay timeouts until dexopt finishes.
10643 mDidDexOpt = false;
10644 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
10645 setBroadcastTimeoutLocked(timeoutTime);
10646 return;
10647 }
10648 if (! mProcessesReady) {
10649 // Only process broadcast timeouts if the system is ready. That way
10650 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
10651 // to do heavy lifting for system up.
10652 return;
10653 }
10654
10655 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
10656 if (timeoutTime > now) {
10657 // We can observe premature timeouts because we do not cancel and reset the
10658 // broadcast timeout message after each receiver finishes. Instead, we set up
10659 // an initial timeout then kick it down the road a little further as needed
10660 // when it expires.
10661 if (DEBUG_BROADCAST) Slog.v(TAG,
10662 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
10663 + timeoutTime);
10664 setBroadcastTimeoutLocked(timeoutTime);
10665 return;
10666 }
10667 }
10668
10669 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
10670 + ", started " + (now - r.receiverTime) + "ms ago");
10671 r.receiverTime = now;
10672 r.anrCount++;
10673
10674 // Current receiver has passed its expiration date.
10675 if (r.nextReceiver <= 0) {
10676 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
10677 return;
10678 }
10679
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010680 ProcessRecord app = null;
10681 String anrMessage = null;
10682
Jeff Brown4d94a762010-09-23 11:33:28 -070010683 Object curReceiver = r.receivers.get(r.nextReceiver-1);
10684 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
10685 logBroadcastReceiverDiscardLocked(r);
10686 if (curReceiver instanceof BroadcastFilter) {
10687 BroadcastFilter bf = (BroadcastFilter)curReceiver;
10688 if (bf.receiverList.pid != 0
10689 && bf.receiverList.pid != MY_PID) {
10690 synchronized (this.mPidsSelfLocked) {
10691 app = this.mPidsSelfLocked.get(
10692 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010694 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010695 } else {
10696 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010697 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010698
Jeff Brown4d94a762010-09-23 11:33:28 -070010699 if (app != null) {
10700 anrMessage = "Broadcast of " + r.intent.toString();
10701 }
10702
10703 if (mPendingBroadcast == r) {
10704 mPendingBroadcast = null;
10705 }
10706
10707 // Move on to the next receiver.
10708 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
10709 r.resultExtras, r.resultAbort, true);
10710 scheduleBroadcastsLocked();
10711
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010712 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070010713 // Post the ANR to the handler since we do not want to process ANRs while
10714 // potentially holding our lock.
10715 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010717 }
10718
10719 private final void processCurBroadcastLocked(BroadcastRecord r,
10720 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010721 if (DEBUG_BROADCAST) Slog.v(TAG,
10722 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010723 if (app.thread == null) {
10724 throw new RemoteException();
10725 }
10726 r.receiver = app.thread.asBinder();
10727 r.curApp = app;
10728 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010729 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010730
10731 // Tell the application to launch this receiver.
10732 r.intent.setComponent(r.curComponent);
10733
10734 boolean started = false;
10735 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010736 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010737 "Delivering to component " + r.curComponent
10738 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010739 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010740 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
10741 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010742 if (DEBUG_BROADCAST) Slog.v(TAG,
10743 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010744 started = true;
10745 } finally {
10746 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010747 if (DEBUG_BROADCAST) Slog.v(TAG,
10748 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010749 r.receiver = null;
10750 r.curApp = null;
10751 app.curReceiver = null;
10752 }
10753 }
10754
10755 }
10756
Jeff Brown4d94a762010-09-23 11:33:28 -070010757 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010758 Intent intent, int resultCode, String data, Bundle extras,
10759 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070010760 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 if (app != null && app.thread != null) {
10762 // If we have an app thread, do the call through that so it is
10763 // correctly ordered with other one-way calls.
10764 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010765 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010766 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010767 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768 }
10769 }
10770
Jeff Brown4d94a762010-09-23 11:33:28 -070010771 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 BroadcastFilter filter, boolean ordered) {
10773 boolean skip = false;
10774 if (filter.requiredPermission != null) {
10775 int perm = checkComponentPermission(filter.requiredPermission,
10776 r.callingPid, r.callingUid, -1);
10777 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010778 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010779 + r.intent.toString()
10780 + " from " + r.callerPackage + " (pid="
10781 + r.callingPid + ", uid=" + r.callingUid + ")"
10782 + " requires " + filter.requiredPermission
10783 + " due to registered receiver " + filter);
10784 skip = true;
10785 }
10786 }
10787 if (r.requiredPermission != null) {
10788 int perm = checkComponentPermission(r.requiredPermission,
10789 filter.receiverList.pid, filter.receiverList.uid, -1);
10790 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010791 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010792 + r.intent.toString()
10793 + " to " + filter.receiverList.app
10794 + " (pid=" + filter.receiverList.pid
10795 + ", uid=" + filter.receiverList.uid + ")"
10796 + " requires " + r.requiredPermission
10797 + " due to sender " + r.callerPackage
10798 + " (uid " + r.callingUid + ")");
10799 skip = true;
10800 }
10801 }
10802
10803 if (!skip) {
10804 // If this is not being sent as an ordered broadcast, then we
10805 // don't want to touch the fields that keep track of the current
10806 // state of ordered broadcasts.
10807 if (ordered) {
10808 r.receiver = filter.receiverList.receiver.asBinder();
10809 r.curFilter = filter;
10810 filter.receiverList.curBroadcast = r;
10811 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010812 if (filter.receiverList.app != null) {
10813 // Bump hosting application to no longer be in background
10814 // scheduling class. Note that we can't do that if there
10815 // isn't an app... but we can only be in that case for
10816 // things that directly call the IActivityManager API, which
10817 // are already core system stuff so don't matter for this.
10818 r.curApp = filter.receiverList.app;
10819 filter.receiverList.app.curReceiver = r;
10820 updateOomAdjLocked();
10821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 }
10823 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010824 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010825 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010826 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010827 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010828 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010829 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010831 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010832 if (ordered) {
10833 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
10834 }
10835 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010836 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010837 if (ordered) {
10838 r.receiver = null;
10839 r.curFilter = null;
10840 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010841 if (filter.receiverList.app != null) {
10842 filter.receiverList.app.curReceiver = null;
10843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 }
10845 }
10846 }
10847 }
10848
Dianne Hackborn12527f92009-11-11 17:39:50 -080010849 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
10850 if (r.callingUid < 0) {
10851 // This was from a registerReceiver() call; ignore it.
10852 return;
10853 }
10854 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
10855 MAX_BROADCAST_HISTORY-1);
10856 r.finishTime = SystemClock.uptimeMillis();
10857 mBroadcastHistory[0] = r;
10858 }
10859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010860 private final void processNextBroadcast(boolean fromMsg) {
10861 synchronized(this) {
10862 BroadcastRecord r;
10863
Joe Onorato8a9b2202010-02-26 18:56:32 -080010864 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010865 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010866 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010867
10868 updateCpuStats();
10869
10870 if (fromMsg) {
10871 mBroadcastsScheduled = false;
10872 }
10873
10874 // First, deliver any non-serialized broadcasts right away.
10875 while (mParallelBroadcasts.size() > 0) {
10876 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080010877 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010878 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010879 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010880 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010881 for (int i=0; i<N; i++) {
10882 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010883 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010884 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010885 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070010886 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010887 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080010888 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010889 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010890 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010891 }
10892
10893 // Now take care of the next serialized one...
10894
10895 // If we are waiting for a process to come up to handle the next
10896 // broadcast, then do nothing at this point. Just in case, we
10897 // check that the process we're waiting for still exists.
10898 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010899 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010900 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070010901 + mPendingBroadcast.curApp);
10902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010903
10904 boolean isDead;
10905 synchronized (mPidsSelfLocked) {
10906 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
10907 }
10908 if (!isDead) {
10909 // It's still alive, so keep waiting
10910 return;
10911 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010912 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010914 mPendingBroadcast.state = BroadcastRecord.IDLE;
10915 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010916 mPendingBroadcast = null;
10917 }
10918 }
10919
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010920 boolean looped = false;
10921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010922 do {
10923 if (mOrderedBroadcasts.size() == 0) {
10924 // No more broadcasts pending, so all done!
10925 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010926 if (looped) {
10927 // If we had finished the last ordered broadcast, then
10928 // make sure all processes have correct oom and sched
10929 // adjustments.
10930 updateOomAdjLocked();
10931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010932 return;
10933 }
10934 r = mOrderedBroadcasts.get(0);
10935 boolean forceReceive = false;
10936
10937 // Ensure that even if something goes awry with the timeout
10938 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010939 // and continue to make progress.
10940 //
10941 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070010942 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010943 // one time heavy lifting after system upgrades and can take
10944 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010945 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010946 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050010947 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 if ((numReceivers > 0) &&
10949 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010950 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 + " now=" + now
10952 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080010953 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 + " intent=" + r.intent
10955 + " numReceivers=" + numReceivers
10956 + " nextReceiver=" + r.nextReceiver
10957 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070010958 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010959 forceReceive = true;
10960 r.state = BroadcastRecord.IDLE;
10961 }
10962 }
10963
10964 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010965 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 "processNextBroadcast() called when not idle (state="
10967 + r.state + ")");
10968 return;
10969 }
10970
10971 if (r.receivers == null || r.nextReceiver >= numReceivers
10972 || r.resultAbort || forceReceive) {
10973 // No more receivers for this broadcast! Send the final
10974 // result if requested...
10975 if (r.resultTo != null) {
10976 try {
10977 if (DEBUG_BROADCAST) {
10978 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010979 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 + " seq=" + seq + " app=" + r.callerApp);
10981 }
Jeff Brown4d94a762010-09-23 11:33:28 -070010982 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010983 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070010984 r.resultData, r.resultExtras, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010986 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987 }
10988 }
10989
Joe Onorato8a9b2202010-02-26 18:56:32 -080010990 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070010991 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992
Joe Onorato8a9b2202010-02-26 18:56:32 -080010993 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070010994 + r);
10995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080010997 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998 mOrderedBroadcasts.remove(0);
10999 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011000 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011001 continue;
11002 }
11003 } while (r == null);
11004
11005 // Get the next receiver...
11006 int recIdx = r.nextReceiver++;
11007
11008 // Keep track of when this receiver started, and make sure there
11009 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011010 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011011 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011012 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013
Joe Onorato8a9b2202010-02-26 18:56:32 -080011014 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011015 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011016 }
11017 if (! mPendingBroadcastTimeoutMessage) {
11018 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011019 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011020 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11021 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011022 }
11023
11024 Object nextReceiver = r.receivers.get(recIdx);
11025 if (nextReceiver instanceof BroadcastFilter) {
11026 // Simple case: this is a registered receiver who gets
11027 // a direct call.
11028 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011029 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011030 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011031 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011032 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 if (r.receiver == null || !r.ordered) {
11034 // The receiver has already finished, so schedule to
11035 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011036 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11037 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011038 r.state = BroadcastRecord.IDLE;
11039 scheduleBroadcastsLocked();
11040 }
11041 return;
11042 }
11043
11044 // Hard case: need to instantiate the receiver, possibly
11045 // starting its application process to host it.
11046
11047 ResolveInfo info =
11048 (ResolveInfo)nextReceiver;
11049
11050 boolean skip = false;
11051 int perm = checkComponentPermission(info.activityInfo.permission,
11052 r.callingPid, r.callingUid,
11053 info.activityInfo.exported
11054 ? -1 : info.activityInfo.applicationInfo.uid);
11055 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011056 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 + r.intent.toString()
11058 + " from " + r.callerPackage + " (pid=" + r.callingPid
11059 + ", uid=" + r.callingUid + ")"
11060 + " requires " + info.activityInfo.permission
11061 + " due to receiver " + info.activityInfo.packageName
11062 + "/" + info.activityInfo.name);
11063 skip = true;
11064 }
11065 if (r.callingUid != Process.SYSTEM_UID &&
11066 r.requiredPermission != null) {
11067 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011068 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011069 checkPermission(r.requiredPermission,
11070 info.activityInfo.applicationInfo.packageName);
11071 } catch (RemoteException e) {
11072 perm = PackageManager.PERMISSION_DENIED;
11073 }
11074 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011075 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011076 + r.intent + " to "
11077 + info.activityInfo.applicationInfo.packageName
11078 + " requires " + r.requiredPermission
11079 + " due to sender " + r.callerPackage
11080 + " (uid " + r.callingUid + ")");
11081 skip = true;
11082 }
11083 }
11084 if (r.curApp != null && r.curApp.crashing) {
11085 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011086 if (DEBUG_BROADCAST) Slog.v(TAG,
11087 "Skipping deliver ordered " + r + " to " + r.curApp
11088 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 skip = true;
11090 }
11091
11092 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011093 if (DEBUG_BROADCAST) Slog.v(TAG,
11094 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011095 r.receiver = null;
11096 r.curFilter = null;
11097 r.state = BroadcastRecord.IDLE;
11098 scheduleBroadcastsLocked();
11099 return;
11100 }
11101
11102 r.state = BroadcastRecord.APP_RECEIVE;
11103 String targetProcess = info.activityInfo.processName;
11104 r.curComponent = new ComponentName(
11105 info.activityInfo.applicationInfo.packageName,
11106 info.activityInfo.name);
11107 r.curReceiver = info.activityInfo;
11108
11109 // Is this receiver's application already running?
11110 ProcessRecord app = getProcessRecordLocked(targetProcess,
11111 info.activityInfo.applicationInfo.uid);
11112 if (app != null && app.thread != null) {
11113 try {
11114 processCurBroadcastLocked(r, app);
11115 return;
11116 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011117 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118 + r.curComponent, e);
11119 }
11120
11121 // If a dead object exception was thrown -- fall through to
11122 // restart the application.
11123 }
11124
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011125 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011126 if (DEBUG_BROADCAST) Slog.v(TAG,
11127 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 if ((r.curApp=startProcessLocked(targetProcess,
11129 info.activityInfo.applicationInfo, true,
11130 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011131 "broadcast", r.curComponent,
11132 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11133 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 // Ah, this recipient is unavailable. Finish it if necessary,
11135 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011136 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 + info.activityInfo.applicationInfo.packageName + "/"
11138 + info.activityInfo.applicationInfo.uid + " for broadcast "
11139 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011140 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11142 r.resultExtras, r.resultAbort, true);
11143 scheduleBroadcastsLocked();
11144 r.state = BroadcastRecord.IDLE;
11145 return;
11146 }
11147
11148 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011149 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 }
11151 }
11152
11153 // =========================================================
11154 // INSTRUMENTATION
11155 // =========================================================
11156
11157 public boolean startInstrumentation(ComponentName className,
11158 String profileFile, int flags, Bundle arguments,
11159 IInstrumentationWatcher watcher) {
11160 // Refuse possible leaked file descriptors
11161 if (arguments != null && arguments.hasFileDescriptors()) {
11162 throw new IllegalArgumentException("File descriptors passed in Bundle");
11163 }
11164
11165 synchronized(this) {
11166 InstrumentationInfo ii = null;
11167 ApplicationInfo ai = null;
11168 try {
11169 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011170 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011172 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 } catch (PackageManager.NameNotFoundException e) {
11174 }
11175 if (ii == null) {
11176 reportStartInstrumentationFailure(watcher, className,
11177 "Unable to find instrumentation info for: " + className);
11178 return false;
11179 }
11180 if (ai == null) {
11181 reportStartInstrumentationFailure(watcher, className,
11182 "Unable to find instrumentation target package: " + ii.targetPackage);
11183 return false;
11184 }
11185
11186 int match = mContext.getPackageManager().checkSignatures(
11187 ii.targetPackage, ii.packageName);
11188 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11189 String msg = "Permission Denial: starting instrumentation "
11190 + className + " from pid="
11191 + Binder.getCallingPid()
11192 + ", uid=" + Binder.getCallingPid()
11193 + " not allowed because package " + ii.packageName
11194 + " does not have a signature matching the target "
11195 + ii.targetPackage;
11196 reportStartInstrumentationFailure(watcher, className, msg);
11197 throw new SecurityException(msg);
11198 }
11199
11200 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011201 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 ProcessRecord app = addAppLocked(ai);
11203 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011204 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011205 app.instrumentationProfileFile = profileFile;
11206 app.instrumentationArguments = arguments;
11207 app.instrumentationWatcher = watcher;
11208 app.instrumentationResultClass = className;
11209 Binder.restoreCallingIdentity(origId);
11210 }
11211
11212 return true;
11213 }
11214
11215 /**
11216 * Report errors that occur while attempting to start Instrumentation. Always writes the
11217 * error to the logs, but if somebody is watching, send the report there too. This enables
11218 * the "am" command to report errors with more information.
11219 *
11220 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11221 * @param cn The component name of the instrumentation.
11222 * @param report The error report.
11223 */
11224 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11225 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011226 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 try {
11228 if (watcher != null) {
11229 Bundle results = new Bundle();
11230 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11231 results.putString("Error", report);
11232 watcher.instrumentationStatus(cn, -1, results);
11233 }
11234 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011235 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011236 }
11237 }
11238
11239 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11240 if (app.instrumentationWatcher != null) {
11241 try {
11242 // NOTE: IInstrumentationWatcher *must* be oneway here
11243 app.instrumentationWatcher.instrumentationFinished(
11244 app.instrumentationClass,
11245 resultCode,
11246 results);
11247 } catch (RemoteException e) {
11248 }
11249 }
11250 app.instrumentationWatcher = null;
11251 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011252 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011253 app.instrumentationProfileFile = null;
11254 app.instrumentationArguments = null;
11255
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011256 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011257 }
11258
11259 public void finishInstrumentation(IApplicationThread target,
11260 int resultCode, Bundle results) {
11261 // Refuse possible leaked file descriptors
11262 if (results != null && results.hasFileDescriptors()) {
11263 throw new IllegalArgumentException("File descriptors passed in Intent");
11264 }
11265
11266 synchronized(this) {
11267 ProcessRecord app = getRecordForAppLocked(target);
11268 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011269 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011270 return;
11271 }
11272 final long origId = Binder.clearCallingIdentity();
11273 finishInstrumentationLocked(app, resultCode, results);
11274 Binder.restoreCallingIdentity(origId);
11275 }
11276 }
11277
11278 // =========================================================
11279 // CONFIGURATION
11280 // =========================================================
11281
11282 public ConfigurationInfo getDeviceConfigurationInfo() {
11283 ConfigurationInfo config = new ConfigurationInfo();
11284 synchronized (this) {
11285 config.reqTouchScreen = mConfiguration.touchscreen;
11286 config.reqKeyboardType = mConfiguration.keyboard;
11287 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011288 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11289 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011290 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11291 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011292 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11293 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011294 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11295 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011296 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011297 }
11298 return config;
11299 }
11300
11301 public Configuration getConfiguration() {
11302 Configuration ci;
11303 synchronized(this) {
11304 ci = new Configuration(mConfiguration);
11305 }
11306 return ci;
11307 }
11308
11309 public void updateConfiguration(Configuration values) {
11310 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11311 "updateConfiguration()");
11312
11313 synchronized(this) {
11314 if (values == null && mWindowManager != null) {
11315 // sentinel: fetch the current configuration from the window manager
11316 values = mWindowManager.computeNewConfiguration();
11317 }
11318
11319 final long origId = Binder.clearCallingIdentity();
11320 updateConfigurationLocked(values, null);
11321 Binder.restoreCallingIdentity(origId);
11322 }
11323 }
11324
11325 /**
11326 * Do either or both things: (1) change the current configuration, and (2)
11327 * make sure the given activity is running with the (now) current
11328 * configuration. Returns true if the activity has been left running, or
11329 * false if <var>starting</var> is being destroyed to match the new
11330 * configuration.
11331 */
11332 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011333 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011334 int changes = 0;
11335
11336 boolean kept = true;
11337
11338 if (values != null) {
11339 Configuration newConfig = new Configuration(mConfiguration);
11340 changes = newConfig.updateFrom(values);
11341 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011342 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011343 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011344 }
11345
Doug Zongker2bec3d42009-12-04 12:52:44 -080011346 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347
11348 if (values.locale != null) {
11349 saveLocaleLocked(values.locale,
11350 !values.locale.equals(mConfiguration.locale),
11351 values.userSetLocale);
11352 }
11353
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011354 mConfigurationSeq++;
11355 if (mConfigurationSeq <= 0) {
11356 mConfigurationSeq = 1;
11357 }
11358 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011359 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011360 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011361
11362 AttributeCache ac = AttributeCache.instance();
11363 if (ac != null) {
11364 ac.updateConfiguration(mConfiguration);
11365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011366
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011367 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11368 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11369 msg.obj = new Configuration(mConfiguration);
11370 mHandler.sendMessage(msg);
11371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011372
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011373 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11374 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011375 try {
11376 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011377 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011378 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011379 app.thread.scheduleConfigurationChanged(mConfiguration);
11380 }
11381 } catch (Exception e) {
11382 }
11383 }
11384 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011385 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11386 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11388 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011389 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11390 broadcastIntentLocked(null, null,
11391 new Intent(Intent.ACTION_LOCALE_CHANGED),
11392 null, null, 0, null, null,
11393 null, false, false, MY_PID, Process.SYSTEM_UID);
11394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011395 }
11396 }
11397
11398 if (changes != 0 && starting == null) {
11399 // If the configuration changed, and the caller is not already
11400 // in the process of starting an activity, then find the top
11401 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011402 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403 }
11404
11405 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011406 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011407 if (kept) {
11408 // If this didn't result in the starting activity being
11409 // destroyed, then we need to make sure at this point that all
11410 // other activities are made visible.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011411 if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011412 + ", ensuring others are correct.");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011413 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 }
11415 }
11416
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011417 if (values != null && mWindowManager != null) {
11418 mWindowManager.setNewConfiguration(mConfiguration);
11419 }
11420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011421 return kept;
11422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011423
11424 /**
11425 * Save the locale. You must be inside a synchronized (this) block.
11426 */
11427 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11428 if(isDiff) {
11429 SystemProperties.set("user.language", l.getLanguage());
11430 SystemProperties.set("user.region", l.getCountry());
11431 }
11432
11433 if(isPersist) {
11434 SystemProperties.set("persist.sys.language", l.getLanguage());
11435 SystemProperties.set("persist.sys.country", l.getCountry());
11436 SystemProperties.set("persist.sys.localevar", l.getVariant());
11437 }
11438 }
11439
11440 // =========================================================
11441 // LIFETIME MANAGEMENT
11442 // =========================================================
11443
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011444 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11445 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011447 // This adjustment has already been computed. If we are calling
11448 // from the top, we may have already computed our adjustment with
11449 // an earlier hidden adjustment that isn't really for us... if
11450 // so, use the new hidden adjustment.
11451 if (!recursed && app.hidden) {
11452 app.curAdj = hiddenAdj;
11453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011454 return app.curAdj;
11455 }
11456
11457 if (app.thread == null) {
11458 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011459 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011460 return (app.curAdj=EMPTY_APP_ADJ);
11461 }
11462
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011463 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11464 // The max adjustment doesn't allow this app to be anything
11465 // below foreground, so it is not worth doing work for it.
11466 app.adjType = "fixed";
11467 app.adjSeq = mAdjSeq;
11468 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011469 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011470 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
11471 return (app.curAdj=app.maxAdj);
11472 }
11473
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011474 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011475 app.adjSource = null;
11476 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011477 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011478 app.empty = false;
11479 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011480
The Android Open Source Project4df24232009-03-05 14:34:35 -080011481 // Determine the importance of the process, starting with most
11482 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011483 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011484 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011486 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011487 // The last app on the list is the foreground app.
11488 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011489 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011490 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011491 } else if (app.instrumentationClass != null) {
11492 // Don't want to kill running instrumentation.
11493 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011494 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011495 app.adjType = "instrumentation";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011496 } else if (app.persistentActivities > 0) {
11497 // Special persistent activities... shouldn't be used these days.
11498 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011499 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011500 app.adjType = "persistent";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011501 } else if (app.curReceiver != null ||
11502 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11503 // An app that is currently receiving a broadcast also
11504 // counts as being in the foreground.
11505 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011506 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011507 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011508 } else if (app.executingServices.size() > 0) {
11509 // An app that is currently executing a service callback also
11510 // counts as being in the foreground.
11511 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011512 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011513 app.adjType = "exec-service";
11514 } else if (app.foregroundServices) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011515 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011516 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011517 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011518 app.adjType = "foreground-service";
11519 } else if (app.forcingToForeground != null) {
11520 // The user is aware of this app, so make it visible.
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011521 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011522 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011523 app.adjType = "force-foreground";
11524 app.adjSource = app.forcingToForeground;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011525 } else if (app == mHeavyWeightProcess) {
11526 // We don't want to kill the current heavy-weight process.
11527 adj = HEAVY_WEIGHT_APP_ADJ;
11528 schedGroup = Process.THREAD_GROUP_DEFAULT;
11529 app.adjType = "heavy";
The Android Open Source Project4df24232009-03-05 14:34:35 -080011530 } else if (app == mHomeProcess) {
11531 // This process is hosting what we currently consider to be the
11532 // home app, so we don't want to let it go into the background.
11533 adj = HOME_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011534 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011535 app.adjType = "home";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 } else if ((N=app.activities.size()) != 0) {
11537 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011538 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011539 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011540 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011541 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011542 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011543 for (int j=0; j<N; j++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011544 if (app.activities.get(j).visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011546 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011548 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011549 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011550 break;
11551 }
11552 }
11553 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011554 // A very not-needed process. If this is lower in the lru list,
11555 // we will push it in to the empty bucket.
11556 app.hidden = true;
11557 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011558 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011559 adj = hiddenAdj;
11560 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011561 }
11562
Joe Onorato8a9b2202010-02-26 18:56:32 -080011563 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011564
The Android Open Source Project4df24232009-03-05 14:34:35 -080011565 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566 // there are applications dependent on our services or providers, but
11567 // this gives us a baseline and makes sure we don't get into an
11568 // infinite recursion.
11569 app.adjSeq = mAdjSeq;
11570 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011571
Christopher Tate6fa95972009-06-05 18:43:55 -070011572 if (mBackupTarget != null && app == mBackupTarget.app) {
11573 // If possible we want to avoid killing apps while they're being backed up
11574 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011575 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070011576 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011577 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011578 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070011579 }
11580 }
11581
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011582 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11583 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011584 final long now = SystemClock.uptimeMillis();
11585 // This process is more important if the top activity is
11586 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070011587 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011589 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011590 if (s.startRequested) {
11591 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
11592 // This service has seen some activity within
11593 // recent memory, so we will keep its process ahead
11594 // of the background processes.
11595 if (adj > SECONDARY_SERVER_ADJ) {
11596 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011597 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011598 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599 }
11600 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080011601 // If we have let the service slide into the background
11602 // state, still have some text describing what it is doing
11603 // even though the service no longer has an impact.
11604 if (adj > SECONDARY_SERVER_ADJ) {
11605 app.adjType = "started-bg-services";
11606 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011607 // Don't kill this process because it is doing work; it
11608 // has said it is doing work.
11609 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011610 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011611 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
11612 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011613 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011614 = s.connections.values().iterator();
11615 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011616 ArrayList<ConnectionRecord> clist = kt.next();
11617 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
11618 // XXX should compute this based on the max of
11619 // all connected clients.
11620 ConnectionRecord cr = clist.get(i);
11621 if (cr.binding.client == app) {
11622 // Binding to ourself is not interesting.
11623 continue;
11624 }
11625 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
11626 ProcessRecord client = cr.binding.client;
11627 int myHiddenAdj = hiddenAdj;
11628 if (myHiddenAdj > client.hiddenAdj) {
11629 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
11630 myHiddenAdj = client.hiddenAdj;
11631 } else {
11632 myHiddenAdj = VISIBLE_APP_ADJ;
11633 }
11634 }
11635 int clientAdj = computeOomAdjLocked(
11636 client, myHiddenAdj, TOP_APP, true);
11637 if (adj > clientAdj) {
11638 adj = clientAdj >= VISIBLE_APP_ADJ
11639 ? clientAdj : VISIBLE_APP_ADJ;
11640 if (!client.hidden) {
11641 app.hidden = false;
11642 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011643 if (client.keeping) {
11644 app.keeping = true;
11645 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011646 app.adjType = "service";
11647 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11648 .REASON_SERVICE_IN_USE;
11649 app.adjSource = cr.binding.client;
11650 app.adjTarget = s.name;
11651 }
11652 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
11653 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11654 schedGroup = Process.THREAD_GROUP_DEFAULT;
11655 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011656 }
11657 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011658 ActivityRecord a = cr.activity;
11659 //if (a != null) {
11660 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
11661 //}
11662 if (a != null && adj > FOREGROUND_APP_ADJ &&
11663 (a.state == ActivityState.RESUMED
11664 || a.state == ActivityState.PAUSING)) {
11665 adj = FOREGROUND_APP_ADJ;
11666 schedGroup = Process.THREAD_GROUP_DEFAULT;
11667 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011668 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011669 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11670 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011671 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011672 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011674 }
11675 }
11676 }
11677 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011678
Dianne Hackborn287952c2010-09-22 22:34:31 -070011679 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011680 // would like to avoid killing it unless it would prevent the current
11681 // application from running. By default we put the process in
11682 // with the rest of the background processes; as we scan through
11683 // its services we may bump it up from there.
11684 if (adj > hiddenAdj) {
11685 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011686 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070011687 app.adjType = "bg-services";
11688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 }
11690
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011691 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
11692 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011693 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011694 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
11695 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070011696 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011697 if (cpr.clients.size() != 0) {
11698 Iterator<ProcessRecord> kt = cpr.clients.iterator();
11699 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11700 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070011701 if (client == app) {
11702 // Being our own client is not interesting.
11703 continue;
11704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011705 int myHiddenAdj = hiddenAdj;
11706 if (myHiddenAdj > client.hiddenAdj) {
11707 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
11708 myHiddenAdj = client.hiddenAdj;
11709 } else {
11710 myHiddenAdj = FOREGROUND_APP_ADJ;
11711 }
11712 }
11713 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011714 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011715 if (adj > clientAdj) {
11716 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011717 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011718 if (!client.hidden) {
11719 app.hidden = false;
11720 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011721 if (client.keeping) {
11722 app.keeping = true;
11723 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011724 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011725 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
11726 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011727 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011728 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011729 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011730 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
11731 schedGroup = Process.THREAD_GROUP_DEFAULT;
11732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011733 }
11734 }
11735 // If the provider has external (non-framework) process
11736 // dependencies, ensure that its adjustment is at least
11737 // FOREGROUND_APP_ADJ.
11738 if (cpr.externals != 0) {
11739 if (adj > FOREGROUND_APP_ADJ) {
11740 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011741 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011742 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011743 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011744 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070011745 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011746 }
11747 }
11748 }
11749 }
11750
11751 app.curRawAdj = adj;
11752
Joe Onorato8a9b2202010-02-26 18:56:32 -080011753 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011754 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
11755 if (adj > app.maxAdj) {
11756 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011757 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011758 schedGroup = Process.THREAD_GROUP_DEFAULT;
11759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011760 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011761 if (adj < HIDDEN_APP_MIN_ADJ) {
11762 app.keeping = true;
11763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011764
11765 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011766 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070011767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011768 return adj;
11769 }
11770
11771 /**
11772 * Ask a given process to GC right now.
11773 */
11774 final void performAppGcLocked(ProcessRecord app) {
11775 try {
11776 app.lastRequestedGc = SystemClock.uptimeMillis();
11777 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011778 if (app.reportLowMemory) {
11779 app.reportLowMemory = false;
11780 app.thread.scheduleLowMemory();
11781 } else {
11782 app.thread.processInBackground();
11783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011784 }
11785 } catch (Exception e) {
11786 // whatever.
11787 }
11788 }
11789
11790 /**
11791 * Returns true if things are idle enough to perform GCs.
11792 */
Josh Bartel7f208742010-02-25 11:01:44 -060011793 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011794 return mParallelBroadcasts.size() == 0
11795 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011796 && (mSleeping || (mMainStack.mResumedActivity != null &&
11797 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798 }
11799
11800 /**
11801 * Perform GCs on all processes that are waiting for it, but only
11802 * if things are idle.
11803 */
11804 final void performAppGcsLocked() {
11805 final int N = mProcessesToGc.size();
11806 if (N <= 0) {
11807 return;
11808 }
Josh Bartel7f208742010-02-25 11:01:44 -060011809 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011810 while (mProcessesToGc.size() > 0) {
11811 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070011812 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011813 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
11814 <= SystemClock.uptimeMillis()) {
11815 // To avoid spamming the system, we will GC processes one
11816 // at a time, waiting a few seconds between each.
11817 performAppGcLocked(proc);
11818 scheduleAppGcsLocked();
11819 return;
11820 } else {
11821 // It hasn't been long enough since we last GCed this
11822 // process... put it in the list to wait for its time.
11823 addProcessToGcListLocked(proc);
11824 break;
11825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826 }
11827 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011828
11829 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011830 }
11831 }
11832
11833 /**
11834 * If all looks good, perform GCs on all processes waiting for them.
11835 */
11836 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060011837 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011838 performAppGcsLocked();
11839 return;
11840 }
11841 // Still not idle, wait some more.
11842 scheduleAppGcsLocked();
11843 }
11844
11845 /**
11846 * Schedule the execution of all pending app GCs.
11847 */
11848 final void scheduleAppGcsLocked() {
11849 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011850
11851 if (mProcessesToGc.size() > 0) {
11852 // Schedule a GC for the time to the next process.
11853 ProcessRecord proc = mProcessesToGc.get(0);
11854 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11855
11856 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
11857 long now = SystemClock.uptimeMillis();
11858 if (when < (now+GC_TIMEOUT)) {
11859 when = now + GC_TIMEOUT;
11860 }
11861 mHandler.sendMessageAtTime(msg, when);
11862 }
11863 }
11864
11865 /**
11866 * Add a process to the array of processes waiting to be GCed. Keeps the
11867 * list in sorted order by the last GC time. The process can't already be
11868 * on the list.
11869 */
11870 final void addProcessToGcListLocked(ProcessRecord proc) {
11871 boolean added = false;
11872 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11873 if (mProcessesToGc.get(i).lastRequestedGc <
11874 proc.lastRequestedGc) {
11875 added = true;
11876 mProcessesToGc.add(i+1, proc);
11877 break;
11878 }
11879 }
11880 if (!added) {
11881 mProcessesToGc.add(0, proc);
11882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011883 }
11884
11885 /**
11886 * Set up to ask a process to GC itself. This will either do it
11887 * immediately, or put it on the list of processes to gc the next
11888 * time things are idle.
11889 */
11890 final void scheduleAppGcLocked(ProcessRecord app) {
11891 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011892 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011893 return;
11894 }
11895 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070011896 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011897 scheduleAppGcsLocked();
11898 }
11899 }
11900
Dianne Hackborn287952c2010-09-22 22:34:31 -070011901 final void checkExcessivePowerUsageLocked(boolean doKills) {
11902 updateCpuStatsNow();
11903
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011904 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011905 boolean doWakeKills = doKills;
11906 boolean doCpuKills = doKills;
11907 if (mLastPowerCheckRealtime == 0) {
11908 doWakeKills = false;
11909 }
11910 if (mLastPowerCheckUptime == 0) {
11911 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011912 }
11913 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011914 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011915 }
11916 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070011917 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
11918 final long curUptime = SystemClock.uptimeMillis();
11919 final long uptimeSince = curUptime - mLastPowerCheckUptime;
11920 mLastPowerCheckRealtime = curRealtime;
11921 mLastPowerCheckUptime = curUptime;
11922 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
11923 doWakeKills = false;
11924 }
11925 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
11926 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011927 }
11928 int i = mLruProcesses.size();
11929 while (i > 0) {
11930 i--;
11931 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011932 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011933 long wtime;
11934 synchronized (stats) {
11935 wtime = stats.getProcessWakeTime(app.info.uid,
11936 app.pid, curRealtime);
11937 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070011938 long wtimeUsed = wtime - app.lastWakeTime;
11939 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
11940 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011941 StringBuilder sb = new StringBuilder(128);
11942 sb.append("Wake for ");
11943 app.toShortString(sb);
11944 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011945 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011946 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011947 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011948 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070011949 sb.append((wtimeUsed*100)/realtimeSince);
11950 sb.append("%)");
11951 Slog.i(TAG, sb.toString());
11952 sb.setLength(0);
11953 sb.append("CPU for ");
11954 app.toShortString(sb);
11955 sb.append(": over ");
11956 TimeUtils.formatDuration(uptimeSince, sb);
11957 sb.append(" used ");
11958 TimeUtils.formatDuration(cputimeUsed, sb);
11959 sb.append(" (");
11960 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070011961 sb.append("%)");
11962 Slog.i(TAG, sb.toString());
11963 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011964 // If a process has held a wake lock for more
11965 // than 50% of the time during this period,
11966 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070011967 if (doWakeKills && realtimeSince > 0
11968 && ((wtimeUsed*100)/realtimeSince) >= 50) {
11969 synchronized (stats) {
11970 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
11971 realtimeSince, wtimeUsed);
11972 }
11973 Slog.w(TAG, "Excessive wake lock in " + app.processName
11974 + " (pid " + app.pid + "): held " + wtimeUsed
11975 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011976 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11977 app.processName, app.setAdj, "excessive wake lock");
11978 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011979 } else if (doCpuKills && uptimeSince > 0
11980 && ((cputimeUsed*100)/uptimeSince) >= 50) {
11981 synchronized (stats) {
11982 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
11983 uptimeSince, cputimeUsed);
11984 }
11985 Slog.w(TAG, "Excessive CPU in " + app.processName
11986 + " (pid " + app.pid + "): used " + cputimeUsed
11987 + " during " + uptimeSince);
11988 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
11989 app.processName, app.setAdj, "excessive cpu");
11990 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011991 } else {
11992 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070011993 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070011994 }
11995 }
11996 }
11997 }
11998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011999 private final boolean updateOomAdjLocked(
12000 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12001 app.hiddenAdj = hiddenAdj;
12002
12003 if (app.thread == null) {
12004 return true;
12005 }
12006
Dianne Hackborn287952c2010-09-22 22:34:31 -070012007 final boolean wasKeeping = app.keeping;
12008
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012009 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012010
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012011 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 if (app.curRawAdj != app.setRawAdj) {
12013 if (app.curRawAdj > FOREGROUND_APP_ADJ
12014 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12015 // If this app is transitioning from foreground to
12016 // non-foreground, have it do a gc.
12017 scheduleAppGcLocked(app);
12018 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12019 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12020 // Likewise do a gc when an app is moving in to the
12021 // background (such as a service stopping).
12022 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012023 }
12024
12025 if (wasKeeping && !app.keeping) {
12026 // This app is no longer something we want to keep. Note
12027 // its current wake lock time to later know to kill it if
12028 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012029 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12030 synchronized (stats) {
12031 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12032 app.pid, SystemClock.elapsedRealtime());
12033 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012034 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012035 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012037 app.setRawAdj = app.curRawAdj;
12038 }
12039 if (adj != app.setAdj) {
12040 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012041 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012042 TAG, "Set app " + app.processName +
12043 " oom adj to " + adj);
12044 app.setAdj = adj;
12045 } else {
12046 return false;
12047 }
12048 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012049 if (app.setSchedGroup != app.curSchedGroup) {
12050 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012051 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012052 "Setting process group of " + app.processName
12053 + " to " + app.curSchedGroup);
12054 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012055 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012056 try {
12057 Process.setProcessGroup(app.pid, app.curSchedGroup);
12058 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012059 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012060 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012061 e.printStackTrace();
12062 } finally {
12063 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012064 }
12065 }
12066 if (false) {
12067 if (app.thread != null) {
12068 try {
12069 app.thread.setSchedulingGroup(app.curSchedGroup);
12070 } catch (RemoteException e) {
12071 }
12072 }
12073 }
12074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012075 }
12076
12077 return true;
12078 }
12079
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012080 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012081 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012082 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012083 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012084 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012085 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012086 }
12087 }
12088 return resumedActivity;
12089 }
12090
12091 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012092 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012093 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12094 int curAdj = app.curAdj;
12095 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12096 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12097
12098 mAdjSeq++;
12099
12100 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12101 if (res) {
12102 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12103 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12104 if (nowHidden != wasHidden) {
12105 // Changed to/from hidden state, so apps after it in the LRU
12106 // list may also be changed.
12107 updateOomAdjLocked();
12108 }
12109 }
12110 return res;
12111 }
12112
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012113 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012114 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012115 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012116 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12117
12118 if (false) {
12119 RuntimeException e = new RuntimeException();
12120 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012121 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012122 }
12123
12124 mAdjSeq++;
12125
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012126 // Let's determine how many processes we have running vs.
12127 // how many slots we have for background processes; we may want
12128 // to put multiple processes in a slot of there are enough of
12129 // them.
12130 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12131 int factor = (mLruProcesses.size()-4)/numSlots;
12132 if (factor < 1) factor = 1;
12133 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012134 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012136 // First try updating the OOM adjustment for each of the
12137 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012138 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012139 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12140 while (i > 0) {
12141 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012142 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012143 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012144 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012145 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012146 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012147 step++;
12148 if (step >= factor) {
12149 step = 0;
12150 curHiddenAdj++;
12151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012152 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012153 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012154 if (!app.killedBackground) {
12155 numHidden++;
12156 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012157 Slog.i(TAG, "No longer want " + app.processName
12158 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012159 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12160 app.processName, app.setAdj, "too many background");
12161 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012162 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012163 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012164 }
12165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012166 } else {
12167 didOomAdj = false;
12168 }
12169 }
12170
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012171 // If we return false, we will fall back on killing processes to
12172 // have a fixed limit. Do this if a limit has been requested; else
12173 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012174 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12175 }
12176
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012177 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012178 synchronized (this) {
12179 int i;
12180
12181 // First remove any unused application processes whose package
12182 // has been removed.
12183 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12184 final ProcessRecord app = mRemovedProcesses.get(i);
12185 if (app.activities.size() == 0
12186 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012187 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012188 TAG, "Exiting empty application process "
12189 + app.processName + " ("
12190 + (app.thread != null ? app.thread.asBinder() : null)
12191 + ")\n");
12192 if (app.pid > 0 && app.pid != MY_PID) {
12193 Process.killProcess(app.pid);
12194 } else {
12195 try {
12196 app.thread.scheduleExit();
12197 } catch (Exception e) {
12198 // Ignore exceptions.
12199 }
12200 }
12201 cleanUpApplicationRecordLocked(app, false, -1);
12202 mRemovedProcesses.remove(i);
12203
12204 if (app.persistent) {
12205 if (app.persistent) {
12206 addAppLocked(app.info);
12207 }
12208 }
12209 }
12210 }
12211
12212 // Now try updating the OOM adjustment for each of the
12213 // application processes based on their current state.
12214 // If the setOomAdj() API is not supported, then go with our
12215 // back-up plan...
12216 if (!updateOomAdjLocked()) {
12217
12218 // Count how many processes are running services.
12219 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012220 for (i=mLruProcesses.size()-1; i>=0; i--) {
12221 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012222
12223 if (app.persistent || app.services.size() != 0
12224 || app.curReceiver != null
12225 || app.persistentActivities > 0) {
12226 // Don't count processes holding services against our
12227 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012228 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012229 TAG, "Not trimming app " + app + " with services: "
12230 + app.services);
12231 numServiceProcs++;
12232 }
12233 }
12234
12235 int curMaxProcs = mProcessLimit;
12236 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12237 if (mAlwaysFinishActivities) {
12238 curMaxProcs = 1;
12239 }
12240 curMaxProcs += numServiceProcs;
12241
12242 // Quit as many processes as we can to get down to the desired
12243 // process count. First remove any processes that no longer
12244 // have activites running in them.
12245 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012246 i<mLruProcesses.size()
12247 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012248 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012249 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012250 // Quit an application only if it is not currently
12251 // running any activities.
12252 if (!app.persistent && app.activities.size() == 0
12253 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012254 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012255 TAG, "Exiting empty application process "
12256 + app.processName + " ("
12257 + (app.thread != null ? app.thread.asBinder() : null)
12258 + ")\n");
12259 if (app.pid > 0 && app.pid != MY_PID) {
12260 Process.killProcess(app.pid);
12261 } else {
12262 try {
12263 app.thread.scheduleExit();
12264 } catch (Exception e) {
12265 // Ignore exceptions.
12266 }
12267 }
12268 // todo: For now we assume the application is not buggy
12269 // or evil, and will quit as a result of our request.
12270 // Eventually we need to drive this off of the death
12271 // notification, and kill the process if it takes too long.
12272 cleanUpApplicationRecordLocked(app, false, i);
12273 i--;
12274 }
12275 }
12276
12277 // If we still have too many processes, now from the least
12278 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012279 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012280 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012281 " of " + curMaxProcs + " processes");
12282 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012283 i<mLruProcesses.size()
12284 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012285 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012286 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012287 // Quit the application only if we have a state saved for
12288 // all of its activities.
12289 boolean canQuit = !app.persistent && app.curReceiver == null
12290 && app.services.size() == 0
12291 && app.persistentActivities == 0;
12292 int NUMA = app.activities.size();
12293 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012294 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012295 TAG, "Looking to quit " + app.processName);
12296 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012297 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012298 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012299 TAG, " " + r.intent.getComponent().flattenToShortString()
12300 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12301 canQuit = (r.haveState || !r.stateNotNeeded)
12302 && !r.visible && r.stopped;
12303 }
12304 if (canQuit) {
12305 // Finish all of the activities, and then the app itself.
12306 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012307 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012309 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012310 }
12311 r.resultTo = null;
12312 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012313 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012314 + app.processName + " ("
12315 + (app.thread != null ? app.thread.asBinder() : null)
12316 + ")\n");
12317 if (app.pid > 0 && app.pid != MY_PID) {
12318 Process.killProcess(app.pid);
12319 } else {
12320 try {
12321 app.thread.scheduleExit();
12322 } catch (Exception e) {
12323 // Ignore exceptions.
12324 }
12325 }
12326 // todo: For now we assume the application is not buggy
12327 // or evil, and will quit as a result of our request.
12328 // Eventually we need to drive this off of the death
12329 // notification, and kill the process if it takes too long.
12330 cleanUpApplicationRecordLocked(app, false, i);
12331 i--;
12332 //dump();
12333 }
12334 }
12335
12336 }
12337
12338 int curMaxActivities = MAX_ACTIVITIES;
12339 if (mAlwaysFinishActivities) {
12340 curMaxActivities = 1;
12341 }
12342
12343 // Finally, if there are too many activities now running, try to
12344 // finish as many as we can to get back down to the limit.
12345 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012346 i<mMainStack.mLRUActivities.size()
12347 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012348 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012349 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012350 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012351
12352 // We can finish this one if we have its icicle saved and
12353 // it is not persistent.
12354 if ((r.haveState || !r.stateNotNeeded) && !r.visible
12355 && r.stopped && !r.persistent && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012356 final int origSize = mMainStack.mLRUActivities.size();
12357 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012358
12359 // This will remove it from the LRU list, so keep
12360 // our index at the same value. Note that this check to
12361 // see if the size changes is just paranoia -- if
12362 // something unexpected happens, we don't want to end up
12363 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012364 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012365 i--;
12366 }
12367 }
12368 }
12369 }
12370 }
12371
12372 /** This method sends the specified signal to each of the persistent apps */
12373 public void signalPersistentProcesses(int sig) throws RemoteException {
12374 if (sig != Process.SIGNAL_USR1) {
12375 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12376 }
12377
12378 synchronized (this) {
12379 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12380 != PackageManager.PERMISSION_GRANTED) {
12381 throw new SecurityException("Requires permission "
12382 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12383 }
12384
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012385 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12386 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012387 if (r.thread != null && r.persistent) {
12388 Process.sendSignal(r.pid, sig);
12389 }
12390 }
12391 }
12392 }
12393
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012394 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012395 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012396
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012397 try {
12398 synchronized (this) {
12399 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12400 // its own permission.
12401 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12402 != PackageManager.PERMISSION_GRANTED) {
12403 throw new SecurityException("Requires permission "
12404 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012405 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012406
12407 if (start && fd == null) {
12408 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012409 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012410
12411 ProcessRecord proc = null;
12412 try {
12413 int pid = Integer.parseInt(process);
12414 synchronized (mPidsSelfLocked) {
12415 proc = mPidsSelfLocked.get(pid);
12416 }
12417 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012418 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012419
12420 if (proc == null) {
12421 HashMap<String, SparseArray<ProcessRecord>> all
12422 = mProcessNames.getMap();
12423 SparseArray<ProcessRecord> procs = all.get(process);
12424 if (procs != null && procs.size() > 0) {
12425 proc = procs.valueAt(0);
12426 }
12427 }
12428
12429 if (proc == null || proc.thread == null) {
12430 throw new IllegalArgumentException("Unknown process: " + process);
12431 }
12432
12433 boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
12434 if (isSecure) {
12435 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12436 throw new SecurityException("Process not debuggable: " + proc);
12437 }
12438 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012439
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012440 proc.thread.profilerControl(start, path, fd);
12441 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012442 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012443 }
12444 } catch (RemoteException e) {
12445 throw new IllegalStateException("Process disappeared");
12446 } finally {
12447 if (fd != null) {
12448 try {
12449 fd.close();
12450 } catch (IOException e) {
12451 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012452 }
12453 }
12454 }
12455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012456 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
12457 public void monitor() {
12458 synchronized (this) { }
12459 }
12460}